commit 83a46b2fc41459b46fed36364841a4af5ad99913 Author: B3ni Date: Mon Jun 16 15:24:27 2025 +0200 alap diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..efec83d --- /dev/null +++ b/.gitignore @@ -0,0 +1,74 @@ +# This .gitignore file should be placed at the root of your Unity project directory +# +# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore +# +.utmp/ +/[Ll]ibrary/ +/[Tt]emp/ +/[Oo]bj/ +/[Bb]uild/ +/[Bb]uilds/ +/[Ll]ogs/ +/[Uu]ser[Ss]ettings/ + +# MemoryCaptures can get excessive in size. +# They also could contain extremely sensitive data +/[Mm]emoryCaptures/ + +# Recordings can get excessive in size +/[Rr]ecordings/ + +# Uncomment this line if you wish to ignore the asset store tools plugin +# /[Aa]ssets/AssetStoreTools* + +# Autogenerated Jetbrains Rider plugin +/[Aa]ssets/Plugins/Editor/JetBrains* + +# Visual Studio cache directory +.vs/ + +# Gradle cache directory +.gradle/ + +# Autogenerated VS/MD/Consulo solution and project files +ExportedObj/ +.consulo/ +*.csproj +*.unityproj +*.sln +*.suo +*.tmp +*.user +*.userprefs +*.pidb +*.booproj +*.svd +*.pdb +*.mdb +*.opendb +*.VC.db + +# Unity3D generated meta files +*.pidb.meta +*.pdb.meta +*.mdb.meta + +# Unity3D generated file on crash reports +sysinfo.txt + +# Builds +*.apk +*.aab +*.unitypackage +*.unitypackage.meta +*.app + +# Crashlytics generated file +crashlytics-build.properties + +# Packed Addressables +/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* + +# Temporary auto-generated Android Assets +/[Aa]ssets/[Ss]treamingAssets/aa.meta +/[Aa]ssets/[Ss]treamingAssets/aa/* diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..ddb6ff8 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "visualstudiotoolsforunity.vstuc" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..da60e25 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,10 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to Unity", + "type": "vstuc", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f77a017 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,55 @@ +{ + "files.exclude": { + "**/.DS_Store": true, + "**/.git": true, + "**/.gitmodules": true, + "**/*.booproj": true, + "**/*.pidb": true, + "**/*.suo": true, + "**/*.user": true, + "**/*.userprefs": true, + "**/*.unityproj": true, + "**/*.dll": true, + "**/*.exe": true, + "**/*.pdf": true, + "**/*.mid": true, + "**/*.midi": true, + "**/*.wav": true, + "**/*.gif": true, + "**/*.ico": true, + "**/*.jpg": true, + "**/*.jpeg": true, + "**/*.png": true, + "**/*.psd": true, + "**/*.tga": true, + "**/*.tif": true, + "**/*.tiff": true, + "**/*.3ds": true, + "**/*.3DS": true, + "**/*.fbx": true, + "**/*.FBX": true, + "**/*.lxo": true, + "**/*.LXO": true, + "**/*.ma": true, + "**/*.MA": true, + "**/*.obj": true, + "**/*.OBJ": true, + "**/*.asset": true, + "**/*.cubemap": true, + "**/*.flare": true, + "**/*.mat": true, + "**/*.meta": true, + "**/*.prefab": true, + "**/*.unity": true, + "build/": true, + "Build/": true, + "Library/": true, + "library/": true, + "obj/": true, + "Obj/": true, + "ProjectSettings/": true, + "temp/": true, + "Temp/": true + }, + "dotnet.defaultSolution": "multiplayer-game.sln" +} \ No newline at end of file diff --git a/.vsconfig b/.vsconfig new file mode 100644 index 0000000..d70cd98 --- /dev/null +++ b/.vsconfig @@ -0,0 +1,6 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Workload.ManagedGame" + ] +} diff --git a/Assets/DefaultVolumeProfile.asset b/Assets/DefaultVolumeProfile.asset new file mode 100644 index 0000000..36c3781 --- /dev/null +++ b/Assets/DefaultVolumeProfile.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: DefaultVolumeProfile + m_EditorClassIdentifier: + components: [] diff --git a/Assets/DefaultVolumeProfile.asset.meta b/Assets/DefaultVolumeProfile.asset.meta new file mode 100644 index 0000000..bf08d80 --- /dev/null +++ b/Assets/DefaultVolumeProfile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4d700d2576e8690408c7f734564d78f7 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Materials.meta b/Assets/Materials.meta new file mode 100644 index 0000000..4537ddc --- /dev/null +++ b/Assets/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 38871691704490b4f8b7f99ba454f9c1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Materials/black.mat b/Assets/Materials/black.mat new file mode 100644 index 0000000..06d72b7 --- /dev/null +++ b/Assets/Materials/black.mat @@ -0,0 +1,135 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-5298968235196956465 +MonoBehaviour: + m_ObjectHideFlags: 11 + 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: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 9 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: black + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 0.122641504, g: 0.122641504, b: 0.122641504, a: 1} + - _Color: {r: 0.12264148, g: 0.12264148, b: 0.12264148, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/Materials/black.mat.meta b/Assets/Materials/black.mat.meta new file mode 100644 index 0000000..859b299 --- /dev/null +++ b/Assets/Materials/black.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c7ae0124944d0364984ad3872a6720f9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror.meta b/Assets/Mirror.meta new file mode 100644 index 0000000..a7a3dd0 --- /dev/null +++ b/Assets/Mirror.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5cf8eb36be0834b3da408c694a41cb88 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Authenticators.meta b/Assets/Mirror/Authenticators.meta new file mode 100644 index 0000000..644f4ec --- /dev/null +++ b/Assets/Mirror/Authenticators.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b2f9d254154cd942ba40b06b869b8f3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Authenticators/BasicAuthenticator.cs b/Assets/Mirror/Authenticators/BasicAuthenticator.cs new file mode 100644 index 0000000..3c077c7 --- /dev/null +++ b/Assets/Mirror/Authenticators/BasicAuthenticator.cs @@ -0,0 +1,192 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror.Authenticators +{ + [AddComponentMenu("Network/ Authenticators/Basic Authenticator")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-authenticators/basic-authenticator")] + public class BasicAuthenticator : NetworkAuthenticator + { + [Header("Server Credentials")] + public string serverUsername; + public string serverPassword; + + [Header("Client Credentials")] + public string username; + public string password; + + readonly HashSet connectionsPendingDisconnect = new HashSet(); + + #region Messages + + public struct AuthRequestMessage : NetworkMessage + { + // use whatever credentials make sense for your game + // for example, you might want to pass the accessToken if using oauth + public string authUsername; + public string authPassword; + } + + public struct AuthResponseMessage : NetworkMessage + { + public byte code; + public string message; + } + + #endregion + + #region Server + + /// + /// Called on server from StartServer to initialize the Authenticator + /// Server message handlers should be registered in this method. + /// + public override void OnStartServer() + { + // register a handler for the authentication request we expect from client + NetworkServer.RegisterHandler(OnAuthRequestMessage, false); + } + + /// + /// Called on server from StopServer to reset the Authenticator + /// Server message handlers should be unregistered in this method. + /// + public override void OnStopServer() + { + // unregister the handler for the authentication request + NetworkServer.UnregisterHandler(); + } + + /// + /// Called on server from OnServerConnectInternal when a client needs to authenticate + /// + /// Connection to client. + public override void OnServerAuthenticate(NetworkConnectionToClient conn) + { + // do nothing...wait for AuthRequestMessage from client + } + + /// + /// Called on server when the client's AuthRequestMessage arrives + /// + /// Connection to client. + /// The message payload + public void OnAuthRequestMessage(NetworkConnectionToClient conn, AuthRequestMessage msg) + { + //Debug.Log($"Authentication Request: {msg.authUsername} {msg.authPassword}"); + + if (connectionsPendingDisconnect.Contains(conn)) return; + + // check the credentials by calling your web server, database table, playfab api, or any method appropriate. + if (msg.authUsername == serverUsername && msg.authPassword == serverPassword) + { + // create and send msg to client so it knows to proceed + AuthResponseMessage authResponseMessage = new AuthResponseMessage + { + code = 100, + message = "Success" + }; + + conn.Send(authResponseMessage); + + // Accept the successful authentication + ServerAccept(conn); + } + else + { + connectionsPendingDisconnect.Add(conn); + + // create and send msg to client so it knows to disconnect + AuthResponseMessage authResponseMessage = new AuthResponseMessage + { + code = 200, + message = "Invalid Credentials" + }; + + conn.Send(authResponseMessage); + + // must set NetworkConnection isAuthenticated = false + conn.isAuthenticated = false; + + // disconnect the client after 1 second so that response message gets delivered + StartCoroutine(DelayedDisconnect(conn, 1f)); + } + } + + IEnumerator DelayedDisconnect(NetworkConnectionToClient conn, float waitTime) + { + yield return new WaitForSeconds(waitTime); + + // Reject the unsuccessful authentication + ServerReject(conn); + + yield return null; + + // remove conn from pending connections + connectionsPendingDisconnect.Remove(conn); + } + + #endregion + + #region Client + + /// + /// Called on client from StartClient to initialize the Authenticator + /// Client message handlers should be registered in this method. + /// + public override void OnStartClient() + { + // register a handler for the authentication response we expect from server + NetworkClient.RegisterHandler(OnAuthResponseMessage, false); + } + + /// + /// Called on client from StopClient to reset the Authenticator + /// Client message handlers should be unregistered in this method. + /// + public override void OnStopClient() + { + // unregister the handler for the authentication response + NetworkClient.UnregisterHandler(); + } + + /// + /// Called on client from OnClientConnectInternal when a client needs to authenticate + /// + public override void OnClientAuthenticate() + { + AuthRequestMessage authRequestMessage = new AuthRequestMessage + { + authUsername = username, + authPassword = password + }; + + NetworkClient.Send(authRequestMessage); + } + + /// + /// Called on client when the server's AuthResponseMessage arrives + /// + /// The message payload + public void OnAuthResponseMessage(AuthResponseMessage msg) + { + if (msg.code == 100) + { + //Debug.Log($"Authentication Response: {msg.message}"); + + // Authentication has been accepted + ClientAccept(); + } + else + { + Debug.LogError($"Authentication Response: {msg.message}"); + + // Authentication has been rejected + ClientReject(); + } + } + + #endregion + } +} diff --git a/Assets/Mirror/Authenticators/BasicAuthenticator.cs.meta b/Assets/Mirror/Authenticators/BasicAuthenticator.cs.meta new file mode 100644 index 0000000..4765013 --- /dev/null +++ b/Assets/Mirror/Authenticators/BasicAuthenticator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 28496b776660156428f00cf78289c1ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Authenticators/DeviceAuthenticator.cs b/Assets/Mirror/Authenticators/DeviceAuthenticator.cs new file mode 100644 index 0000000..5e0ea56 --- /dev/null +++ b/Assets/Mirror/Authenticators/DeviceAuthenticator.cs @@ -0,0 +1,129 @@ +using System; +using UnityEngine; + +namespace Mirror.Authenticators +{ + /// + /// An authenticator that identifies the user by their device. + /// A GUID is used as a fallback when the platform doesn't support SystemInfo.deviceUniqueIdentifier. + /// Note: deviceUniqueIdentifier can be spoofed, so security is not guaranteed. + /// See https://docs.unity3d.com/ScriptReference/SystemInfo-deviceUniqueIdentifier.html for details. + /// + [AddComponentMenu("Network/ Authenticators/Device Authenticator")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-authenticators/device-authenticator")] + public class DeviceAuthenticator : NetworkAuthenticator + { + #region Messages + + public struct AuthRequestMessage : NetworkMessage + { + public string clientDeviceID; + } + + public struct AuthResponseMessage : NetworkMessage { } + + #endregion + + #region Server + + /// + /// Called on server from StartServer to initialize the Authenticator + /// Server message handlers should be registered in this method. + /// + public override void OnStartServer() + { + // register a handler for the authentication request we expect from client + NetworkServer.RegisterHandler(OnAuthRequestMessage, false); + } + + /// + /// Called on server from StopServer to reset the Authenticator + /// Server message handlers should be registered in this method. + /// + public override void OnStopServer() + { + // unregister the handler for the authentication request + NetworkServer.UnregisterHandler(); + } + + /// + /// Called on server from OnServerConnectInternal when a client needs to authenticate + /// + /// Connection to client. + public override void OnServerAuthenticate(NetworkConnectionToClient conn) + { + // do nothing, wait for client to send his id + } + + void OnAuthRequestMessage(NetworkConnectionToClient conn, AuthRequestMessage msg) + { + Debug.Log($"connection {conn.connectionId} authenticated with id {msg.clientDeviceID}"); + + // Store the device id for later reference, e.g. when spawning the player + conn.authenticationData = msg.clientDeviceID; + + // Send a response to client telling it to proceed as authenticated + conn.Send(new AuthResponseMessage()); + + // Accept the successful authentication + ServerAccept(conn); + } + + #endregion + + #region Client + + /// + /// Called on client from StartClient to initialize the Authenticator + /// Client message handlers should be registered in this method. + /// + public override void OnStartClient() + { + // register a handler for the authentication response we expect from server + NetworkClient.RegisterHandler(OnAuthResponseMessage, false); + } + + /// + /// Called on client from StopClient to reset the Authenticator + /// Client message handlers should be unregistered in this method. + /// + public override void OnStopClient() + { + // unregister the handler for the authentication response + NetworkClient.UnregisterHandler(); + } + + /// + /// Called on client from OnClientConnectInternal when a client needs to authenticate + /// + public override void OnClientAuthenticate() + { + string deviceUniqueIdentifier = SystemInfo.deviceUniqueIdentifier; + + // Not all platforms support this, so we use a GUID instead + if (deviceUniqueIdentifier == SystemInfo.unsupportedIdentifier) + { + // Get the value from PlayerPrefs if it exists, new GUID if it doesn't + deviceUniqueIdentifier = PlayerPrefs.GetString("deviceUniqueIdentifier", Guid.NewGuid().ToString()); + + // Store the deviceUniqueIdentifier to PlayerPrefs (in case we just made a new GUID) + PlayerPrefs.SetString("deviceUniqueIdentifier", deviceUniqueIdentifier); + } + + // send the deviceUniqueIdentifier to the server + NetworkClient.Send(new AuthRequestMessage { clientDeviceID = deviceUniqueIdentifier } ); + } + + /// + /// Called on client when the server's AuthResponseMessage arrives + /// + /// The message payload + public void OnAuthResponseMessage(AuthResponseMessage msg) + { + Debug.Log("Authentication Success"); + ClientAccept(); + } + + #endregion + } +} diff --git a/Assets/Mirror/Authenticators/DeviceAuthenticator.cs.meta b/Assets/Mirror/Authenticators/DeviceAuthenticator.cs.meta new file mode 100644 index 0000000..9ca9f64 --- /dev/null +++ b/Assets/Mirror/Authenticators/DeviceAuthenticator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 60960a6ba81a842deb2fdcdc93788242 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Authenticators/Mirror.Authenticators.asmdef b/Assets/Mirror/Authenticators/Mirror.Authenticators.asmdef new file mode 100644 index 0000000..70eacf3 --- /dev/null +++ b/Assets/Mirror/Authenticators/Mirror.Authenticators.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Mirror.Authenticators", + "rootNamespace": "", + "references": [ + "GUID:30817c1a0e6d646d99c048fc403f5979" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Authenticators/Mirror.Authenticators.asmdef.meta b/Assets/Mirror/Authenticators/Mirror.Authenticators.asmdef.meta new file mode 100644 index 0000000..2731701 --- /dev/null +++ b/Assets/Mirror/Authenticators/Mirror.Authenticators.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e720aa64e3f58fb4880566a322584340 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Authenticators/TimeoutAuthenticator.cs b/Assets/Mirror/Authenticators/TimeoutAuthenticator.cs new file mode 100644 index 0000000..711ee6e --- /dev/null +++ b/Assets/Mirror/Authenticators/TimeoutAuthenticator.cs @@ -0,0 +1,70 @@ +using System.Collections; +using UnityEngine; + +namespace Mirror.Authenticators +{ + /// + /// An authenticator that disconnects connections if they don't + /// authenticate within a specified time limit. + /// + [AddComponentMenu("Network/ Authenticators/Timeout Authenticator")] + public class TimeoutAuthenticator : NetworkAuthenticator + { + public NetworkAuthenticator authenticator; + + [Range(0, 600), Tooltip("Timeout to auto-disconnect in seconds. Set to 0 for no timeout.")] + public float timeout = 60; + + public void Awake() + { + authenticator.OnServerAuthenticated.AddListener(connection => OnServerAuthenticated.Invoke(connection)); + authenticator.OnClientAuthenticated.AddListener(OnClientAuthenticated.Invoke); + } + + public override void OnStartServer() + { + authenticator.OnStartServer(); + } + + public override void OnStopServer() + { + authenticator.OnStopServer(); + } + + public override void OnStartClient() + { + authenticator.OnStartClient(); + } + + public override void OnStopClient() + { + authenticator.OnStopClient(); + } + + public override void OnServerAuthenticate(NetworkConnectionToClient conn) + { + authenticator.OnServerAuthenticate(conn); + if (timeout > 0) + StartCoroutine(BeginAuthentication(conn)); + } + + public override void OnClientAuthenticate() + { + authenticator.OnClientAuthenticate(); + if (timeout > 0) + StartCoroutine(BeginAuthentication(NetworkClient.connection)); + } + + IEnumerator BeginAuthentication(NetworkConnection conn) + { + //Debug.Log($"Authentication countdown started {conn} {timeout}"); + yield return new WaitForSecondsRealtime(timeout); + + if (!conn.isAuthenticated) + { + Debug.LogError($"Authentication Timeout - Disconnecting {conn}"); + conn.Disconnect(); + } + } + } +} diff --git a/Assets/Mirror/Authenticators/TimeoutAuthenticator.cs.meta b/Assets/Mirror/Authenticators/TimeoutAuthenticator.cs.meta new file mode 100644 index 0000000..b19ddec --- /dev/null +++ b/Assets/Mirror/Authenticators/TimeoutAuthenticator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24d8269a07b8e4edfa374753a91c946e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/CompilerSymbols.meta b/Assets/Mirror/CompilerSymbols.meta new file mode 100644 index 0000000..4652ae1 --- /dev/null +++ b/Assets/Mirror/CompilerSymbols.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f8b918bcd89f5c488b06f5574f34760 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef b/Assets/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef new file mode 100644 index 0000000..af25622 --- /dev/null +++ b/Assets/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef @@ -0,0 +1,14 @@ +{ + "name": "Mirror.CompilerSymbols", + "references": [], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef.meta b/Assets/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef.meta new file mode 100644 index 0000000..8b23823 --- /dev/null +++ b/Assets/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 325984b52e4128546bc7558552f8b1d2 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/CompilerSymbols/PreprocessorDefine.cs b/Assets/Mirror/CompilerSymbols/PreprocessorDefine.cs new file mode 100644 index 0000000..79775a7 --- /dev/null +++ b/Assets/Mirror/CompilerSymbols/PreprocessorDefine.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using UnityEditor; + +namespace Mirror +{ + static class PreprocessorDefine + { + /// + /// Add define symbols as soon as Unity gets done compiling. + /// + [InitializeOnLoadMethod] + public static void AddDefineSymbols() + { +#if UNITY_2021_2_OR_NEWER + string currentDefines = PlayerSettings.GetScriptingDefineSymbols(UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(EditorUserBuildSettings.selectedBuildTargetGroup)); +#else + // Deprecated in Unity 2023.1 + string currentDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup); +#endif + // Remove oldest when adding next month's symbol. + // Keep a rolling 12 months of symbols. + HashSet defines = new HashSet(currentDefines.Split(';')) + { + "MIRROR", + "MIRROR_79_OR_NEWER", + "MIRROR_81_OR_NEWER", + "MIRROR_82_OR_NEWER", + "MIRROR_83_OR_NEWER", + "MIRROR_84_OR_NEWER", + "MIRROR_85_OR_NEWER", + "MIRROR_86_OR_NEWER", + "MIRROR_89_OR_NEWER" + }; + + // only touch PlayerSettings if we actually modified it, + // otherwise it shows up as changed in git each time. + string newDefines = string.Join(";", defines); + if (newDefines != currentDefines) + { +#if UNITY_2021_2_OR_NEWER + PlayerSettings.SetScriptingDefineSymbols(UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(EditorUserBuildSettings.selectedBuildTargetGroup), newDefines); +#else + // Deprecated in Unity 2023.1 + PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, newDefines); +#endif + } + } + } +} diff --git a/Assets/Mirror/CompilerSymbols/PreprocessorDefine.cs.meta b/Assets/Mirror/CompilerSymbols/PreprocessorDefine.cs.meta new file mode 100644 index 0000000..6306c16 --- /dev/null +++ b/Assets/Mirror/CompilerSymbols/PreprocessorDefine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f1d66fe74ec6f42dd974cba37d25d453 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components.meta b/Assets/Mirror/Components.meta new file mode 100644 index 0000000..c2771d9 --- /dev/null +++ b/Assets/Mirror/Components.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9bee879fbc8ef4b1a9a9f7088bfbf726 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/AssemblyInfo.cs b/Assets/Mirror/Components/AssemblyInfo.cs new file mode 100644 index 0000000..f342716 --- /dev/null +++ b/Assets/Mirror/Components/AssemblyInfo.cs @@ -0,0 +1,12 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Mirror.Tests.Common")] +[assembly: InternalsVisibleTo("Mirror.Tests")] +// need to use Unity.*.CodeGen assembly name to import Unity.CompilationPipeline +// for ILPostProcessor tests. +[assembly: InternalsVisibleTo("Unity.Mirror.Tests.CodeGen")] +[assembly: InternalsVisibleTo("Mirror.Tests.Generated")] +[assembly: InternalsVisibleTo("Mirror.Tests.Runtime")] +[assembly: InternalsVisibleTo("Mirror.Tests.Performance.Editor")] +[assembly: InternalsVisibleTo("Mirror.Tests.Performance.Runtime")] +[assembly: InternalsVisibleTo("Mirror.Editor")] diff --git a/Assets/Mirror/Components/AssemblyInfo.cs.meta b/Assets/Mirror/Components/AssemblyInfo.cs.meta new file mode 100644 index 0000000..f9af1fa --- /dev/null +++ b/Assets/Mirror/Components/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a65b9283f7a724e70b8e17cb277f4c1e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Discovery.meta b/Assets/Mirror/Components/Discovery.meta new file mode 100644 index 0000000..d5bb0cb --- /dev/null +++ b/Assets/Mirror/Components/Discovery.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b5dcf9618f5e14a4eb60bff5480284a6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Discovery/NetworkDiscovery.cs b/Assets/Mirror/Components/Discovery/NetworkDiscovery.cs new file mode 100644 index 0000000..5fa9397 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/NetworkDiscovery.cs @@ -0,0 +1,93 @@ +using System; +using System.Net; +using UnityEngine; +using UnityEngine.Events; + +namespace Mirror.Discovery +{ + [Serializable] + public class ServerFoundUnityEvent : UnityEvent {}; + + [DisallowMultipleComponent] + [AddComponentMenu("Network/Network Discovery")] + public class NetworkDiscovery : NetworkDiscoveryBase + { + #region Server + + /// + /// Process the request from a client + /// + /// + /// Override if you wish to provide more information to the clients + /// such as the name of the host player + /// + /// Request coming from client + /// Address of the client that sent the request + /// The message to be sent back to the client or null + protected override ServerResponse ProcessRequest(ServerRequest request, IPEndPoint endpoint) + { + // In this case we don't do anything with the request + // but other discovery implementations might want to use the data + // in there, This way the client can ask for + // specific game mode or something + + try + { + // this is an example reply message, return your own + // to include whatever is relevant for your game + return new ServerResponse + { + serverId = ServerId, + uri = transport.ServerUri() + }; + } + catch (NotImplementedException) + { + Debug.LogError($"Transport {transport} does not support network discovery"); + throw; + } + } + + #endregion + + #region Client + + /// + /// Create a message that will be broadcasted on the network to discover servers + /// + /// + /// Override if you wish to include additional data in the discovery message + /// such as desired game mode, language, difficulty, etc... + /// An instance of ServerRequest with data to be broadcasted + protected override ServerRequest GetRequest() => new ServerRequest(); + + /// + /// Process the answer from a server + /// + /// + /// A client receives a reply from a server, this method processes the + /// reply and raises an event + /// + /// Response that came from the server + /// Address of the server that replied + protected override void ProcessResponse(ServerResponse response, IPEndPoint endpoint) + { + // we received a message from the remote endpoint + response.EndPoint = endpoint; + + // although we got a supposedly valid url, we may not be able to resolve + // the provided host + // However we know the real ip address of the server because we just + // received a packet from it, so use that as host. + UriBuilder realUri = new UriBuilder(response.uri) + { + Host = response.EndPoint.Address.ToString() + }; + response.uri = realUri.Uri; + + OnServerFound.Invoke(response); + } + + #endregion + } +} diff --git a/Assets/Mirror/Components/Discovery/NetworkDiscovery.cs.meta b/Assets/Mirror/Components/Discovery/NetworkDiscovery.cs.meta new file mode 100644 index 0000000..c691a61 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/NetworkDiscovery.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c761308e733c51245b2e8bb4201f46dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs b/Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs new file mode 100644 index 0000000..4417344 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs @@ -0,0 +1,470 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading.Tasks; +using UnityEngine; + +// Based on https://github.com/EnlightenedOne/MirrorNetworkDiscovery +// forked from https://github.com/in0finite/MirrorNetworkDiscovery +// Both are MIT Licensed + +namespace Mirror.Discovery +{ + /// + /// Base implementation for Network Discovery. Extend this component + /// to provide custom discovery with game specific data + /// NetworkDiscovery for a sample implementation + /// + [DisallowMultipleComponent] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-discovery")] + public abstract class NetworkDiscoveryBase : MonoBehaviour + where Request : NetworkMessage + where Response : NetworkMessage + { + public static bool SupportedOnThisPlatform { get { return Application.platform != RuntimePlatform.WebGLPlayer; } } + + [SerializeField] + [Tooltip("If true, broadcasts a discovery request every ActiveDiscoveryInterval seconds")] + public bool enableActiveDiscovery = true; + + // broadcast address needs to be configurable on iOS: + // https://github.com/vis2k/Mirror/pull/3255 + [Tooltip("iOS may require LAN IP address here (e.g. 192.168.x.x), otherwise leave blank.")] + public string BroadcastAddress = ""; + + [SerializeField] + [Tooltip("The UDP port the server will listen for multi-cast messages")] + protected int serverBroadcastListenPort = 47777; + + [SerializeField] + [Tooltip("Time in seconds between multi-cast messages")] + [Range(1, 60)] + float ActiveDiscoveryInterval = 3; + + [Tooltip("Transport to be advertised during discovery")] + public Transport transport; + + [Tooltip("Invoked when a server is found")] + public ServerFoundUnityEvent OnServerFound; + + // Each game should have a random unique handshake, + // this way you can tell if this is the same game or not + [HideInInspector] + public long secretHandshake; + + public long ServerId { get; private set; } + + protected UdpClient serverUdpClient; + protected UdpClient clientUdpClient; + +#if UNITY_EDITOR + public virtual void OnValidate() + { + if (transport == null) + transport = GetComponent(); + + if (secretHandshake == 0) + { + secretHandshake = RandomLong(); + UnityEditor.Undo.RecordObject(this, "Set secret handshake"); + } + } +#endif + + /// + /// virtual so that inheriting classes' Start() can call base.Start() too + /// + public virtual void Start() + { + ServerId = RandomLong(); + + // active transport gets initialized in Awake + // so make sure we set it here in Start() after Awake + // Or just let the user assign it in the inspector + if (transport == null) + transport = Transport.active; + + // Server mode? then start advertising + if (Utils.IsHeadless()) + { + AdvertiseServer(); + } + } + + public static long RandomLong() + { + int value1 = UnityEngine.Random.Range(int.MinValue, int.MaxValue); + int value2 = UnityEngine.Random.Range(int.MinValue, int.MaxValue); + return value1 + ((long)value2 << 32); + } + + // Ensure the ports are cleared no matter when Game/Unity UI exits + void OnApplicationQuit() + { + //Debug.Log("NetworkDiscoveryBase OnApplicationQuit"); + Shutdown(); + } + + void OnDisable() + { + //Debug.Log("NetworkDiscoveryBase OnDisable"); + Shutdown(); + } + + void OnDestroy() + { + //Debug.Log("NetworkDiscoveryBase OnDestroy"); + Shutdown(); + } + + void Shutdown() + { + EndpMulticastLock(); + if (serverUdpClient != null) + { + try + { + serverUdpClient.Close(); + } + catch (Exception) + { + // it is just close, swallow the error + } + + serverUdpClient = null; + } + + if (clientUdpClient != null) + { + try + { + clientUdpClient.Close(); + } + catch (Exception) + { + // it is just close, swallow the error + } + + clientUdpClient = null; + } + + CancelInvoke(); + } + + #region Server + + /// + /// Advertise this server in the local network + /// + public void AdvertiseServer() + { + if (!SupportedOnThisPlatform) + throw new PlatformNotSupportedException("Network discovery not supported in this platform"); + + StopDiscovery(); + + // Setup port -- may throw exception + serverUdpClient = new UdpClient(serverBroadcastListenPort) + { + EnableBroadcast = true, + MulticastLoopback = false + }; + + // listen for client pings + _ = ServerListenAsync(); + } + + public async Task ServerListenAsync() + { + BeginMulticastLock(); + while (true) + { + try + { + await ReceiveRequestAsync(serverUdpClient); + } + catch (ObjectDisposedException) + { + // socket has been closed + break; + } + catch (Exception) {} + } + } + + async Task ReceiveRequestAsync(UdpClient udpClient) + { + // only proceed if there is available data in network buffer, or otherwise Receive() will block + // average time for UdpClient.Available : 10 us + + UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync(); + + using (NetworkReaderPooled networkReader = NetworkReaderPool.Get(udpReceiveResult.Buffer)) + { + long handshake = networkReader.ReadLong(); + if (handshake != secretHandshake) + { + // message is not for us + throw new ProtocolViolationException("Invalid handshake"); + } + + Request request = networkReader.Read(); + + ProcessClientRequest(request, udpReceiveResult.RemoteEndPoint); + } + } + + /// + /// Reply to the client to inform it of this server + /// + /// + /// Override if you wish to ignore server requests based on + /// custom criteria such as language, full server game mode or difficulty + /// + /// Request coming from client + /// Address of the client that sent the request + protected virtual void ProcessClientRequest(Request request, IPEndPoint endpoint) + { + Response info = ProcessRequest(request, endpoint); + + if (info == null) + return; + + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + try + { + writer.WriteLong(secretHandshake); + + writer.Write(info); + + ArraySegment data = writer.ToArraySegment(); + // signature matches + // send response + serverUdpClient.Send(data.Array, data.Count, endpoint); + } + catch (Exception ex) + { + Debug.LogException(ex, this); + } + } + } + + /// + /// Process the request from a client + /// + /// + /// Override if you wish to provide more information to the clients + /// such as the name of the host player + /// + /// Request coming from client + /// Address of the client that sent the request + /// The message to be sent back to the client or null + protected abstract Response ProcessRequest(Request request, IPEndPoint endpoint); + + // Android Multicast fix: https://github.com/vis2k/Mirror/pull/2887 +#if UNITY_ANDROID + AndroidJavaObject multicastLock; + bool hasMulticastLock; +#endif + + void BeginMulticastLock() + { +#if UNITY_ANDROID + if (hasMulticastLock) return; + + if (Application.platform == RuntimePlatform.Android) + { + using (AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic("currentActivity")) + { + using (var wifiManager = activity.Call("getSystemService", "wifi")) + { + multicastLock = wifiManager.Call("createMulticastLock", "lock"); + multicastLock.Call("acquire"); + hasMulticastLock = true; + } + } + } +#endif + } + + void EndpMulticastLock() + { +#if UNITY_ANDROID + if (!hasMulticastLock) return; + + multicastLock?.Call("release"); + hasMulticastLock = false; +#endif + } + +#endregion + + #region Client + + /// + /// Start Active Discovery + /// + public void StartDiscovery() + { + if (!SupportedOnThisPlatform) + throw new PlatformNotSupportedException("Network discovery not supported in this platform"); + + StopDiscovery(); + + try + { + // Setup port + clientUdpClient = new UdpClient(0) + { + EnableBroadcast = true, + MulticastLoopback = false + }; + } + catch (Exception) + { + // Free the port if we took it + //Debug.LogError("NetworkDiscoveryBase StartDiscovery Exception"); + Shutdown(); + throw; + } + + _ = ClientListenAsync(); + + if (enableActiveDiscovery) InvokeRepeating(nameof(BroadcastDiscoveryRequest), 0, ActiveDiscoveryInterval); + } + + /// + /// Stop Active Discovery + /// + public void StopDiscovery() + { + //Debug.Log("NetworkDiscoveryBase StopDiscovery"); + Shutdown(); + } + + /// + /// Awaits for server response + /// + /// ClientListenAsync Task + public async Task ClientListenAsync() + { + // while clientUpdClient to fix: + // https://github.com/vis2k/Mirror/pull/2908 + // + // If, you cancel discovery the clientUdpClient is set to null. + // However, nothing cancels ClientListenAsync. If we change the if(true) + // to check if the client is null. You can properly cancel the discovery, + // and kill the listen thread. + // + // Prior to this fix, if you cancel the discovery search. It crashes the + // thread, and is super noisy in the output. As well as causes issues on + // the quest. + while (clientUdpClient != null) + { + try + { + await ReceiveGameBroadcastAsync(clientUdpClient); + } + catch (ObjectDisposedException) + { + // socket was closed, no problem + return; + } + catch (Exception ex) + { + Debug.LogException(ex); + } + } + } + + /// + /// Sends discovery request from client + /// + public void BroadcastDiscoveryRequest() + { + if (clientUdpClient == null) + return; + + if (NetworkClient.isConnected) + { + StopDiscovery(); + return; + } + + IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, serverBroadcastListenPort); + + if (!string.IsNullOrWhiteSpace(BroadcastAddress)) + { + try + { + endPoint = new IPEndPoint(IPAddress.Parse(BroadcastAddress), serverBroadcastListenPort); + } + catch (Exception ex) + { + Debug.LogException(ex); + } + } + + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + writer.WriteLong(secretHandshake); + + try + { + Request request = GetRequest(); + + writer.Write(request); + + ArraySegment data = writer.ToArraySegment(); + + clientUdpClient.SendAsync(data.Array, data.Count, endPoint); + } + catch (Exception) + { + // It is ok if we can't broadcast to one of the addresses + } + } + } + + /// + /// Create a message that will be broadcasted on the network to discover servers + /// + /// + /// Override if you wish to include additional data in the discovery message + /// such as desired game mode, language, difficulty, etc... + /// An instance of ServerRequest with data to be broadcasted + protected virtual Request GetRequest() => default; + + async Task ReceiveGameBroadcastAsync(UdpClient udpClient) + { + // only proceed if there is available data in network buffer, or otherwise Receive() will block + // average time for UdpClient.Available : 10 us + + UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync(); + + using (NetworkReaderPooled networkReader = NetworkReaderPool.Get(udpReceiveResult.Buffer)) + { + if (networkReader.ReadLong() != secretHandshake) + return; + + Response response = networkReader.Read(); + + ProcessResponse(response, udpReceiveResult.RemoteEndPoint); + } + } + + /// + /// Process the answer from a server + /// + /// + /// A client receives a reply from a server, this method processes the + /// reply and raises an event + /// + /// Response that came from the server + /// Address of the server that replied + protected abstract void ProcessResponse(Response response, IPEndPoint endpoint); + + #endregion + } +} diff --git a/Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs.meta b/Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs.meta new file mode 100644 index 0000000..fecf845 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9971d60ce61f4e39b07cd9e7e0c68fa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs b/Assets/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs new file mode 100644 index 0000000..e43c3d7 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror.Discovery +{ + [DisallowMultipleComponent] + [AddComponentMenu("Network/Network Discovery HUD")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-discovery")] + [RequireComponent(typeof(NetworkDiscovery))] + public class NetworkDiscoveryHUD : MonoBehaviour + { + readonly Dictionary discoveredServers = new Dictionary(); + Vector2 scrollViewPos = Vector2.zero; + + public NetworkDiscovery networkDiscovery; + +#if UNITY_EDITOR + void OnValidate() + { + if (networkDiscovery == null) + { + networkDiscovery = GetComponent(); + UnityEditor.Events.UnityEventTools.AddPersistentListener(networkDiscovery.OnServerFound, OnDiscoveredServer); + UnityEditor.Undo.RecordObjects(new Object[] { this, networkDiscovery }, "Set NetworkDiscovery"); + } + } +#endif + + void OnGUI() + { + if (NetworkManager.singleton == null) + return; + + if (!NetworkClient.isConnected && !NetworkServer.active && !NetworkClient.active) + DrawGUI(); + + if (NetworkServer.active || NetworkClient.active) + StopButtons(); + } + + void DrawGUI() + { + GUILayout.BeginArea(new Rect(10, 10, 300, 500)); + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("Find Servers")) + { + discoveredServers.Clear(); + networkDiscovery.StartDiscovery(); + } + + // LAN Host + if (GUILayout.Button("Start Host")) + { + discoveredServers.Clear(); + NetworkManager.singleton.StartHost(); + networkDiscovery.AdvertiseServer(); + } + + // Dedicated server + if (GUILayout.Button("Start Server")) + { + discoveredServers.Clear(); + NetworkManager.singleton.StartServer(); + networkDiscovery.AdvertiseServer(); + } + + GUILayout.EndHorizontal(); + + // show list of found server + + GUILayout.Label($"Discovered Servers [{discoveredServers.Count}]:"); + + // servers + scrollViewPos = GUILayout.BeginScrollView(scrollViewPos); + + foreach (ServerResponse info in discoveredServers.Values) + if (GUILayout.Button(info.EndPoint.Address.ToString())) + Connect(info); + + GUILayout.EndScrollView(); + GUILayout.EndArea(); + } + + void StopButtons() + { + GUILayout.BeginArea(new Rect(10, 40, 100, 25)); + + // stop host if host mode + if (NetworkServer.active && NetworkClient.isConnected) + { + if (GUILayout.Button("Stop Host")) + { + NetworkManager.singleton.StopHost(); + networkDiscovery.StopDiscovery(); + } + } + // stop client if client-only + else if (NetworkClient.isConnected) + { + if (GUILayout.Button("Stop Client")) + { + NetworkManager.singleton.StopClient(); + networkDiscovery.StopDiscovery(); + } + } + // stop server if server-only + else if (NetworkServer.active) + { + if (GUILayout.Button("Stop Server")) + { + NetworkManager.singleton.StopServer(); + networkDiscovery.StopDiscovery(); + } + } + + GUILayout.EndArea(); + } + + void Connect(ServerResponse info) + { + networkDiscovery.StopDiscovery(); + NetworkManager.singleton.StartClient(info.uri); + } + + public void OnDiscoveredServer(ServerResponse info) + { + // Note that you can check the versioning to decide if you can connect to the server or not using this method + discoveredServers[info.serverId] = info; + } + } +} diff --git a/Assets/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs.meta b/Assets/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs.meta new file mode 100644 index 0000000..f93b275 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 88c37d3deca7a834d80cfd8d3cfcc510 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Discovery/ServerRequest.cs b/Assets/Mirror/Components/Discovery/ServerRequest.cs new file mode 100644 index 0000000..647b619 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/ServerRequest.cs @@ -0,0 +1,4 @@ +namespace Mirror.Discovery +{ + public struct ServerRequest : NetworkMessage {} +} diff --git a/Assets/Mirror/Components/Discovery/ServerRequest.cs.meta b/Assets/Mirror/Components/Discovery/ServerRequest.cs.meta new file mode 100644 index 0000000..a7e246c --- /dev/null +++ b/Assets/Mirror/Components/Discovery/ServerRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ea7254bf7b9454da4adad881d94cd141 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Discovery/ServerResponse.cs b/Assets/Mirror/Components/Discovery/ServerResponse.cs new file mode 100644 index 0000000..7465783 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/ServerResponse.cs @@ -0,0 +1,18 @@ +using System; +using System.Net; + +namespace Mirror.Discovery +{ + public struct ServerResponse : NetworkMessage + { + // The server that sent this + // this is a property so that it is not serialized, but the + // client fills this up after we receive it + public IPEndPoint EndPoint { get; set; } + + public Uri uri; + + // Prevent duplicate server appearance when a connection can be made via LAN on multiple NICs + public long serverId; + } +} \ No newline at end of file diff --git a/Assets/Mirror/Components/Discovery/ServerResponse.cs.meta b/Assets/Mirror/Components/Discovery/ServerResponse.cs.meta new file mode 100644 index 0000000..239b218 --- /dev/null +++ b/Assets/Mirror/Components/Discovery/ServerResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 36f97227fdf2d7a4e902db5bfc43039c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Experimental.meta b/Assets/Mirror/Components/Experimental.meta new file mode 100644 index 0000000..57cce38 --- /dev/null +++ b/Assets/Mirror/Components/Experimental.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bfbf2a1f2b300c5489dcab219ef2846e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs b/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs new file mode 100644 index 0000000..adca7cb --- /dev/null +++ b/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs @@ -0,0 +1,97 @@ +using System; +using UnityEngine; + +namespace Mirror.Experimental +{ + [AddComponentMenu("Network/ Experimental/Network Lerp Rigidbody")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-lerp-rigidbody")] + [Obsolete("Use the new NetworkRigidbodyReliable/Unreliable component with Snapshot Interpolation instead.")] + public class NetworkLerpRigidbody : NetworkBehaviour + { + [Header("Settings")] + [SerializeField] internal Rigidbody target = null; + + [Tooltip("How quickly current velocity approaches target velocity")] + [SerializeField] float lerpVelocityAmount = 0.5f; + + [Tooltip("How quickly current position approaches target position")] + [SerializeField] float lerpPositionAmount = 0.5f; + + [Tooltip("Set to true if moves come from owner client, set to false if moves always come from server")] + [SerializeField] bool clientAuthority = false; + + double nextSyncTime; + + [SyncVar()] + Vector3 targetVelocity; + + [SyncVar()] + Vector3 targetPosition; + + /// + /// Ignore value if is host or client with Authority + /// + bool IgnoreSync => isServer || ClientWithAuthority; + + bool ClientWithAuthority => clientAuthority && isOwned; + + protected override void OnValidate() + { + base.OnValidate(); + Reset(); + } + + public virtual void Reset() + { + if (target == null) + target = GetComponent(); + + syncDirection = SyncDirection.ClientToServer; + } + + void Update() + { + if (isServer) + SyncToClients(); + else if (ClientWithAuthority) + SendToServer(); + } + + void SyncToClients() + { + targetVelocity = target.velocity; + targetPosition = target.position; + } + + void SendToServer() + { + double now = NetworkTime.localTime; // Unity 2019 doesn't have Time.timeAsDouble yet + if (now > nextSyncTime) + { + nextSyncTime = now + syncInterval; + CmdSendState(target.velocity, target.position); + } + } + + [Command] + void CmdSendState(Vector3 velocity, Vector3 position) + { + target.velocity = velocity; + target.position = position; + targetVelocity = velocity; + targetPosition = position; + } + + void FixedUpdate() + { + if (IgnoreSync) { return; } + + target.velocity = Vector3.Lerp(target.velocity, targetVelocity, lerpVelocityAmount); + target.position = Vector3.Lerp(target.position, targetPosition, lerpPositionAmount); + // add velocity to position as position would have moved on server at that velocity + target.position += target.velocity * Time.fixedDeltaTime; + + // TODO does this also need to sync acceleration so and update velocity? + } + } +} diff --git a/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs.meta b/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs.meta new file mode 100644 index 0000000..35ef1fe --- /dev/null +++ b/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f032128052c95a46afb0ddd97d994cc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs new file mode 100644 index 0000000..aa204ad --- /dev/null +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs @@ -0,0 +1,354 @@ +using System; +using UnityEngine; + +namespace Mirror.Experimental +{ + [AddComponentMenu("Network/ Experimental/Network Rigidbody")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-rigidbody")] + [Obsolete("Use the new NetworkRigidbodyReliable/Unreliable component with Snapshot Interpolation instead.")] + public class NetworkRigidbody : NetworkBehaviour + { + [Header("Settings")] + [SerializeField] internal Rigidbody target = null; + + [Tooltip("Set to true if moves come from owner client, set to false if moves always come from server")] + public bool clientAuthority = false; + + [Header("Velocity")] + [Tooltip("Syncs Velocity every SyncInterval")] + [SerializeField] bool syncVelocity = true; + + [Tooltip("Set velocity to 0 each frame (only works if syncVelocity is false")] + [SerializeField] bool clearVelocity = false; + + [Tooltip("Only Syncs Value if distance between previous and current is great than sensitivity")] + [SerializeField] float velocitySensitivity = 0.1f; + + [Header("Angular Velocity")] + [Tooltip("Syncs AngularVelocity every SyncInterval")] + [SerializeField] bool syncAngularVelocity = true; + + [Tooltip("Set angularVelocity to 0 each frame (only works if syncAngularVelocity is false")] + [SerializeField] bool clearAngularVelocity = false; + + [Tooltip("Only Syncs Value if distance between previous and current is great than sensitivity")] + [SerializeField] float angularVelocitySensitivity = 0.1f; + + /// + /// Values sent on client with authority after they are sent to the server + /// + readonly ClientSyncState previousValue = new ClientSyncState(); + + protected override void OnValidate() + { + base.OnValidate(); + Reset(); + } + + public virtual void Reset() + { + if (target == null) + target = GetComponent(); + + syncDirection = SyncDirection.ClientToServer; + } + + #region Sync vars + + [SyncVar(hook = nameof(OnVelocityChanged))] + Vector3 velocity; + + [SyncVar(hook = nameof(OnAngularVelocityChanged))] + Vector3 angularVelocity; + + [SyncVar(hook = nameof(OnIsKinematicChanged))] + bool isKinematic; + + [SyncVar(hook = nameof(OnUseGravityChanged))] + bool useGravity; + + [SyncVar(hook = nameof(OnuDragChanged))] + float drag; + + [SyncVar(hook = nameof(OnAngularDragChanged))] + float angularDrag; + + /// + /// Ignore value if is host or client with Authority + /// + /// + bool IgnoreSync => isServer || ClientWithAuthority; + + bool ClientWithAuthority => clientAuthority && isOwned; + + void OnVelocityChanged(Vector3 _, Vector3 newValue) + { + if (IgnoreSync) + return; + + target.velocity = newValue; + } + + void OnAngularVelocityChanged(Vector3 _, Vector3 newValue) + { + if (IgnoreSync) + return; + + target.angularVelocity = newValue; + } + + void OnIsKinematicChanged(bool _, bool newValue) + { + if (IgnoreSync) + return; + + target.isKinematic = newValue; + } + + void OnUseGravityChanged(bool _, bool newValue) + { + if (IgnoreSync) + return; + + target.useGravity = newValue; + } + + void OnuDragChanged(float _, float newValue) + { + if (IgnoreSync) + return; + + target.drag = newValue; + } + + void OnAngularDragChanged(float _, float newValue) + { + if (IgnoreSync) + return; + + target.angularDrag = newValue; + } + + #endregion + + internal void Update() + { + if (isServer) + SyncToClients(); + else if (ClientWithAuthority) + SendToServer(); + } + + internal void FixedUpdate() + { + if (clearAngularVelocity && !syncAngularVelocity) + target.angularVelocity = Vector3.zero; + + if (clearVelocity && !syncVelocity) + target.velocity = Vector3.zero; + } + + /// + /// Updates sync var values on server so that they sync to the client + /// + [Server] + void SyncToClients() + { + // only update if they have changed more than Sensitivity + + Vector3 currentVelocity = syncVelocity ? target.velocity : default; + Vector3 currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default; + + bool velocityChanged = syncVelocity && ((previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity); + bool angularVelocityChanged = syncAngularVelocity && ((previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity); + + if (velocityChanged) + { + velocity = currentVelocity; + previousValue.velocity = currentVelocity; + } + + if (angularVelocityChanged) + { + angularVelocity = currentAngularVelocity; + previousValue.angularVelocity = currentAngularVelocity; + } + + // other rigidbody settings + isKinematic = target.isKinematic; + useGravity = target.useGravity; + drag = target.drag; + angularDrag = target.angularDrag; + } + + /// + /// Uses Command to send values to server + /// + [Client] + void SendToServer() + { + if (!isOwned) + { + Debug.LogWarning("SendToServer called without authority"); + return; + } + + SendVelocity(); + SendRigidBodySettings(); + } + + [Client] + void SendVelocity() + { + double now = NetworkTime.localTime; // Unity 2019 doesn't have Time.timeAsDouble yet + if (now < previousValue.nextSyncTime) + return; + + Vector3 currentVelocity = syncVelocity ? target.velocity : default; + Vector3 currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default; + + bool velocityChanged = syncVelocity && ((previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity); + bool angularVelocityChanged = syncAngularVelocity && ((previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity); + + // if angularVelocity has changed it is likely that velocity has also changed so just sync both values + // however if only velocity has changed just send velocity + if (angularVelocityChanged) + { + CmdSendVelocityAndAngular(currentVelocity, currentAngularVelocity); + previousValue.velocity = currentVelocity; + previousValue.angularVelocity = currentAngularVelocity; + } + else if (velocityChanged) + { + CmdSendVelocity(currentVelocity); + previousValue.velocity = currentVelocity; + } + + + // only update syncTime if either has changed + if (angularVelocityChanged || velocityChanged) + previousValue.nextSyncTime = now + syncInterval; + } + + [Client] + void SendRigidBodySettings() + { + // These shouldn't change often so it is ok to send in their own Command + if (previousValue.isKinematic != target.isKinematic) + { + CmdSendIsKinematic(target.isKinematic); + previousValue.isKinematic = target.isKinematic; + } + if (previousValue.useGravity != target.useGravity) + { + CmdSendUseGravity(target.useGravity); + previousValue.useGravity = target.useGravity; + } + if (previousValue.drag != target.drag) + { + CmdSendDrag(target.drag); + previousValue.drag = target.drag; + } + if (previousValue.angularDrag != target.angularDrag) + { + CmdSendAngularDrag(target.angularDrag); + previousValue.angularDrag = target.angularDrag; + } + } + + /// + /// Called when only Velocity has changed on the client + /// + [Command] + void CmdSendVelocity(Vector3 velocity) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.velocity = velocity; + target.velocity = velocity; + } + + /// + /// Called when angularVelocity has changed on the client + /// + [Command] + void CmdSendVelocityAndAngular(Vector3 velocity, Vector3 angularVelocity) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + if (syncVelocity) + { + this.velocity = velocity; + target.velocity = velocity; + } + + this.angularVelocity = angularVelocity; + target.angularVelocity = angularVelocity; + } + + [Command] + void CmdSendIsKinematic(bool isKinematic) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.isKinematic = isKinematic; + target.isKinematic = isKinematic; + } + + [Command] + void CmdSendUseGravity(bool useGravity) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.useGravity = useGravity; + target.useGravity = useGravity; + } + + [Command] + void CmdSendDrag(float drag) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.drag = drag; + target.drag = drag; + } + + [Command] + void CmdSendAngularDrag(float angularDrag) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.angularDrag = angularDrag; + target.angularDrag = angularDrag; + } + + /// + /// holds previously synced values + /// + public class ClientSyncState + { + /// + /// Next sync time that velocity will be synced, based on syncInterval. + /// + public double nextSyncTime; + public Vector3 velocity; + public Vector3 angularVelocity; + public bool isKinematic; + public bool useGravity; + public float drag; + public float angularDrag; + } + } +} diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta new file mode 100644 index 0000000..1610f0a --- /dev/null +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 83392ae5c1b731446909f252fd494ae4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs b/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs new file mode 100644 index 0000000..ba68374 --- /dev/null +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs @@ -0,0 +1,349 @@ +using UnityEngine; + +namespace Mirror.Experimental +{ + [AddComponentMenu("Network/ Experimental/Network Rigidbody 2D")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-rigidbody")] + public class NetworkRigidbody2D : NetworkBehaviour + { + [Header("Settings")] + [SerializeField] internal Rigidbody2D target = null; + + [Tooltip("Set to true if moves come from owner client, set to false if moves always come from server")] + public bool clientAuthority = false; + + [Header("Velocity")] + [Tooltip("Syncs Velocity every SyncInterval")] + [SerializeField] bool syncVelocity = true; + + [Tooltip("Set velocity to 0 each frame (only works if syncVelocity is false")] + [SerializeField] bool clearVelocity = false; + + [Tooltip("Only Syncs Value if distance between previous and current is great than sensitivity")] + [SerializeField] float velocitySensitivity = 0.1f; + + [Header("Angular Velocity")] + [Tooltip("Syncs AngularVelocity every SyncInterval")] + [SerializeField] bool syncAngularVelocity = true; + + [Tooltip("Set angularVelocity to 0 each frame (only works if syncAngularVelocity is false")] + [SerializeField] bool clearAngularVelocity = false; + + [Tooltip("Only Syncs Value if distance between previous and current is great than sensitivity")] + [SerializeField] float angularVelocitySensitivity = 0.1f; + + /// + /// Values sent on client with authority after they are sent to the server + /// + readonly ClientSyncState previousValue = new ClientSyncState(); + + protected override void OnValidate() + { + base.OnValidate(); + Reset(); + } + + public virtual void Reset() + { + if (target == null) + target = GetComponent(); + + syncDirection = SyncDirection.ClientToServer; + } + + #region Sync vars + + [SyncVar(hook = nameof(OnVelocityChanged))] + Vector2 velocity; + + [SyncVar(hook = nameof(OnAngularVelocityChanged))] + float angularVelocity; + + [SyncVar(hook = nameof(OnIsKinematicChanged))] + bool isKinematic; + + [SyncVar(hook = nameof(OnGravityScaleChanged))] + float gravityScale; + + [SyncVar(hook = nameof(OnuDragChanged))] + float drag; + + [SyncVar(hook = nameof(OnAngularDragChanged))] + float angularDrag; + + /// + /// Ignore value if is host or client with Authority + /// + bool IgnoreSync => isServer || ClientWithAuthority; + + bool ClientWithAuthority => clientAuthority && isOwned; + + void OnVelocityChanged(Vector2 _, Vector2 newValue) + { + if (IgnoreSync) + return; + + target.linearVelocity = newValue; + } + + void OnAngularVelocityChanged(float _, float newValue) + { + if (IgnoreSync) + return; + + target.angularVelocity = newValue; + } + + void OnIsKinematicChanged(bool _, bool newValue) + { + if (IgnoreSync) + return; + + target.isKinematic = newValue; + } + + void OnGravityScaleChanged(float _, float newValue) + { + if (IgnoreSync) + return; + + target.gravityScale = newValue; + } + + void OnuDragChanged(float _, float newValue) + { + if (IgnoreSync) + return; + + target.linearDamping = newValue; + } + + void OnAngularDragChanged(float _, float newValue) + { + if (IgnoreSync) + return; + + target.angularDamping = newValue; + } + + #endregion + + internal void Update() + { + if (isServer) + SyncToClients(); + else if (ClientWithAuthority) + SendToServer(); + } + + internal void FixedUpdate() + { + if (clearAngularVelocity && !syncAngularVelocity) + target.angularVelocity = 0f; + + if (clearVelocity && !syncVelocity) + target.linearVelocity = Vector2.zero; + } + + /// + /// Updates sync var values on server so that they sync to the client + /// + [Server] + void SyncToClients() + { + // only update if they have changed more than Sensitivity + + Vector2 currentVelocity = syncVelocity ? target.linearVelocity : default; + float currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default; + + bool velocityChanged = syncVelocity && ((previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity); + bool angularVelocityChanged = syncAngularVelocity && ((previousValue.angularVelocity - currentAngularVelocity) > angularVelocitySensitivity); + + if (velocityChanged) + { + velocity = currentVelocity; + previousValue.velocity = currentVelocity; + } + + if (angularVelocityChanged) + { + angularVelocity = currentAngularVelocity; + previousValue.angularVelocity = currentAngularVelocity; + } + + // other rigidbody settings + isKinematic = target.isKinematic; + gravityScale = target.gravityScale; + drag = target.linearDamping; + angularDrag = target.angularDamping; + } + + /// + /// Uses Command to send values to server + /// + [Client] + void SendToServer() + { + if (!isOwned) + { + Debug.LogWarning("SendToServer called without authority"); + return; + } + + SendVelocity(); + SendRigidBodySettings(); + } + + [Client] + void SendVelocity() + { + float now = Time.time; + if (now < previousValue.nextSyncTime) + return; + + Vector2 currentVelocity = syncVelocity ? target.linearVelocity : default; + float currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default; + + bool velocityChanged = syncVelocity && ((previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity); + bool angularVelocityChanged = syncAngularVelocity && previousValue.angularVelocity != currentAngularVelocity;//((previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity); + + // if angularVelocity has changed it is likely that velocity has also changed so just sync both values + // however if only velocity has changed just send velocity + if (angularVelocityChanged) + { + CmdSendVelocityAndAngular(currentVelocity, currentAngularVelocity); + previousValue.velocity = currentVelocity; + previousValue.angularVelocity = currentAngularVelocity; + } + else if (velocityChanged) + { + CmdSendVelocity(currentVelocity); + previousValue.velocity = currentVelocity; + } + + // only update syncTime if either has changed + if (angularVelocityChanged || velocityChanged) + previousValue.nextSyncTime = now + syncInterval; + } + + [Client] + void SendRigidBodySettings() + { + // These shouldn't change often so it is ok to send in their own Command + if (previousValue.isKinematic != target.isKinematic) + { + CmdSendIsKinematic(target.isKinematic); + previousValue.isKinematic = target.isKinematic; + } + if (previousValue.gravityScale != target.gravityScale) + { + CmdChangeGravityScale(target.gravityScale); + previousValue.gravityScale = target.gravityScale; + } + if (previousValue.drag != target.linearDamping) + { + CmdSendDrag(target.linearDamping); + previousValue.drag = target.linearDamping; + } + if (previousValue.angularDrag != target.angularDamping) + { + CmdSendAngularDrag(target.angularDamping); + previousValue.angularDrag = target.angularDamping; + } + } + + /// + /// Called when only Velocity has changed on the client + /// + [Command] + void CmdSendVelocity(Vector2 velocity) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.velocity = velocity; + target.linearVelocity = velocity; + } + + /// + /// Called when angularVelocity has changed on the client + /// + [Command] + void CmdSendVelocityAndAngular(Vector2 velocity, float angularVelocity) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + if (syncVelocity) + { + this.velocity = velocity; + target.linearVelocity = velocity; + } + this.angularVelocity = angularVelocity; + target.angularVelocity = angularVelocity; + } + + [Command] + void CmdSendIsKinematic(bool isKinematic) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.isKinematic = isKinematic; + target.isKinematic = isKinematic; + } + + [Command] + void CmdChangeGravityScale(float gravityScale) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.gravityScale = gravityScale; + target.gravityScale = gravityScale; + } + + [Command] + void CmdSendDrag(float drag) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.drag = drag; + target.linearDamping = drag; + } + + [Command] + void CmdSendAngularDrag(float angularDrag) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + this.angularDrag = angularDrag; + target.angularDamping = angularDrag; + } + + /// + /// holds previously synced values + /// + public class ClientSyncState + { + /// + /// Next sync time that velocity will be synced, based on syncInterval. + /// + public float nextSyncTime; + public Vector2 velocity; + public float angularVelocity; + public bool isKinematic; + public float gravityScale; + public float drag; + public float angularDrag; + } + } +} diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs.meta b/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs.meta new file mode 100644 index 0000000..df466bd --- /dev/null +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ab2cbc52526ea384ba280d13cd1a57b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/GUIConsole.cs b/Assets/Mirror/Components/GUIConsole.cs new file mode 100644 index 0000000..7055fe1 --- /dev/null +++ b/Assets/Mirror/Components/GUIConsole.cs @@ -0,0 +1,133 @@ +// People should be able to see and report errors to the developer very easily. +// +// Unity's Developer Console only works in development builds and it only shows +// errors. This class provides a console that works in all builds and also shows +// log and warnings in development builds. +// +// Note: we don't include the stack trace, because that can also be grabbed from +// the log files if needed. +// +// Note: there is no 'hide' button because we DO want people to see those errors +// and report them back to us. +// +// Note: normal Debug.Log messages can be shown by building in Debug/Development +// mode. +using UnityEngine; +using System.Collections.Generic; + +namespace Mirror +{ + struct LogEntry + { + public string message; + public LogType type; + + public LogEntry(string message, LogType type) + { + this.message = message; + this.type = type; + } + } + + public class GUIConsole : MonoBehaviour + { + public int height = 80; + public int offsetY = 40; + + // only keep the recent 'n' entries. otherwise memory would grow forever + // and drawing would get slower and slower. + public int maxLogCount = 50; + + // Unity Editor has the Console window, we don't need to show it there. + // unless for testing, so keep it as option. + public bool showInEditor = false; + + // log as queue so we can remove the first entry easily + readonly Queue log = new Queue(); + + // hotkey to show/hide at runtime for easier debugging + // (sometimes we need to temporarily hide/show it) + // Default is BackQuote, because F keys are already assigned in browsers + [Tooltip("Hotkey to show/hide the console at runtime\nBack Quote is usually on the left above Tab\nChange with caution - F keys are generally already taken in Browsers")] + public KeyCode hotKey = KeyCode.BackQuote; + + // GUI + bool visible; + Vector2 scroll = Vector2.zero; + + // only show at runtime, or if showInEditor is enabled + bool show => !Application.isEditor || showInEditor; + + void Awake() + { + // only show at runtime, or if showInEditor is enabled + if (show) + Application.logMessageReceived += OnLog; + } + + // OnLog logs everything, even Debug.Log messages in release builds + // => this makes a lot of things easier. e.g. addon initialization logs. + // => it's really better to have than not to have those + void OnLog(string message, string stackTrace, LogType type) + { + // is this important? + // => always show exceptions & errors + // => usually a good idea to show warnings too, otherwise it's too + // easy to miss OnDeserialize warnings etc. in builds + bool isImportant = type == LogType.Error || type == LogType.Exception || type == LogType.Warning; + + // use stack trace only if important + // (otherwise users would have to find and search the log file. + // seeing it in the console directly is way easier to deal with.) + // => only add \n if stack trace is available (only in debug builds) + if (isImportant && !string.IsNullOrWhiteSpace(stackTrace)) + message += $"\n{stackTrace}"; + + // add to queue + log.Enqueue(new LogEntry(message, type)); + + // respect max entries + if (log.Count > maxLogCount) + log.Dequeue(); + + // become visible if it was important + // (no need to become visible for regular log. let the user decide.) + if (isImportant) + visible = true; + + // auto scroll + scroll.y = float.MaxValue; + } + + void Update() + { + if (show && Input.GetKeyDown(hotKey)) + visible = !visible; + } + + void OnGUI() + { + if (!visible) return; + + // If this offset is changed, also change width in NetworkManagerHUD::OnGUI + int offsetX = 300 + 20; + + GUILayout.BeginArea(new Rect(offsetX, offsetY, Screen.width - offsetX - 10, height)); + + scroll = GUILayout.BeginScrollView(scroll, "Box", GUILayout.Width(Screen.width - offsetX - 10), GUILayout.Height(height)); + foreach (LogEntry entry in log) + { + if (entry.type == LogType.Error || entry.type == LogType.Exception) + GUI.color = Color.red; + else if (entry.type == LogType.Warning) + GUI.color = Color.yellow; + + GUILayout.Label(entry.message); + GUI.color = Color.white; + } + GUILayout.EndScrollView(); + + GUILayout.EndArea(); + } + } +} diff --git a/Assets/Mirror/Components/GUIConsole.cs.meta b/Assets/Mirror/Components/GUIConsole.cs.meta new file mode 100644 index 0000000..5664216 --- /dev/null +++ b/Assets/Mirror/Components/GUIConsole.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9021b6cc314944290986ab6feb48db79 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement.meta b/Assets/Mirror/Components/InterestManagement.meta new file mode 100644 index 0000000..9b1f746 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c66f27e006ab94253b39a55a3b213651 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/Distance.meta b/Assets/Mirror/Components/InterestManagement/Distance.meta new file mode 100644 index 0000000..9847902 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Distance.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fa4cbc6b9c584db4971985cb9f369077 +timeCreated: 1613110605 \ No newline at end of file diff --git a/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagement.cs b/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagement.cs new file mode 100644 index 0000000..6549961 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagement.cs @@ -0,0 +1,90 @@ +// straight forward Vector3.Distance based interest management. +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + [AddComponentMenu("Network/ Interest Management/ Distance/Distance Interest Management")] + public class DistanceInterestManagement : InterestManagement + { + [Tooltip("The maximum range that objects will be visible at. Add DistanceInterestManagementCustomRange onto NetworkIdentities for custom ranges.")] + public int visRange = 500; + + [Tooltip("Rebuild all every 'rebuildInterval' seconds.")] + public float rebuildInterval = 1; + double lastRebuildTime; + + // cache custom ranges to avoid runtime TryGetComponent lookups + readonly Dictionary CustomRanges = new Dictionary(); + + // helper function to get vis range for a given object, or default. + [ServerCallback] + int GetVisRange(NetworkIdentity identity) + { + return CustomRanges.TryGetValue(identity, out DistanceInterestManagementCustomRange custom) ? custom.visRange : visRange; + } + + [ServerCallback] + public override void ResetState() + { + lastRebuildTime = 0D; + CustomRanges.Clear(); + } + + public override void OnSpawned(NetworkIdentity identity) + { + if (identity.TryGetComponent(out DistanceInterestManagementCustomRange custom)) + CustomRanges[identity] = custom; + } + + public override void OnDestroyed(NetworkIdentity identity) + { + CustomRanges.Remove(identity); + } + + public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver) + { + int range = GetVisRange(identity); + return Vector3.Distance(identity.transform.position, newObserver.identity.transform.position) < range; + } + + public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers) + { + // cache range and .transform because both call GetComponent. + int range = GetVisRange(identity); + Vector3 position = identity.transform.position; + + // brute force distance check + // -> only player connections can be observers, so it's enough if we + // go through all connections instead of all spawned identities. + // -> compared to UNET's sphere cast checking, this one is orders of + // magnitude faster. if we have 10k monsters and run a sphere + // cast 10k times, we will see a noticeable lag even with physics + // layers. but checking to every connection is fast. + foreach (NetworkConnectionToClient conn in NetworkServer.connections.Values) + { + // authenticated and joined world with a player? + if (conn != null && conn.isAuthenticated && conn.identity != null) + { + // check distance + if (Vector3.Distance(conn.identity.transform.position, position) < range) + { + newObservers.Add(conn); + } + } + } + } + + // internal so we can update from tests + [ServerCallback] + internal void Update() + { + // rebuild all spawned NetworkIdentity's observers every interval + if (NetworkTime.localTime >= lastRebuildTime + rebuildInterval) + { + RebuildAll(); + lastRebuildTime = NetworkTime.localTime; + } + } + } +} diff --git a/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagement.cs.meta b/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagement.cs.meta new file mode 100644 index 0000000..1a575af --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f60becab051427fbdd3c8ac9ab4712b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagementCustomRange.cs b/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagementCustomRange.cs new file mode 100644 index 0000000..12556e5 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagementCustomRange.cs @@ -0,0 +1,15 @@ +// add this to NetworkIdentities for custom range if needed. +// only works with DistanceInterestManagement. +using UnityEngine; + +namespace Mirror +{ + [DisallowMultipleComponent] + [AddComponentMenu("Network/ Interest Management/ Distance/Distance Custom Range")] + [HelpURL("https://mirror-networking.gitbook.io/docs/guides/interest-management")] + public class DistanceInterestManagementCustomRange : NetworkBehaviour + { + [Tooltip("The maximum range that objects will be visible at.")] + public int visRange = 100; + } +} diff --git a/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagementCustomRange.cs.meta b/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagementCustomRange.cs.meta new file mode 100644 index 0000000..406ca78 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Distance/DistanceInterestManagementCustomRange.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b2e242ee38a14076a39934172a19079b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/Match.meta b/Assets/Mirror/Components/InterestManagement/Match.meta new file mode 100644 index 0000000..e429883 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Match.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5eca5245ae6bb460e9a92f7e14d5493a +timeCreated: 1622649517 \ No newline at end of file diff --git a/Assets/Mirror/Components/InterestManagement/Match/MatchInterestManagement.cs b/Assets/Mirror/Components/InterestManagement/Match/MatchInterestManagement.cs new file mode 100644 index 0000000..d741d0c --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Match/MatchInterestManagement.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + [AddComponentMenu("Network/ Interest Management/ Match/Match Interest Management")] + public class MatchInterestManagement : InterestManagement + { + [Header("Diagnostics")] + [ReadOnly, SerializeField] + internal ushort matchCount; + + readonly Dictionary> matchObjects = + new Dictionary>(); + + readonly HashSet dirtyMatches = new HashSet(); + + // LateUpdate so that all spawns/despawns/changes are done + [ServerCallback] + void LateUpdate() + { + // Rebuild all dirty matches + // dirtyMatches will be empty if no matches changed members + // by spawning or destroying or changing matchId in this frame. + foreach (Guid dirtyMatch in dirtyMatches) + { + // rebuild always, even if matchObjects[dirtyMatch] is empty. + // Players might have left the match, but they may still be spawned. + RebuildMatchObservers(dirtyMatch); + + // clean up empty entries in the dict + if (matchObjects[dirtyMatch].Count == 0) + matchObjects.Remove(dirtyMatch); + } + + dirtyMatches.Clear(); + + matchCount = (ushort)matchObjects.Count; + } + + [ServerCallback] + void RebuildMatchObservers(Guid matchId) + { + foreach (NetworkMatch networkMatch in matchObjects[matchId]) + if (networkMatch.netIdentity != null) + NetworkServer.RebuildObservers(networkMatch.netIdentity, false); + } + + // called by NetworkMatch.matchId setter + [ServerCallback] + internal void OnMatchChanged(NetworkMatch networkMatch, Guid oldMatch) + { + // This object is in a new match so observers in the prior match + // and the new match need to rebuild their respective observers lists. + + // Remove this object from the hashset of the match it just left + // Guid.Empty is never a valid matchId + if (oldMatch != Guid.Empty) + { + dirtyMatches.Add(oldMatch); + matchObjects[oldMatch].Remove(networkMatch); + } + + // Guid.Empty is never a valid matchId + if (networkMatch.matchId == Guid.Empty) + return; + + dirtyMatches.Add(networkMatch.matchId); + + // Make sure this new match is in the dictionary + if (!matchObjects.ContainsKey(networkMatch.matchId)) + matchObjects[networkMatch.matchId] = new HashSet(); + + // Add this object to the hashset of the new match + matchObjects[networkMatch.matchId].Add(networkMatch); + } + + [ServerCallback] + public override void OnSpawned(NetworkIdentity identity) + { + if (!identity.TryGetComponent(out NetworkMatch networkMatch)) + return; + + Guid networkMatchId = networkMatch.matchId; + + // Guid.Empty is never a valid matchId...do not add to matchObjects collection + if (networkMatchId == Guid.Empty) + return; + + // Debug.Log($"MatchInterestManagement.OnSpawned({identity.name}) currentMatch: {currentMatch}"); + if (!matchObjects.TryGetValue(networkMatchId, out HashSet objects)) + { + objects = new HashSet(); + matchObjects.Add(networkMatchId, objects); + } + + objects.Add(networkMatch); + + // Match ID could have been set in NetworkBehaviour::OnStartServer on this object. + // Since that's after OnCheckObserver is called it would be missed, so force Rebuild here. + // Add the current match to dirtyMatches for LateUpdate to rebuild it. + dirtyMatches.Add(networkMatchId); + } + + [ServerCallback] + public override void OnDestroyed(NetworkIdentity identity) + { + // Don't RebuildSceneObservers here - that will happen in LateUpdate. + // Multiple objects could be destroyed in same frame and we don't + // want to rebuild for each one...let LateUpdate do it once. + // We must add the current match to dirtyMatches for LateUpdate to rebuild it. + if (identity.TryGetComponent(out NetworkMatch currentMatch)) + { + if (currentMatch.matchId != Guid.Empty && + matchObjects.TryGetValue(currentMatch.matchId, out HashSet objects) && + objects.Remove(currentMatch)) + dirtyMatches.Add(currentMatch.matchId); + } + } + + [ServerCallback] + public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver) + { + // Never observed if no NetworkMatch component + if (!identity.TryGetComponent(out NetworkMatch identityNetworkMatch)) + return false; + + // Guid.Empty is never a valid matchId + if (identityNetworkMatch.matchId == Guid.Empty) + return false; + + // Never observed if no NetworkMatch component + if (!newObserver.identity.TryGetComponent(out NetworkMatch newObserverNetworkMatch)) + return false; + + // Guid.Empty is never a valid matchId + if (newObserverNetworkMatch.matchId == Guid.Empty) + return false; + + return identityNetworkMatch.matchId == newObserverNetworkMatch.matchId; + } + + [ServerCallback] + public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers) + { + if (!identity.TryGetComponent(out NetworkMatch networkMatch)) + return; + + // Guid.Empty is never a valid matchId + if (networkMatch.matchId == Guid.Empty) + return; + + // Abort if this match hasn't been created yet by OnSpawned or OnMatchChanged + if (!matchObjects.TryGetValue(networkMatch.matchId, out HashSet objects)) + return; + + // Add everything in the hashset for this object's current match + foreach (NetworkMatch netMatch in objects) + if (netMatch.netIdentity != null && netMatch.netIdentity.connectionToClient != null) + newObservers.Add(netMatch.netIdentity.connectionToClient); + } + } +} diff --git a/Assets/Mirror/Components/InterestManagement/Match/MatchInterestManagement.cs.meta b/Assets/Mirror/Components/InterestManagement/Match/MatchInterestManagement.cs.meta new file mode 100644 index 0000000..605d215 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Match/MatchInterestManagement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d09f5c8bf2f4747b7a9284ef5d9ce2a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/Match/NetworkMatch.cs b/Assets/Mirror/Components/InterestManagement/Match/NetworkMatch.cs new file mode 100644 index 0000000..0d55fd0 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Match/NetworkMatch.cs @@ -0,0 +1,42 @@ +// simple component that holds match information +using System; +using UnityEngine; + +namespace Mirror +{ + [DisallowMultipleComponent] + [AddComponentMenu("Network/ Interest Management/ Match/Network Match")] + [HelpURL("https://mirror-networking.gitbook.io/docs/guides/interest-management")] + public class NetworkMatch : NetworkBehaviour + { + Guid _matchId; + +#pragma warning disable IDE0052 // Suppress warning for unused field...this is for debugging purposes + [SerializeField, ReadOnly] + [Tooltip("Match ID is shown here on server for debugging purposes.")] + string MatchID = string.Empty; +#pragma warning restore IDE0052 + + ///Set this to the same value on all networked objects that belong to a given match + public Guid matchId + { + get => _matchId; + set + { + if (!NetworkServer.active) + throw new InvalidOperationException("matchId can only be set at runtime on active server"); + + if (_matchId == value) + return; + + Guid oldMatch = _matchId; + _matchId = value; + MatchID = value.ToString(); + + // Only inform the AOI if this netIdentity has been spawned (isServer) and only if using a MatchInterestManagement + if (isServer && NetworkServer.aoi is MatchInterestManagement matchInterestManagement) + matchInterestManagement.OnMatchChanged(this, oldMatch); + } + } + } +} diff --git a/Assets/Mirror/Components/InterestManagement/Match/NetworkMatch.cs.meta b/Assets/Mirror/Components/InterestManagement/Match/NetworkMatch.cs.meta new file mode 100644 index 0000000..47fc70a --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Match/NetworkMatch.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d17e718851449a6879986e45c458fb7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/Scene.meta b/Assets/Mirror/Components/InterestManagement/Scene.meta new file mode 100644 index 0000000..28b469f --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Scene.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7655d309a46a4bd4860edf964228b3f6 +timeCreated: 1622649517 \ No newline at end of file diff --git a/Assets/Mirror/Components/InterestManagement/Scene/SceneInterestManagement.cs b/Assets/Mirror/Components/InterestManagement/Scene/SceneInterestManagement.cs new file mode 100644 index 0000000..28e5eba --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Scene/SceneInterestManagement.cs @@ -0,0 +1,118 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace Mirror +{ + [AddComponentMenu("Network/ Interest Management/ Scene/Scene Interest Management")] + public class SceneInterestManagement : InterestManagement + { + // Use Scene instead of string scene.name because when additively + // loading multiples of a subscene the name won't be unique + readonly Dictionary> sceneObjects = + new Dictionary>(); + + readonly Dictionary lastObjectScene = + new Dictionary(); + + HashSet dirtyScenes = new HashSet(); + + [ServerCallback] + public override void OnSpawned(NetworkIdentity identity) + { + Scene currentScene = identity.gameObject.scene; + lastObjectScene[identity] = currentScene; + // Debug.Log($"SceneInterestManagement.OnSpawned({identity.name}) currentScene: {currentScene}"); + if (!sceneObjects.TryGetValue(currentScene, out HashSet objects)) + { + objects = new HashSet(); + sceneObjects.Add(currentScene, objects); + } + + objects.Add(identity); + } + + [ServerCallback] + public override void OnDestroyed(NetworkIdentity identity) + { + // Don't RebuildSceneObservers here - that will happen in Update. + // Multiple objects could be destroyed in same frame and we don't + // want to rebuild for each one...let Update do it once. + // We must add the current scene to dirtyScenes for Update to rebuild it. + if (lastObjectScene.TryGetValue(identity, out Scene currentScene)) + { + lastObjectScene.Remove(identity); + if (sceneObjects.TryGetValue(currentScene, out HashSet objects) && objects.Remove(identity)) + dirtyScenes.Add(currentScene); + } + } + + // internal so we can update from tests + [ServerCallback] + internal void Update() + { + // for each spawned: + // if scene changed: + // add previous to dirty + // add new to dirty + foreach (NetworkIdentity identity in NetworkServer.spawned.Values) + { + if (!lastObjectScene.TryGetValue(identity, out Scene currentScene)) + continue; + + Scene newScene = identity.gameObject.scene; + if (newScene == currentScene) + continue; + + // Mark new/old scenes as dirty so they get rebuilt + dirtyScenes.Add(currentScene); + dirtyScenes.Add(newScene); + + // This object is in a new scene so observers in the prior scene + // and the new scene need to rebuild their respective observers lists. + + // Remove this object from the hashset of the scene it just left + sceneObjects[currentScene].Remove(identity); + + // Set this to the new scene this object just entered + lastObjectScene[identity] = newScene; + + // Make sure this new scene is in the dictionary + if (!sceneObjects.ContainsKey(newScene)) + sceneObjects.Add(newScene, new HashSet()); + + // Add this object to the hashset of the new scene + sceneObjects[newScene].Add(identity); + } + + // rebuild all dirty scenes + foreach (Scene dirtyScene in dirtyScenes) + RebuildSceneObservers(dirtyScene); + + dirtyScenes.Clear(); + } + + void RebuildSceneObservers(Scene scene) + { + foreach (NetworkIdentity netIdentity in sceneObjects[scene]) + if (netIdentity != null) + NetworkServer.RebuildObservers(netIdentity, false); + } + + public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver) + { + return identity.gameObject.scene == newObserver.identity.gameObject.scene; + } + + public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers) + { + if (!sceneObjects.TryGetValue(identity.gameObject.scene, out HashSet objects)) + return; + + // Add everything in the hashset for this object's current scene + foreach (NetworkIdentity networkIdentity in objects) + if (networkIdentity != null && networkIdentity.connectionToClient != null) + newObservers.Add(networkIdentity.connectionToClient); + } + } +} diff --git a/Assets/Mirror/Components/InterestManagement/Scene/SceneInterestManagement.cs.meta b/Assets/Mirror/Components/InterestManagement/Scene/SceneInterestManagement.cs.meta new file mode 100644 index 0000000..9cc1ff5 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Scene/SceneInterestManagement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b979f26c95d34324ba005bfacfa9c4fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/SpatialHashing.meta b/Assets/Mirror/Components/InterestManagement/SpatialHashing.meta new file mode 100644 index 0000000..00f5cd6 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/SpatialHashing.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cfa12b73503344d49b398b01bcb07967 +timeCreated: 1613110634 \ No newline at end of file diff --git a/Assets/Mirror/Components/InterestManagement/SpatialHashing/Grid2D.cs b/Assets/Mirror/Components/InterestManagement/SpatialHashing/Grid2D.cs new file mode 100644 index 0000000..d557713 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/SpatialHashing/Grid2D.cs @@ -0,0 +1,104 @@ +// Grid2D from uMMORPG: get/set values of type T at any point +// -> not named 'Grid' because Unity already has a Grid type. causes warnings. +// -> struct to avoid memory indirection. it's accessed a lot. +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + // struct to avoid memory indirection. it's accessed a lot. + public struct Grid2D + { + // the grid + // note that we never remove old keys. + // => over time, HashSets will be allocated for every possible + // grid position in the world + // => Clear() doesn't clear them so we don't constantly reallocate the + // entries when populating the grid in every Update() call + // => makes the code a lot easier too + // => this is FINE because in the worst case, every grid position in the + // game world is filled with a player anyway! + readonly Dictionary> grid; + + // cache a 9 neighbor grid of vector2 offsets so we can use them more easily + readonly Vector2Int[] neighbourOffsets; + + public Grid2D(int initialCapacity) + { + grid = new Dictionary>(initialCapacity); + + neighbourOffsets = new[] { + Vector2Int.up, + Vector2Int.up + Vector2Int.left, + Vector2Int.up + Vector2Int.right, + Vector2Int.left, + Vector2Int.zero, + Vector2Int.right, + Vector2Int.down, + Vector2Int.down + Vector2Int.left, + Vector2Int.down + Vector2Int.right + }; + } + + // helper function so we can add an entry without worrying + public void Add(Vector2Int position, T value) + { + // initialize set in grid if it's not in there yet + if (!grid.TryGetValue(position, out HashSet hashSet)) + { + // each grid entry may hold hundreds of entities. + // let's create the HashSet with a large initial capacity + // in order to avoid resizing & allocations. +#if !UNITY_2021_3_OR_NEWER + // Unity 2019 doesn't have "new HashSet(capacity)" yet + hashSet = new HashSet(); +#else + hashSet = new HashSet(128); +#endif + grid[position] = hashSet; + } + + // add to it + hashSet.Add(value); + } + + // helper function to get set at position without worrying + // -> result is passed as parameter to avoid allocations + // -> result is not cleared before. this allows us to pass the HashSet from + // GetWithNeighbours and avoid .UnionWith which is very expensive. + void GetAt(Vector2Int position, HashSet result) + { + // return the set at position + if (grid.TryGetValue(position, out HashSet hashSet)) + { + foreach (T entry in hashSet) + result.Add(entry); + } + } + + // helper function to get at position and it's 8 neighbors without worrying + // -> result is passed as parameter to avoid allocations + public void GetWithNeighbours(Vector2Int position, HashSet result) + { + // clear result first + result.Clear(); + + // add neighbours + foreach (Vector2Int offset in neighbourOffsets) + GetAt(position + offset, result); + } + + // clear: clears the whole grid + // IMPORTANT: we already allocated HashSets and don't want to do + // reallocate every single update when we rebuild the grid. + // => so simply remove each position's entries, but keep + // every position in there + // => see 'grid' comments above! + // => named ClearNonAlloc to make it more obvious! + public void ClearNonAlloc() + { + foreach (HashSet hashSet in grid.Values) + hashSet.Clear(); + } + } +} diff --git a/Assets/Mirror/Components/InterestManagement/SpatialHashing/Grid2D.cs.meta b/Assets/Mirror/Components/InterestManagement/SpatialHashing/Grid2D.cs.meta new file mode 100644 index 0000000..f1d3cf0 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/SpatialHashing/Grid2D.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7c5232a4d2854116a35d52b80ec07752 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/SpatialHashing/SpatialHashingInterestManagement.cs b/Assets/Mirror/Components/InterestManagement/SpatialHashing/SpatialHashingInterestManagement.cs new file mode 100644 index 0000000..066a1c5 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/SpatialHashing/SpatialHashingInterestManagement.cs @@ -0,0 +1,154 @@ +// extremely fast spatial hashing interest management based on uMMORPG GridChecker. +// => 30x faster in initial tests +// => scales way higher +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + [AddComponentMenu("Network/ Interest Management/ Spatial Hash/Spatial Hashing Interest Management")] + public class SpatialHashingInterestManagement : InterestManagement + { + [Tooltip("The maximum range that objects will be visible at.")] + public int visRange = 30; + + // we use a 9 neighbour grid. + // so we always see in a distance of 2 grids. + // for example, our own grid and then one on top / below / left / right. + // + // this means that grid resolution needs to be distance / 2. + // so for example, for distance = 30 we see 2 cells = 15 * 2 distance. + // + // on first sight, it seems we need distance / 3 (we see left/us/right). + // but that's not the case. + // resolution would be 10, and we only see 1 cell far, so 10+10=20. + public int resolution => visRange / 2; + + [Tooltip("Rebuild all every 'rebuildInterval' seconds.")] + public float rebuildInterval = 1; + double lastRebuildTime; + + public enum CheckMethod + { + XZ_FOR_3D, + XY_FOR_2D + } + [Tooltip("Spatial Hashing supports 3D (XZ) and 2D (XY) games.")] + public CheckMethod checkMethod = CheckMethod.XZ_FOR_3D; + + // debugging + public bool showSlider; + + // the grid + // begin with a large capacity to avoid resizing & allocations. + Grid2D grid = new Grid2D(1024); + + // project 3d world position to grid position + Vector2Int ProjectToGrid(Vector3 position) => + checkMethod == CheckMethod.XZ_FOR_3D + ? Vector2Int.RoundToInt(new Vector2(position.x, position.z) / resolution) + : Vector2Int.RoundToInt(new Vector2(position.x, position.y) / resolution); + + public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver) + { + // calculate projected positions + Vector2Int projected = ProjectToGrid(identity.transform.position); + Vector2Int observerProjected = ProjectToGrid(newObserver.identity.transform.position); + + // distance needs to be at max one of the 8 neighbors, which is + // 1 for the direct neighbors + // 1.41 for the diagonal neighbors (= sqrt(2)) + // => use sqrMagnitude and '2' to avoid computations. same result. + return (projected - observerProjected).sqrMagnitude <= 2; + } + + public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers) + { + // add everyone in 9 neighbour grid + // -> pass observers to GetWithNeighbours directly to avoid allocations + // and expensive .UnionWith computations. + Vector2Int current = ProjectToGrid(identity.transform.position); + grid.GetWithNeighbours(current, newObservers); + } + + [ServerCallback] + public override void ResetState() + { + lastRebuildTime = 0D; + } + + // update everyone's position in the grid + // (internal so we can update from tests) + [ServerCallback] + internal void Update() + { + // NOTE: unlike Scene/MatchInterestManagement, this rebuilds ALL + // entities every INTERVAL. consider the other approach later. + + // IMPORTANT: refresh grid every update! + // => newly spawned entities get observers assigned via + // OnCheckObservers. this can happen any time and we don't want + // them broadcast to old (moved or destroyed) connections. + // => players do move all the time. we want them to always be in the + // correct grid position. + // => note that the actual 'rebuildall' doesn't need to happen all + // the time. + // NOTE: consider refreshing grid only every 'interval' too. but not + // for now. stability & correctness matter. + + // clear old grid results before we update everyone's position. + // (this way we get rid of destroyed connections automatically) + // + // NOTE: keeps allocated HashSets internally. + // clearing & populating every frame works without allocations + grid.ClearNonAlloc(); + + // put every connection into the grid at it's main player's position + // NOTE: player sees in a radius around him. NOT around his pet too. + foreach (NetworkConnectionToClient connection in NetworkServer.connections.Values) + { + // authenticated and joined world with a player? + if (connection.isAuthenticated && connection.identity != null) + { + // calculate current grid position + Vector2Int position = ProjectToGrid(connection.identity.transform.position); + + // put into grid + grid.Add(position, connection); + } + } + + // rebuild all spawned entities' observers every 'interval' + // this will call OnRebuildObservers which then returns the + // observers at grid[position] for each entity. + if (NetworkTime.localTime >= lastRebuildTime + rebuildInterval) + { + RebuildAll(); + lastRebuildTime = NetworkTime.localTime; + } + } + +// OnGUI allocates even if it does nothing. avoid in release. +#if UNITY_EDITOR || DEVELOPMENT_BUILD + // slider from dotsnet. it's nice to play around with in the benchmark + // demo. + void OnGUI() + { + if (!showSlider) return; + + // only show while server is running. not on client, etc. + if (!NetworkServer.active) return; + + int height = 30; + int width = 250; + GUILayout.BeginArea(new Rect(Screen.width / 2 - width / 2, Screen.height - height, width, height)); + GUILayout.BeginHorizontal("Box"); + GUILayout.Label("Radius:"); + visRange = Mathf.RoundToInt(GUILayout.HorizontalSlider(visRange, 0, 200, GUILayout.Width(150))); + GUILayout.Label(visRange.ToString()); + GUILayout.EndHorizontal(); + GUILayout.EndArea(); + } +#endif + } +} diff --git a/Assets/Mirror/Components/InterestManagement/SpatialHashing/SpatialHashingInterestManagement.cs.meta b/Assets/Mirror/Components/InterestManagement/SpatialHashing/SpatialHashingInterestManagement.cs.meta new file mode 100644 index 0000000..271e433 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/SpatialHashing/SpatialHashingInterestManagement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 39adc6e09d5544ed955a50ce8600355a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/Team.meta b/Assets/Mirror/Components/InterestManagement/Team.meta new file mode 100644 index 0000000..fe40aa4 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Team.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d418e60072433b4bbebbf5f3a7de1bb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/Team/NetworkTeam.cs b/Assets/Mirror/Components/InterestManagement/Team/NetworkTeam.cs new file mode 100644 index 0000000..290eb06 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Team/NetworkTeam.cs @@ -0,0 +1,39 @@ +// simple component that holds team information +using System; +using UnityEngine; + +namespace Mirror +{ + [DisallowMultipleComponent] + [AddComponentMenu("Network/ Interest Management/ Team/Network Team")] + [HelpURL("https://mirror-networking.gitbook.io/docs/guides/interest-management")] + public class NetworkTeam : NetworkBehaviour + { + [SerializeField] + [Tooltip("Set teamId on Server at runtime to the same value on all networked objects that belong to a given team")] + string _teamId; + + public string teamId + { + get => _teamId; + set + { + if (Application.IsPlaying(gameObject) && !NetworkServer.active) + throw new InvalidOperationException("teamId can only be set at runtime on active server"); + + if (_teamId == value) + return; + + string oldTeam = _teamId; + _teamId = value; + + //Only inform the AOI if this netIdentity has been spawned(isServer) and only if using a TeamInterestManagement + if (isServer && NetworkServer.aoi is TeamInterestManagement teamInterestManagement) + teamInterestManagement.OnTeamChanged(this, oldTeam); + } + } + + [Tooltip("When enabled this object is visible to all clients. Typically this would be true for player objects")] + public bool forceShown; + } +} diff --git a/Assets/Mirror/Components/InterestManagement/Team/NetworkTeam.cs.meta b/Assets/Mirror/Components/InterestManagement/Team/NetworkTeam.cs.meta new file mode 100644 index 0000000..ca75a7a --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Team/NetworkTeam.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2576730625b1632468cbcbfe5e721f88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/InterestManagement/Team/TeamInterestManagement.cs b/Assets/Mirror/Components/InterestManagement/Team/TeamInterestManagement.cs new file mode 100644 index 0000000..cb5bdb7 --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Team/TeamInterestManagement.cs @@ -0,0 +1,182 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + [AddComponentMenu("Network/ Interest Management/ Team/Team Interest Management")] + public class TeamInterestManagement : InterestManagement + { + readonly Dictionary> teamObjects = + new Dictionary>(); + + readonly HashSet dirtyTeams = new HashSet(); + + // LateUpdate so that all spawns/despawns/changes are done + [ServerCallback] + void LateUpdate() + { + // Rebuild all dirty teams + // dirtyTeams will be empty if no teams changed members + // by spawning or destroying or changing teamId in this frame. + foreach (string dirtyTeam in dirtyTeams) + { + // rebuild always, even if teamObjects[dirtyTeam] is empty. + // Players might have left the team, but they may still be spawned. + RebuildTeamObservers(dirtyTeam); + + // clean up empty entries in the dict + if (teamObjects[dirtyTeam].Count == 0) + teamObjects.Remove(dirtyTeam); + } + + dirtyTeams.Clear(); + } + + [ServerCallback] + void RebuildTeamObservers(string teamId) + { + foreach (NetworkTeam networkTeam in teamObjects[teamId]) + if (networkTeam.netIdentity != null) + NetworkServer.RebuildObservers(networkTeam.netIdentity, false); + } + + // called by NetworkTeam.teamId setter + [ServerCallback] + internal void OnTeamChanged(NetworkTeam networkTeam, string oldTeam) + { + // This object is in a new team so observers in the prior team + // and the new team need to rebuild their respective observers lists. + + // Remove this object from the hashset of the team it just left + // Null / Empty string is never a valid teamId + if (!string.IsNullOrWhiteSpace(oldTeam)) + { + dirtyTeams.Add(oldTeam); + teamObjects[oldTeam].Remove(networkTeam); + } + + // Null / Empty string is never a valid teamId + if (string.IsNullOrWhiteSpace(networkTeam.teamId)) + return; + + dirtyTeams.Add(networkTeam.teamId); + + // Make sure this new team is in the dictionary + if (!teamObjects.ContainsKey(networkTeam.teamId)) + teamObjects[networkTeam.teamId] = new HashSet(); + + // Add this object to the hashset of the new team + teamObjects[networkTeam.teamId].Add(networkTeam); + } + + [ServerCallback] + public override void OnSpawned(NetworkIdentity identity) + { + if (!identity.TryGetComponent(out NetworkTeam networkTeam)) + return; + + string networkTeamId = networkTeam.teamId; + + // Null / Empty string is never a valid teamId...do not add to teamObjects collection + if (string.IsNullOrWhiteSpace(networkTeamId)) + return; + + // Debug.Log($"TeamInterestManagement.OnSpawned({identity.name}) currentTeam: {currentTeam}"); + if (!teamObjects.TryGetValue(networkTeamId, out HashSet objects)) + { + objects = new HashSet(); + teamObjects.Add(networkTeamId, objects); + } + + objects.Add(networkTeam); + + // Team ID could have been set in NetworkBehaviour::OnStartServer on this object. + // Since that's after OnCheckObserver is called it would be missed, so force Rebuild here. + // Add the current team to dirtyTeames for LateUpdate to rebuild it. + dirtyTeams.Add(networkTeamId); + } + + [ServerCallback] + public override void OnDestroyed(NetworkIdentity identity) + { + // Don't RebuildSceneObservers here - that will happen in LateUpdate. + // Multiple objects could be destroyed in same frame and we don't + // want to rebuild for each one...let LateUpdate do it once. + // We must add the current team to dirtyTeames for LateUpdate to rebuild it. + if (identity.TryGetComponent(out NetworkTeam currentTeam)) + { + if (!string.IsNullOrWhiteSpace(currentTeam.teamId) && + teamObjects.TryGetValue(currentTeam.teamId, out HashSet objects) && + objects.Remove(currentTeam)) + dirtyTeams.Add(currentTeam.teamId); + } + } + + public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver) + { + // Always observed if no NetworkTeam component + if (!identity.TryGetComponent(out NetworkTeam identityNetworkTeam)) + return true; + + if (identityNetworkTeam.forceShown) + return true; + + // Null / Empty string is never a valid teamId + if (string.IsNullOrWhiteSpace(identityNetworkTeam.teamId)) + return false; + + // Always observed if no NetworkTeam component + if (!newObserver.identity.TryGetComponent(out NetworkTeam newObserverNetworkTeam)) + return true; + + // Null / Empty string is never a valid teamId + if (string.IsNullOrWhiteSpace(newObserverNetworkTeam.teamId)) + return false; + + //Debug.Log($"TeamInterestManagement.OnCheckObserver {identity.name} {identityNetworkTeam.teamId} | {newObserver.identity.name} {newObserverNetworkTeam.teamId}"); + + // Observed only if teamId's team + return identityNetworkTeam.teamId == newObserverNetworkTeam.teamId; + } + + public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers) + { + // If this object doesn't have a NetworkTeam then it's visible to all clients + if (!identity.TryGetComponent(out NetworkTeam networkTeam)) + { + AddAllConnections(newObservers); + return; + } + + // If this object has NetworkTeam and forceShown == true then it's visible to all clients + if (networkTeam.forceShown) + { + AddAllConnections(newObservers); + return; + } + + // Null / Empty string is never a valid teamId + if (string.IsNullOrWhiteSpace(networkTeam.teamId)) + return; + + // Abort if this team hasn't been created yet by OnSpawned or OnTeamChanged + if (!teamObjects.TryGetValue(networkTeam.teamId, out HashSet objects)) + return; + + // Add everything in the hashset for this object's current team + foreach (NetworkTeam netTeam in objects) + if (netTeam.netIdentity != null && netTeam.netIdentity.connectionToClient != null) + newObservers.Add(netTeam.netIdentity.connectionToClient); + } + + void AddAllConnections(HashSet newObservers) + { + foreach (NetworkConnectionToClient conn in NetworkServer.connections.Values) + { + // authenticated and joined world with a player? + if (conn != null && conn.isAuthenticated && conn.identity != null) + newObservers.Add(conn); + } + } + } +} diff --git a/Assets/Mirror/Components/InterestManagement/Team/TeamInterestManagement.cs.meta b/Assets/Mirror/Components/InterestManagement/Team/TeamInterestManagement.cs.meta new file mode 100644 index 0000000..6e8748a --- /dev/null +++ b/Assets/Mirror/Components/InterestManagement/Team/TeamInterestManagement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dceb9a7085758fd4590419ff5b14b636 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/LagCompensation.meta b/Assets/Mirror/Components/LagCompensation.meta new file mode 100644 index 0000000..669a5b8 --- /dev/null +++ b/Assets/Mirror/Components/LagCompensation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00ac1d0527f234939aba22b4d7cbf280 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/LagCompensation/HistoryCollider.cs b/Assets/Mirror/Components/LagCompensation/HistoryCollider.cs new file mode 100644 index 0000000..8e841a4 --- /dev/null +++ b/Assets/Mirror/Components/LagCompensation/HistoryCollider.cs @@ -0,0 +1,107 @@ +// Applies HistoryBounds to the physics world by projecting to a trigger Collider. +// This way we can use Physics.Raycast on it. +using UnityEngine; + +namespace Mirror +{ + public class HistoryCollider : MonoBehaviour + { + [Header("Components")] + [Tooltip("The object's actual collider. We need to know where it is, and how large it is.")] + public Collider actualCollider; + + [Tooltip("The helper collider that the history bounds are projected onto.\nNeeds to be added to a child GameObject to counter-rotate an axis aligned Bounding Box onto it.\nThis is only used by this component.")] + public BoxCollider boundsCollider; + + [Header("History")] + [Tooltip("Keep this many past bounds in the buffer. The larger this is, the further we can raycast into the past.\nMaximum time := historyAmount * captureInterval")] + public int boundsLimit = 8; + + [Tooltip("Gather N bounds at a time into a bucket for faster encapsulation. A factor of 2 will be twice as fast, etc.")] + public int boundsPerBucket = 2; + + [Tooltip("Capture bounds every 'captureInterval' seconds. Larger values will require fewer computations, but may not capture every small move.")] + public float captureInterval = 0.100f; // 100 ms + double lastCaptureTime = 0; + + [Header("Debug")] + public Color historyColor = new Color(1.0f, 0.5f, 0.0f, 1.0f); + public Color currentColor = Color.red; + + protected HistoryBounds history = null; + + protected virtual void Awake() + { + history = new HistoryBounds(boundsLimit, boundsPerBucket); + + // ensure colliders were set. + // bounds collider should always be a trigger. + if (actualCollider == null) Debug.LogError("HistoryCollider: actualCollider was not set."); + if (boundsCollider == null) Debug.LogError("HistoryCollider: boundsCollider was not set."); + if (boundsCollider.transform.parent != transform) Debug.LogError("HistoryCollider: boundsCollider must be a child of this GameObject."); + if (!boundsCollider.isTrigger) Debug.LogError("HistoryCollider: boundsCollider must be a trigger."); + } + + // capturing and projecting onto colliders should use physics update + protected virtual void FixedUpdate() + { + // capture current bounds every interval + if (NetworkTime.localTime >= lastCaptureTime + captureInterval) + { + lastCaptureTime = NetworkTime.localTime; + CaptureBounds(); + } + + // project bounds onto helper collider + ProjectBounds(); + } + + protected virtual void CaptureBounds() + { + // grab current collider bounds + // this is in world space coordinates, and axis aligned + // TODO double check + Bounds bounds = actualCollider.bounds; + + // insert into history + history.Insert(bounds); + } + + protected virtual void ProjectBounds() + { + // grab total collider encapsulating all of history + Bounds total = history.total; + + // don't assign empty bounds, this will throw a Unity warning + if (history.boundsCount == 0) return; + + // scale projection doesn't work yet. + // for now, don't allow scale changes. + if (transform.lossyScale != Vector3.one) + { + Debug.LogWarning($"HistoryCollider: {name}'s transform global scale must be (1,1,1)."); + return; + } + + // counter rotate the child collider against the gameobject's rotation. + // we need this to always be axis aligned. + boundsCollider.transform.localRotation = Quaternion.Inverse(transform.rotation); + + // project world space bounds to collider's local space + boundsCollider.center = boundsCollider.transform.InverseTransformPoint(total.center); + boundsCollider.size = total.size; // TODO projection? + } + + // TODO runtime drawing for debugging? + protected virtual void OnDrawGizmos() + { + // draw total bounds + Gizmos.color = historyColor; + Gizmos.DrawWireCube(history.total.center, history.total.size); + + // draw current bounds + Gizmos.color = currentColor; + Gizmos.DrawWireCube(actualCollider.bounds.center, actualCollider.bounds.size); + } + } +} diff --git a/Assets/Mirror/Components/LagCompensation/HistoryCollider.cs.meta b/Assets/Mirror/Components/LagCompensation/HistoryCollider.cs.meta new file mode 100644 index 0000000..6275ff1 --- /dev/null +++ b/Assets/Mirror/Components/LagCompensation/HistoryCollider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f5f2158d9776d4b569858f793be4da60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/LagCompensation/LagCompensator.cs b/Assets/Mirror/Components/LagCompensation/LagCompensator.cs new file mode 100644 index 0000000..96b6366 --- /dev/null +++ b/Assets/Mirror/Components/LagCompensation/LagCompensator.cs @@ -0,0 +1,196 @@ +// Add this component to a Player object with collider. +// Automatically keeps a history for lag compensation. +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + public struct Capture3D : Capture + { + public double timestamp { get; set; } + public Vector3 position; + public Vector3 size; + + public Capture3D(double timestamp, Vector3 position, Vector3 size) + { + this.timestamp = timestamp; + this.position = position; + this.size = size; + } + + public void DrawGizmo() + { + Gizmos.DrawWireCube(position, size); + } + + public static Capture3D Interpolate(Capture3D from, Capture3D to, double t) => + new Capture3D( + 0, // interpolated snapshot is applied directly. don't need timestamps. + Vector3.LerpUnclamped(from.position, to.position, (float)t), + Vector3.LerpUnclamped(from.size, to.size, (float)t) + ); + + public override string ToString() => $"(time={timestamp} pos={position} size={size})"; + } + + [Obsolete("This is a preview version. Community feedback is welcome!")] + public class LagCompensator : NetworkBehaviour + { + [Header("Components")] + [Tooltip("The collider to keep a history of.")] + public Collider trackedCollider; // assign this in inspector + + [Header("Settings")] + public LagCompensationSettings lagCompensationSettings = new LagCompensationSettings(); + double lastCaptureTime; + + // lag compensation history of + readonly Queue> history = new Queue>(); + + [Header("Debugging")] + public Color historyColor = Color.white; + + protected virtual void Update() + { + // only capture on server + if (!NetworkServer.active) return; + + // capture lag compensation snapshots every interval. + // NetworkTime.localTime because Unity 2019 doesn't have 'double' time yet. + if (NetworkTime.localTime >= lastCaptureTime + lagCompensationSettings.captureInterval) + { + lastCaptureTime = NetworkTime.localTime; + Capture(); + } + } + + protected virtual void Capture() + { + // capture current state + Capture3D capture = new Capture3D( + NetworkTime.localTime, + trackedCollider.bounds.center, + trackedCollider.bounds.size + ); + + // insert into history + LagCompensation.Insert(history, lagCompensationSettings.historyLimit, NetworkTime.localTime, capture); + } + + protected virtual void OnDrawGizmos() + { + // draw history + Gizmos.color = historyColor; + LagCompensation.DrawGizmos(history); + } + + // sampling //////////////////////////////////////////////////////////// + // sample the sub-tick (=interpolated) history of this object for a hit test. + // 'viewer' needs to be the player who fired! + // for example, if A fires at B, then call B.Sample(viewer, point, tolerance). + [Server] + public virtual bool Sample(NetworkConnectionToClient viewer, out Capture3D sample) + { + // never trust the client: estimate client time instead. + // https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking + // the estimation is very good. the error is as low as ~6ms for the demo. + // note that passing 'rtt' is fine: EstimateTime halves it to latency. + double estimatedTime = LagCompensation.EstimateTime(NetworkTime.localTime, viewer.rtt, NetworkClient.bufferTime); + + // sample the history to get the nearest snapshots around 'timestamp' + if (LagCompensation.Sample(history, estimatedTime, lagCompensationSettings.captureInterval, out Capture3D resultBefore, out Capture3D resultAfter, out double t)) + { + // interpolate to get a decent estimation at exactly 'timestamp' + sample = Capture3D.Interpolate(resultBefore, resultAfter, t); + return true; + } + else Debug.Log($"CmdClicked: history doesn't contain {estimatedTime:F3}"); + + sample = default; + return false; + } + + // convenience tests /////////////////////////////////////////////////// + // there are multiple different ways to check a hit against the sample: + // - raycasting + // - bounds.contains + // - increasing bounds by tolerance and checking contains + // - threshold to bounds.closestpoint + // let's offer a few solutions directly and see which users prefer. + + // bounds check: checks distance to closest point on bounds in history @ -rtt. + // 'viewer' needs to be the player who fired! + // for example, if A fires at B, then call B.Sample(viewer, point, tolerance). + // this is super simple and fast, but not 100% physically accurate since we don't raycast. + [Server] + public virtual bool BoundsCheck( + NetworkConnectionToClient viewer, + Vector3 hitPoint, + float toleranceDistance, + out float distance, + out Vector3 nearest) + { + // first, sample the history at -rtt of the viewer. + if (Sample(viewer, out Capture3D capture)) + { + // now that we know where the other player was at that time, + // we can see if the hit point was within tolerance of it. + // TODO consider rotations??? + // TODO consider original collider shape?? + Bounds bounds = new Bounds(capture.position, capture.size); + nearest = bounds.ClosestPoint(hitPoint); + distance = Vector3.Distance(nearest, hitPoint); + return distance <= toleranceDistance; + } + nearest = hitPoint; + distance = 0; + return false; + } + + // raycast check: creates a collider the sampled position and raycasts to hitPoint. + // 'viewer' needs to be the player who fired! + // for example, if A fires at B, then call B.Sample(viewer, point, tolerance). + // this is physically accurate (checks against walls etc.), with the cost + // of a runtime instantiation. + // + // originPoint: where the player fired the weapon. + // hitPoint: where the player's local raycast hit. + // tolerance: scale up the sampled collider by % in order to have a bit of a tolerance. + // 0 means no extra tolerance, 0.05 means 5% extra tolerance. + // layerMask: the layer mask to use for the raycast. + [Server] + public virtual bool RaycastCheck( + NetworkConnectionToClient viewer, + Vector3 originPoint, + Vector3 hitPoint, + float tolerancePercent, + int layerMask, + out RaycastHit hit) + { + // first, sample the history at -rtt of the viewer. + if (Sample(viewer, out Capture3D capture)) + { + // instantiate a real physics collider on demand. + // TODO rotation?? + // TODO different collier types?? + GameObject temp = new GameObject("LagCompensatorTest"); + temp.transform.position = capture.position; + BoxCollider tempCollider = temp.AddComponent(); + tempCollider.size = capture.size * (1 + tolerancePercent); + + // raycast + Vector3 direction = hitPoint - originPoint; + float maxDistance = direction.magnitude * 2; + bool result = Physics.Raycast(originPoint, direction, out hit, maxDistance, layerMask); + + // cleanup + Destroy(temp); + return result; + } + + hit = default; + return false; + } + } +} diff --git a/Assets/Mirror/Components/LagCompensation/LagCompensator.cs.meta b/Assets/Mirror/Components/LagCompensation/LagCompensator.cs.meta new file mode 100644 index 0000000..d4912e4 --- /dev/null +++ b/Assets/Mirror/Components/LagCompensation/LagCompensator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a898831dd60c4cdfbfd9a6ea5702ed01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/Mirror.Components.asmdef b/Assets/Mirror/Components/Mirror.Components.asmdef new file mode 100644 index 0000000..90c360e --- /dev/null +++ b/Assets/Mirror/Components/Mirror.Components.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Mirror.Components", + "rootNamespace": "", + "references": [ + "GUID:30817c1a0e6d646d99c048fc403f5979" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Components/Mirror.Components.asmdef.meta b/Assets/Mirror/Components/Mirror.Components.asmdef.meta new file mode 100644 index 0000000..263b6f0 --- /dev/null +++ b/Assets/Mirror/Components/Mirror.Components.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 72872094b21c16e48b631b2224833d49 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkAnimator.cs b/Assets/Mirror/Components/NetworkAnimator.cs new file mode 100644 index 0000000..2189098 --- /dev/null +++ b/Assets/Mirror/Components/NetworkAnimator.cs @@ -0,0 +1,655 @@ +using System.Linq; +using UnityEngine; +using UnityEngine.Serialization; + +namespace Mirror +{ + /// + /// A component to synchronize Mecanim animation states for networked objects. + /// + /// + /// The animation of game objects can be networked by this component. There are two models of authority for networked movement: + /// If the object has authority on the client, then it should be animated locally on the owning client. The animation state information will be sent from the owning client to the server, then broadcast to all of the other clients. This is common for player objects. + /// If the object has authority on the server, then it should be animated on the server and state information will be sent to all clients. This is common for objects not related to a specific client, such as an enemy unit. + /// The NetworkAnimator synchronizes all animation parameters of the selected Animator. It does not automatically synchronize triggers. The function SetTrigger can by used by an object with authority to fire an animation trigger on other clients. + /// + // [RequireComponent(typeof(NetworkIdentity))] disabled to allow child NetworkBehaviours + [AddComponentMenu("Network/Network Animator")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-animator")] + public class NetworkAnimator : NetworkBehaviour + { + [Header("Authority")] + [Tooltip("Set to true if animations come from owner client, set to false if animations always come from server")] + public bool clientAuthority; + + /// + /// The animator component to synchronize. + /// + [FormerlySerializedAs("m_Animator")] + [Header("Animator")] + [Tooltip("Animator that will have parameters synchronized")] + public Animator animator; + + /// + /// Syncs animator.speed + /// + [SyncVar(hook = nameof(OnAnimatorSpeedChanged))] + float animatorSpeed; + float previousSpeed; + + // Note: not an object[] array because otherwise initialization is real annoying + int[] lastIntParameters; + float[] lastFloatParameters; + bool[] lastBoolParameters; + AnimatorControllerParameter[] parameters; + + // multiple layers + int[] animationHash; + int[] transitionHash; + float[] layerWeight; + double nextSendTime; + + bool SendMessagesAllowed + { + get + { + if (isServer) + { + if (!clientAuthority) + return true; + + // This is a special case where we have client authority but we have not assigned the client who has + // authority over it, no animator data will be sent over the network by the server. + // + // So we check here for a connectionToClient and if it is null we will + // let the server send animation data until we receive an owner. + if (netIdentity != null && netIdentity.connectionToClient == null) + return true; + } + + return (isOwned && clientAuthority); + } + } + + void Initialize() + { + // store the animator parameters in a variable - the "Animator.parameters" getter allocates + // a new parameter array every time it is accessed so we should avoid doing it in a loop + parameters = animator.parameters + .Where(par => !animator.IsParameterControlledByCurve(par.nameHash)) + .ToArray(); + lastIntParameters = new int[parameters.Length]; + lastFloatParameters = new float[parameters.Length]; + lastBoolParameters = new bool[parameters.Length]; + + animationHash = new int[animator.layerCount]; + transitionHash = new int[animator.layerCount]; + layerWeight = new float[animator.layerCount]; + } + + // fix https://github.com/MirrorNetworking/Mirror/issues/2810 + // both Awake and Enable need to initialize arrays. + // in case users call SetActive(false) -> SetActive(true). + void Awake() => Initialize(); + void OnEnable() => Initialize(); + + public virtual void Reset() + { + syncDirection = SyncDirection.ClientToServer; + } + + void FixedUpdate() + { + if (!SendMessagesAllowed) + return; + + if (!animator.enabled) + return; + + CheckSendRate(); + + for (int i = 0; i < animator.layerCount; i++) + { + int stateHash; + float normalizedTime; + if (!CheckAnimStateChanged(out stateHash, out normalizedTime, i)) + { + continue; + } + + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + WriteParameters(writer); + SendAnimationMessage(stateHash, normalizedTime, i, layerWeight[i], writer.ToArray()); + } + } + + CheckSpeed(); + } + + void CheckSpeed() + { + float newSpeed = animator.speed; + if (Mathf.Abs(previousSpeed - newSpeed) > 0.001f) + { + previousSpeed = newSpeed; + if (isServer) + { + animatorSpeed = newSpeed; + } + else if (isClient) + { + CmdSetAnimatorSpeed(newSpeed); + } + } + } + + void OnAnimatorSpeedChanged(float _, float value) + { + // skip if host or client with authority + // they will have already set the speed so don't set again + if (isServer || (isOwned && clientAuthority)) + return; + + animator.speed = value; + } + + bool CheckAnimStateChanged(out int stateHash, out float normalizedTime, int layerId) + { + bool change = false; + stateHash = 0; + normalizedTime = 0; + + float lw = animator.GetLayerWeight(layerId); + if (Mathf.Abs(lw - layerWeight[layerId]) > 0.001f) + { + layerWeight[layerId] = lw; + change = true; + } + + if (animator.IsInTransition(layerId)) + { + AnimatorTransitionInfo tt = animator.GetAnimatorTransitionInfo(layerId); + if (tt.fullPathHash != transitionHash[layerId]) + { + // first time in this transition + transitionHash[layerId] = tt.fullPathHash; + animationHash[layerId] = 0; + return true; + } + return change; + } + + AnimatorStateInfo st = animator.GetCurrentAnimatorStateInfo(layerId); + if (st.fullPathHash != animationHash[layerId]) + { + // first time in this animation state + if (animationHash[layerId] != 0) + { + // came from another animation directly - from Play() + stateHash = st.fullPathHash; + normalizedTime = st.normalizedTime; + } + transitionHash[layerId] = 0; + animationHash[layerId] = st.fullPathHash; + return true; + } + return change; + } + + void CheckSendRate() + { + double now = NetworkTime.localTime; + if (SendMessagesAllowed && syncInterval >= 0 && now > nextSendTime) + { + nextSendTime = now + syncInterval; + + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + if (WriteParameters(writer)) + SendAnimationParametersMessage(writer.ToArray()); + } + } + } + + void SendAnimationMessage(int stateHash, float normalizedTime, int layerId, float weight, byte[] parameters) + { + if (isServer) + { + RpcOnAnimationClientMessage(stateHash, normalizedTime, layerId, weight, parameters); + } + else if (isClient) + { + CmdOnAnimationServerMessage(stateHash, normalizedTime, layerId, weight, parameters); + } + } + + void SendAnimationParametersMessage(byte[] parameters) + { + if (isServer) + { + RpcOnAnimationParametersClientMessage(parameters); + } + else if (isClient) + { + CmdOnAnimationParametersServerMessage(parameters); + } + } + + void HandleAnimMsg(int stateHash, float normalizedTime, int layerId, float weight, NetworkReader reader) + { + if (isOwned && clientAuthority) + return; + + // usually transitions will be triggered by parameters, if not, play anims directly. + // NOTE: this plays "animations", not transitions, so any transitions will be skipped. + // NOTE: there is no API to play a transition(?) + if (stateHash != 0 && animator.enabled) + { + animator.Play(stateHash, layerId, normalizedTime); + } + + animator.SetLayerWeight(layerId, weight); + + ReadParameters(reader); + } + + void HandleAnimParamsMsg(NetworkReader reader) + { + if (isOwned && clientAuthority) + return; + + ReadParameters(reader); + } + + void HandleAnimTriggerMsg(int hash) + { + if (animator.enabled) + animator.SetTrigger(hash); + } + + void HandleAnimResetTriggerMsg(int hash) + { + if (animator.enabled) + animator.ResetTrigger(hash); + } + + ulong NextDirtyBits() + { + ulong dirtyBits = 0; + for (int i = 0; i < parameters.Length; i++) + { + AnimatorControllerParameter par = parameters[i]; + bool changed = false; + if (par.type == AnimatorControllerParameterType.Int) + { + int newIntValue = animator.GetInteger(par.nameHash); + changed = newIntValue != lastIntParameters[i]; + if (changed) + lastIntParameters[i] = newIntValue; + } + else if (par.type == AnimatorControllerParameterType.Float) + { + float newFloatValue = animator.GetFloat(par.nameHash); + changed = Mathf.Abs(newFloatValue - lastFloatParameters[i]) > 0.001f; + // only set lastValue if it was changed, otherwise value could slowly drift within the 0.001f limit each frame + if (changed) + lastFloatParameters[i] = newFloatValue; + } + else if (par.type == AnimatorControllerParameterType.Bool) + { + bool newBoolValue = animator.GetBool(par.nameHash); + changed = newBoolValue != lastBoolParameters[i]; + if (changed) + lastBoolParameters[i] = newBoolValue; + } + if (changed) + { + dirtyBits |= 1ul << i; + } + } + return dirtyBits; + } + + bool WriteParameters(NetworkWriter writer, bool forceAll = false) + { + // fix: https://github.com/MirrorNetworking/Mirror/issues/2852 + // serialize parameterCount to be 100% sure we deserialize correct amount of bytes. + // (255 parameters should be enough for everyone, write it as byte) + byte parameterCount = (byte)parameters.Length; + writer.WriteByte(parameterCount); + + ulong dirtyBits = forceAll ? (~0ul) : NextDirtyBits(); + writer.WriteULong(dirtyBits); + + // iterate on byte count. if it's >256, it won't break + // serialization - just not serialize excess layers. + for (int i = 0; i < parameterCount; i++) + { + if ((dirtyBits & (1ul << i)) == 0) + continue; + + AnimatorControllerParameter par = parameters[i]; + if (par.type == AnimatorControllerParameterType.Int) + { + int newIntValue = animator.GetInteger(par.nameHash); + writer.WriteInt(newIntValue); + } + else if (par.type == AnimatorControllerParameterType.Float) + { + float newFloatValue = animator.GetFloat(par.nameHash); + writer.WriteFloat(newFloatValue); + } + else if (par.type == AnimatorControllerParameterType.Bool) + { + bool newBoolValue = animator.GetBool(par.nameHash); + writer.WriteBool(newBoolValue); + } + } + return dirtyBits != 0; + } + + void ReadParameters(NetworkReader reader) + { + // fix: https://github.com/MirrorNetworking/Mirror/issues/2852 + // serialize parameterCount to be 100% sure we deserialize correct amount of bytes. + // mismatch shows error to make this super easy to debug. + byte parameterCount = reader.ReadByte(); + if (parameterCount != parameters.Length) + { + Debug.LogError($"NetworkAnimator: serialized parameter count={parameterCount} does not match expected parameter count={parameters.Length}. Are you changing animators at runtime?", gameObject); + return; + } + + bool animatorEnabled = animator.enabled; + // need to read values from NetworkReader even if animator is disabled + ulong dirtyBits = reader.ReadULong(); + for (int i = 0; i < parameterCount; i++) + { + if ((dirtyBits & (1ul << i)) == 0) + continue; + + AnimatorControllerParameter par = parameters[i]; + if (par.type == AnimatorControllerParameterType.Int) + { + int newIntValue = reader.ReadInt(); + if (animatorEnabled) + animator.SetInteger(par.nameHash, newIntValue); + } + else if (par.type == AnimatorControllerParameterType.Float) + { + float newFloatValue = reader.ReadFloat(); + if (animatorEnabled) + animator.SetFloat(par.nameHash, newFloatValue); + } + else if (par.type == AnimatorControllerParameterType.Bool) + { + bool newBoolValue = reader.ReadBool(); + if (animatorEnabled) + animator.SetBool(par.nameHash, newBoolValue); + } + } + } + + public override void OnSerialize(NetworkWriter writer, bool initialState) + { + base.OnSerialize(writer, initialState); + if (initialState) + { + // fix: https://github.com/MirrorNetworking/Mirror/issues/2852 + // serialize layerCount to be 100% sure we deserialize correct amount of bytes. + // (255 layers should be enough for everyone, write it as byte) + byte layerCount = (byte)animator.layerCount; + writer.WriteByte(layerCount); + + // iterate on byte count. if it's >256, it won't break + // serialization - just not serialize excess layers. + for (int i = 0; i < layerCount; i++) + { + AnimatorStateInfo st = animator.IsInTransition(i) + ? animator.GetNextAnimatorStateInfo(i) + : animator.GetCurrentAnimatorStateInfo(i); + writer.WriteInt(st.fullPathHash); + writer.WriteFloat(st.normalizedTime); + writer.WriteFloat(animator.GetLayerWeight(i)); + } + WriteParameters(writer, true); + } + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + base.OnDeserialize(reader, initialState); + if (initialState) + { + // fix: https://github.com/MirrorNetworking/Mirror/issues/2852 + // serialize layerCount to be 100% sure we deserialize correct amount of bytes. + // mismatch shows error to make this super easy to debug. + byte layerCount = reader.ReadByte(); + if (layerCount != animator.layerCount) + { + Debug.LogError($"NetworkAnimator: serialized layer count={layerCount} does not match expected layer count={animator.layerCount}. Are you changing animators at runtime?", gameObject); + return; + } + + for (int i = 0; i < layerCount; i++) + { + int stateHash = reader.ReadInt(); + float normalizedTime = reader.ReadFloat(); + float weight = reader.ReadFloat(); + + animator.SetLayerWeight(i, weight); + animator.Play(stateHash, i, normalizedTime); + } + + ReadParameters(reader); + } + } + + /// + /// Causes an animation trigger to be invoked for a networked object. + /// If local authority is set, and this is called from the client, then the trigger will be invoked on the server and all clients. If not, then this is called on the server, and the trigger will be called on all clients. + /// + /// Name of trigger. + public void SetTrigger(string triggerName) + { + SetTrigger(Animator.StringToHash(triggerName)); + } + + /// + /// Causes an animation trigger to be invoked for a networked object. + /// + /// Hash id of trigger (from the Animator). + public void SetTrigger(int hash) + { + if (clientAuthority) + { + if (!isClient) + { + Debug.LogWarning("Tried to set animation in the server for a client-controlled animator", gameObject); + return; + } + + if (!isOwned) + { + Debug.LogWarning("Only the client with authority can set animations", gameObject); + return; + } + + if (isClient) + CmdOnAnimationTriggerServerMessage(hash); + + // call on client right away + HandleAnimTriggerMsg(hash); + } + else + { + if (!isServer) + { + Debug.LogWarning("Tried to set animation in the client for a server-controlled animator", gameObject); + return; + } + + HandleAnimTriggerMsg(hash); + RpcOnAnimationTriggerClientMessage(hash); + } + } + + /// + /// Causes an animation trigger to be reset for a networked object. + /// If local authority is set, and this is called from the client, then the trigger will be reset on the server and all clients. If not, then this is called on the server, and the trigger will be reset on all clients. + /// + /// Name of trigger. + public void ResetTrigger(string triggerName) + { + ResetTrigger(Animator.StringToHash(triggerName)); + } + + /// Causes an animation trigger to be reset for a networked object. + /// Hash id of trigger (from the Animator). + public void ResetTrigger(int hash) + { + if (clientAuthority) + { + if (!isClient) + { + Debug.LogWarning("Tried to reset animation in the server for a client-controlled animator", gameObject); + return; + } + + if (!isOwned) + { + Debug.LogWarning("Only the client with authority can reset animations", gameObject); + return; + } + + if (isClient) + CmdOnAnimationResetTriggerServerMessage(hash); + + // call on client right away + HandleAnimResetTriggerMsg(hash); + } + else + { + if (!isServer) + { + Debug.LogWarning("Tried to reset animation in the client for a server-controlled animator", gameObject); + return; + } + + HandleAnimResetTriggerMsg(hash); + RpcOnAnimationResetTriggerClientMessage(hash); + } + } + + #region server message handlers + + [Command] + void CmdOnAnimationServerMessage(int stateHash, float normalizedTime, int layerId, float weight, byte[] parameters) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + //Debug.Log($"OnAnimationMessage for netId {netId}"); + + // handle and broadcast + using (NetworkReaderPooled networkReader = NetworkReaderPool.Get(parameters)) + { + HandleAnimMsg(stateHash, normalizedTime, layerId, weight, networkReader); + RpcOnAnimationClientMessage(stateHash, normalizedTime, layerId, weight, parameters); + } + } + + [Command] + void CmdOnAnimationParametersServerMessage(byte[] parameters) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + // handle and broadcast + using (NetworkReaderPooled networkReader = NetworkReaderPool.Get(parameters)) + { + HandleAnimParamsMsg(networkReader); + RpcOnAnimationParametersClientMessage(parameters); + } + } + + [Command] + void CmdOnAnimationTriggerServerMessage(int hash) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + // handle and broadcast + // host should have already the trigger + bool isHostOwner = isClient && isOwned; + if (!isHostOwner) + { + HandleAnimTriggerMsg(hash); + } + + RpcOnAnimationTriggerClientMessage(hash); + } + + [Command] + void CmdOnAnimationResetTriggerServerMessage(int hash) + { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + + // handle and broadcast + // host should have already the trigger + bool isHostOwner = isClient && isOwned; + if (!isHostOwner) + { + HandleAnimResetTriggerMsg(hash); + } + + RpcOnAnimationResetTriggerClientMessage(hash); + } + + [Command] + void CmdSetAnimatorSpeed(float newSpeed) + { + // set animator + animator.speed = newSpeed; + animatorSpeed = newSpeed; + } + + #endregion + + #region client message handlers + + [ClientRpc] + void RpcOnAnimationClientMessage(int stateHash, float normalizedTime, int layerId, float weight, byte[] parameters) + { + using (NetworkReaderPooled networkReader = NetworkReaderPool.Get(parameters)) + HandleAnimMsg(stateHash, normalizedTime, layerId, weight, networkReader); + } + + [ClientRpc] + void RpcOnAnimationParametersClientMessage(byte[] parameters) + { + using (NetworkReaderPooled networkReader = NetworkReaderPool.Get(parameters)) + HandleAnimParamsMsg(networkReader); + } + + [ClientRpc(includeOwner = false)] + void RpcOnAnimationTriggerClientMessage(int hash) + { + HandleAnimTriggerMsg(hash); + } + + [ClientRpc(includeOwner = false)] + void RpcOnAnimationResetTriggerClientMessage(int hash) + { + HandleAnimResetTriggerMsg(hash); + } + + #endregion + } +} diff --git a/Assets/Mirror/Components/NetworkAnimator.cs.meta b/Assets/Mirror/Components/NetworkAnimator.cs.meta new file mode 100644 index 0000000..211ce78 --- /dev/null +++ b/Assets/Mirror/Components/NetworkAnimator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f6f3bf89aa97405989c802ba270f815 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkDiagnosticsDebugger.cs b/Assets/Mirror/Components/NetworkDiagnosticsDebugger.cs new file mode 100644 index 0000000..021b791 --- /dev/null +++ b/Assets/Mirror/Components/NetworkDiagnosticsDebugger.cs @@ -0,0 +1,30 @@ +using UnityEngine; + +namespace Mirror +{ + public class NetworkDiagnosticsDebugger : MonoBehaviour + { + public bool logInMessages = true; + public bool logOutMessages = true; + void OnInMessage(NetworkDiagnostics.MessageInfo msgInfo) + { + if (logInMessages) + Debug.Log(msgInfo); + } + void OnOutMessage(NetworkDiagnostics.MessageInfo msgInfo) + { + if (logOutMessages) + Debug.Log(msgInfo); + } + void OnEnable() + { + NetworkDiagnostics.InMessageEvent += OnInMessage; + NetworkDiagnostics.OutMessageEvent += OnOutMessage; + } + void OnDisable() + { + NetworkDiagnostics.InMessageEvent -= OnInMessage; + NetworkDiagnostics.OutMessageEvent -= OnOutMessage; + } + } +} diff --git a/Assets/Mirror/Components/NetworkDiagnosticsDebugger.cs.meta b/Assets/Mirror/Components/NetworkDiagnosticsDebugger.cs.meta new file mode 100644 index 0000000..5a9819e --- /dev/null +++ b/Assets/Mirror/Components/NetworkDiagnosticsDebugger.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bc9f0a0fe4124424b8f9d4927795ee01 +timeCreated: 1700945893 \ No newline at end of file diff --git a/Assets/Mirror/Components/NetworkLobbyManager.cs b/Assets/Mirror/Components/NetworkLobbyManager.cs new file mode 100644 index 0000000..3dcd4ea --- /dev/null +++ b/Assets/Mirror/Components/NetworkLobbyManager.cs @@ -0,0 +1,18 @@ +using System; +using UnityEngine; + +namespace Mirror +{ + /// + /// This is a specialized NetworkManager that includes a networked lobby. + /// + /// + /// The lobby has slots that track the joined players, and a maximum player count that is enforced. It requires that the NetworkLobbyPlayer component be on the lobby player objects. + /// NetworkLobbyManager is derived from NetworkManager, and so it implements many of the virtual functions provided by the NetworkManager class. To avoid accidentally replacing functionality of the NetworkLobbyManager, there are new virtual functions on the NetworkLobbyManager that begin with "OnLobby". These should be used on classes derived from NetworkLobbyManager instead of the virtual functions on NetworkManager. + /// The OnLobby*() functions have empty implementations on the NetworkLobbyManager base class, so the base class functions do not have to be called. + /// + [AddComponentMenu("Network/Network Lobby Manager")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-room-manager")] + [Obsolete("Use / inherit from NetworkRoomManager instead")] + public class NetworkLobbyManager : NetworkRoomManager {} +} diff --git a/Assets/Mirror/Components/NetworkLobbyManager.cs.meta b/Assets/Mirror/Components/NetworkLobbyManager.cs.meta new file mode 100644 index 0000000..a32c8c7 --- /dev/null +++ b/Assets/Mirror/Components/NetworkLobbyManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4c96e6dd99826849ab1431f94547141 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkLobbyPlayer.cs b/Assets/Mirror/Components/NetworkLobbyPlayer.cs new file mode 100644 index 0000000..95ffbbc --- /dev/null +++ b/Assets/Mirror/Components/NetworkLobbyPlayer.cs @@ -0,0 +1,15 @@ +using System; +using UnityEngine; + +namespace Mirror +{ + /// + /// This component works in conjunction with the NetworkLobbyManager to make up the multiplayer lobby system. + /// The LobbyPrefab object of the NetworkLobbyManager must have this component on it. This component holds basic lobby player data required for the lobby to function. Game specific data for lobby players can be put in other components on the LobbyPrefab or in scripts derived from NetworkLobbyPlayer. + /// + [DisallowMultipleComponent] + [AddComponentMenu("Network/Network Lobby Player")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-room-player")] + [Obsolete("Use / inherit from NetworkRoomPlayer instead")] + public class NetworkLobbyPlayer : NetworkRoomPlayer {} +} diff --git a/Assets/Mirror/Components/NetworkLobbyPlayer.cs.meta b/Assets/Mirror/Components/NetworkLobbyPlayer.cs.meta new file mode 100644 index 0000000..7a21eec --- /dev/null +++ b/Assets/Mirror/Components/NetworkLobbyPlayer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 777a368af85f2e84da7ea5666581921b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkPingDisplay.cs b/Assets/Mirror/Components/NetworkPingDisplay.cs new file mode 100644 index 0000000..255e62d --- /dev/null +++ b/Assets/Mirror/Components/NetworkPingDisplay.cs @@ -0,0 +1,39 @@ +using System; +using UnityEngine; + +namespace Mirror +{ + /// + /// Component that will display the clients ping in milliseconds + /// + [DisallowMultipleComponent] + [AddComponentMenu("Network/Network Ping Display")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-ping-display")] + public class NetworkPingDisplay : MonoBehaviour + { + public Color color = Color.white; + public int padding = 2; + public int width = 150; + public int height = 25; + + void OnGUI() + { + // only while client is active + if (!NetworkClient.active) return; + + // show stats in bottom right corner, right aligned + GUI.color = color; + Rect rect = new Rect(Screen.width - width - padding, Screen.height - height - padding, width, height); + GUILayout.BeginArea(rect); + GUIStyle style = GUI.skin.GetStyle("Label"); + style.alignment = TextAnchor.MiddleRight; + GUILayout.BeginHorizontal(style); + GUILayout.Label($"RTT: {Math.Round(NetworkTime.rtt * 1000)}ms"); + GUI.color = NetworkClient.connectionQuality.ColorCode(); + GUILayout.Label($"Q: {new string('-', (int)NetworkClient.connectionQuality)}"); + GUILayout.EndHorizontal(); + GUILayout.EndArea(); + GUI.color = Color.white; + } + } +} diff --git a/Assets/Mirror/Components/NetworkPingDisplay.cs.meta b/Assets/Mirror/Components/NetworkPingDisplay.cs.meta new file mode 100644 index 0000000..221a745 --- /dev/null +++ b/Assets/Mirror/Components/NetworkPingDisplay.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc654f29862fc2643b948f772ebb9e68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkRigidbody.meta b/Assets/Mirror/Components/NetworkRigidbody.meta new file mode 100644 index 0000000..a67178e --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 80106690aef541a5b8e2f8fb3d5949ad +timeCreated: 1686733778 \ No newline at end of file diff --git a/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable.cs b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable.cs new file mode 100644 index 0000000..4611d3b --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable.cs @@ -0,0 +1,96 @@ +using UnityEngine; + +namespace Mirror +{ + // [RequireComponent(typeof(Rigidbody))] <- OnValidate ensures this is on .target + public class NetworkRigidbodyReliable : NetworkTransformReliable + { + bool clientAuthority => syncDirection == SyncDirection.ClientToServer; + + Rigidbody rb; + bool wasKinematic; + + // cach Rigidbody and original isKinematic setting + protected override void Awake() + { + // we can't overwrite .target to be a Rigidbody. + // but we can use its Rigidbody component. + rb = target.GetComponent(); + if (rb == null) + { + Debug.LogError($"{name}'s NetworkRigidbody.target {target.name} is missing a Rigidbody", this); + return; + } + wasKinematic = rb.isKinematic; + base.Awake(); + } + + // reset forced isKinematic flag to original. + // otherwise the overwritten value would remain between sessions forever. + // for example, a game may run as client, set rigidbody.iskinematic=true, + // then run as server, where .iskinematic isn't touched and remains at + // the overwritten=true, even though the user set it to false originally. + public override void OnStopServer() => rb.isKinematic = wasKinematic; + public override void OnStopClient() => rb.isKinematic = wasKinematic; + + // overwriting Construct() and Apply() to set Rigidbody.MovePosition + // would give more jittery movement. + + // FixedUpdate for physics + void FixedUpdate() + { + // who ever has authority moves the Rigidbody with physics. + // everyone else simply sets it to kinematic. + // so that only the Transform component is synced. + + // host mode + if (isServer && isClient) + { + // in host mode, we own it it if: + // clientAuthority is disabled (hence server / we own it) + // clientAuthority is enabled and we have authority over this object. + bool owned = !clientAuthority || IsClientWithAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + // client only + else if (isClient) + { + // on the client, we own it only if clientAuthority is enabled, + // and we have authority over this object. + bool owned = IsClientWithAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + // server only + else if (isServer) + { + // on the server, we always own it if clientAuthority is disabled. + bool owned = !clientAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + } + + protected override void OnValidate() + { + base.OnValidate(); + + // we can't overwrite .target to be a Rigidbody. + // but we can ensure that .target has a Rigidbody, and use it. + if (target.GetComponent() == null) + { + Debug.LogWarning($"{name}'s NetworkRigidbody.target {target.name} is missing a Rigidbody", this); + } + } + } +} diff --git a/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable.cs.meta b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable.cs.meta new file mode 100644 index 0000000..b3b61c9 --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cb803efbe62c34d7baece46c9ffebad9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable2D.cs b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable2D.cs new file mode 100644 index 0000000..82bc25b --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable2D.cs @@ -0,0 +1,96 @@ +using UnityEngine; + +namespace Mirror +{ + // [RequireComponent(typeof(Rigidbody))] <- OnValidate ensures this is on .target + public class NetworkRigidbodyReliable2D : NetworkTransformReliable + { + bool clientAuthority => syncDirection == SyncDirection.ClientToServer; + + Rigidbody2D rb; + bool wasKinematic; + + // cach Rigidbody and original isKinematic setting + protected override void Awake() + { + // we can't overwrite .target to be a Rigidbody. + // but we can use its Rigidbody component. + rb = target.GetComponent(); + if (rb == null) + { + Debug.LogError($"{name}'s NetworkRigidbody2D.target {target.name} is missing a Rigidbody2D", this); + return; + } + wasKinematic = rb.isKinematic; + base.Awake(); + } + + // reset forced isKinematic flag to original. + // otherwise the overwritten value would remain between sessions forever. + // for example, a game may run as client, set rigidbody.iskinematic=true, + // then run as server, where .iskinematic isn't touched and remains at + // the overwritten=true, even though the user set it to false originally. + public override void OnStopServer() => rb.isKinematic = wasKinematic; + public override void OnStopClient() => rb.isKinematic = wasKinematic; + + // overwriting Construct() and Apply() to set Rigidbody.MovePosition + // would give more jittery movement. + + // FixedUpdate for physics + void FixedUpdate() + { + // who ever has authority moves the Rigidbody with physics. + // everyone else simply sets it to kinematic. + // so that only the Transform component is synced. + + // host mode + if (isServer && isClient) + { + // in host mode, we own it it if: + // clientAuthority is disabled (hence server / we own it) + // clientAuthority is enabled and we have authority over this object. + bool owned = !clientAuthority || IsClientWithAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + // client only + else if (isClient) + { + // on the client, we own it only if clientAuthority is enabled, + // and we have authority over this object. + bool owned = IsClientWithAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + // server only + else if (isServer) + { + // on the server, we always own it if clientAuthority is disabled. + bool owned = !clientAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + } + + protected override void OnValidate() + { + base.OnValidate(); + + // we can't overwrite .target to be a Rigidbody. + // but we can ensure that .target has a Rigidbody, and use it. + if (target.GetComponent() == null) + { + Debug.LogWarning($"{name}'s NetworkRigidbody2D.target {target.name} is missing a Rigidbody2D", this); + } + } + } +} diff --git a/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable2D.cs.meta b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable2D.cs.meta new file mode 100644 index 0000000..172c8a4 --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyReliable2D.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ec4f7556ca1e4b55a3381fc6a02b1bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable.cs b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable.cs new file mode 100644 index 0000000..c943f18 --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable.cs @@ -0,0 +1,96 @@ +using UnityEngine; + +namespace Mirror +{ + // [RequireComponent(typeof(Rigidbody))] <- OnValidate ensures this is on .target + public class NetworkRigidbodyUnreliable : NetworkTransformUnreliable + { + bool clientAuthority => syncDirection == SyncDirection.ClientToServer; + + Rigidbody rb; + bool wasKinematic; + + // cach Rigidbody and original isKinematic setting + protected override void Awake() + { + // we can't overwrite .target to be a Rigidbody. + // but we can use its Rigidbody component. + rb = target.GetComponent(); + if (rb == null) + { + Debug.LogError($"{name}'s NetworkRigidbody.target {target.name} is missing a Rigidbody", this); + return; + } + wasKinematic = rb.isKinematic; + base.Awake(); + } + + // reset forced isKinematic flag to original. + // otherwise the overwritten value would remain between sessions forever. + // for example, a game may run as client, set rigidbody.iskinematic=true, + // then run as server, where .iskinematic isn't touched and remains at + // the overwritten=true, even though the user set it to false originally. + public override void OnStopServer() => rb.isKinematic = wasKinematic; + public override void OnStopClient() => rb.isKinematic = wasKinematic; + + // overwriting Construct() and Apply() to set Rigidbody.MovePosition + // would give more jittery movement. + + // FixedUpdate for physics + void FixedUpdate() + { + // who ever has authority moves the Rigidbody with physics. + // everyone else simply sets it to kinematic. + // so that only the Transform component is synced. + + // host mode + if (isServer && isClient) + { + // in host mode, we own it it if: + // clientAuthority is disabled (hence server / we own it) + // clientAuthority is enabled and we have authority over this object. + bool owned = !clientAuthority || IsClientWithAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + // client only + else if (isClient) + { + // on the client, we own it only if clientAuthority is enabled, + // and we have authority over this object. + bool owned = IsClientWithAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + // server only + else if (isServer) + { + // on the server, we always own it if clientAuthority is disabled. + bool owned = !clientAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + } + + protected override void OnValidate() + { + base.OnValidate(); + + // we can't overwrite .target to be a Rigidbody. + // but we can ensure that .target has a Rigidbody, and use it. + if (target.GetComponent() == null) + { + Debug.LogWarning($"{name}'s NetworkRigidbody.target {target.name} is missing a Rigidbody", this); + } + } + } +} diff --git a/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable.cs.meta b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable.cs.meta new file mode 100644 index 0000000..2dfb14b --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b20dc110904e47f8a154cdcf6433eae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable2D.cs b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable2D.cs new file mode 100644 index 0000000..c770b33 --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable2D.cs @@ -0,0 +1,96 @@ +using UnityEngine; + +namespace Mirror +{ + // [RequireComponent(typeof(Rigidbody))] <- OnValidate ensures this is on .target + public class NetworkRigidbodyUnreliable2D : NetworkTransformUnreliable + { + bool clientAuthority => syncDirection == SyncDirection.ClientToServer; + + Rigidbody2D rb; + bool wasKinematic; + + // cach Rigidbody and original isKinematic setting + protected override void Awake() + { + // we can't overwrite .target to be a Rigidbody. + // but we can use its Rigidbody component. + rb = target.GetComponent(); + if (rb == null) + { + Debug.LogError($"{name}'s NetworkRigidbody2D.target {target.name} is missing a Rigidbody2D", this); + return; + } + wasKinematic = rb.isKinematic; + base.Awake(); + } + + // reset forced isKinematic flag to original. + // otherwise the overwritten value would remain between sessions forever. + // for example, a game may run as client, set rigidbody.iskinematic=true, + // then run as server, where .iskinematic isn't touched and remains at + // the overwritten=true, even though the user set it to false originally. + public override void OnStopServer() => rb.isKinematic = wasKinematic; + public override void OnStopClient() => rb.isKinematic = wasKinematic; + + // overwriting Construct() and Apply() to set Rigidbody.MovePosition + // would give more jittery movement. + + // FixedUpdate for physics + void FixedUpdate() + { + // who ever has authority moves the Rigidbody with physics. + // everyone else simply sets it to kinematic. + // so that only the Transform component is synced. + + // host mode + if (isServer && isClient) + { + // in host mode, we own it it if: + // clientAuthority is disabled (hence server / we own it) + // clientAuthority is enabled and we have authority over this object. + bool owned = !clientAuthority || IsClientWithAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + // client only + else if (isClient) + { + // on the client, we own it only if clientAuthority is enabled, + // and we have authority over this object. + bool owned = IsClientWithAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + // server only + else if (isServer) + { + // on the server, we always own it if clientAuthority is disabled. + bool owned = !clientAuthority; + + // only set to kinematic if we don't own it + // otherwise don't touch isKinematic. + // the authority owner might use it either way. + if (!owned) rb.isKinematic = true; + } + } + + protected override void OnValidate() + { + base.OnValidate(); + + // we can't overwrite .target to be a Rigidbody. + // but we can ensure that .target has a Rigidbody, and use it. + if (target.GetComponent() == null) + { + Debug.LogWarning($"{name}'s NetworkRigidbody2D.target {target.name} is missing a Rigidbody2D", this); + } + } + } +} diff --git a/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable2D.cs.meta b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable2D.cs.meta new file mode 100644 index 0000000..8a19149 --- /dev/null +++ b/Assets/Mirror/Components/NetworkRigidbody/NetworkRigidbodyUnreliable2D.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1c7e12ad9b9ae443c9fdf37e9f5ecd36 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkRoomManager.cs b/Assets/Mirror/Components/NetworkRoomManager.cs new file mode 100644 index 0000000..11e17f2 --- /dev/null +++ b/Assets/Mirror/Components/NetworkRoomManager.cs @@ -0,0 +1,685 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.Serialization; + +namespace Mirror +{ + /// + /// This is a specialized NetworkManager that includes a networked room. + /// + /// + /// The room has slots that track the joined players, and a maximum player count that is enforced. It requires that the NetworkRoomPlayer component be on the room player objects. + /// NetworkRoomManager is derived from NetworkManager, and so it implements many of the virtual functions provided by the NetworkManager class. To avoid accidentally replacing functionality of the NetworkRoomManager, there are new virtual functions on the NetworkRoomManager that begin with "OnRoom". These should be used on classes derived from NetworkRoomManager instead of the virtual functions on NetworkManager. + /// The OnRoom*() functions have empty implementations on the NetworkRoomManager base class, so the base class functions do not have to be called. + /// + [AddComponentMenu("Network/Network Room Manager")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-room-manager")] + public class NetworkRoomManager : NetworkManager + { + public struct PendingPlayer + { + public NetworkConnectionToClient conn; + public GameObject roomPlayer; + } + + [Header("Room Settings")] + [FormerlySerializedAs("m_ShowRoomGUI")] + [SerializeField] + [Tooltip("This flag controls whether the default UI is shown for the room")] + public bool showRoomGUI = true; + + [FormerlySerializedAs("m_MinPlayers")] + [SerializeField] + [Tooltip("Minimum number of players to auto-start the game")] + public int minPlayers = 1; + + [FormerlySerializedAs("m_RoomPlayerPrefab")] + [SerializeField] + [Tooltip("Prefab to use for the Room Player")] + public NetworkRoomPlayer roomPlayerPrefab; + + /// + /// The scene to use for the room. This is similar to the offlineScene of the NetworkManager. + /// + [Scene] + public string RoomScene; + + /// + /// The scene to use for the playing the game from the room. This is similar to the onlineScene of the NetworkManager. + /// + [Scene] + public string GameplayScene; + + /// + /// List of players that are in the Room + /// + [FormerlySerializedAs("m_PendingPlayers")] + public List pendingPlayers = new List(); + + [Header("Diagnostics")] + /// + /// True when all players have submitted a Ready message + /// + [Tooltip("Diagnostic flag indicating all players are ready to play")] + [FormerlySerializedAs("allPlayersReady")] + [ReadOnly, SerializeField] bool _allPlayersReady; + + /// + /// These slots track players that enter the room. + /// The slotId on players is global to the game - across all players. + /// + [ReadOnly, Tooltip("List of Room Player objects")] + public List roomSlots = new List(); + + public bool allPlayersReady + { + get => _allPlayersReady; + set + { + bool wasReady = _allPlayersReady; + bool nowReady = value; + + if (wasReady != nowReady) + { + _allPlayersReady = value; + + if (nowReady) + { + OnRoomServerPlayersReady(); + } + else + { + OnRoomServerPlayersNotReady(); + } + } + } + } + + public override void OnValidate() + { + base.OnValidate(); + + // always <= maxConnections + minPlayers = Mathf.Min(minPlayers, maxConnections); + + // always >= 0 + minPlayers = Mathf.Max(minPlayers, 0); + + if (roomPlayerPrefab != null) + { + NetworkIdentity identity = roomPlayerPrefab.GetComponent(); + if (identity == null) + { + roomPlayerPrefab = null; + Debug.LogError("RoomPlayer prefab must have a NetworkIdentity component."); + } + } + } + + void SceneLoadedForPlayer(NetworkConnectionToClient conn, GameObject roomPlayer) + { + //Debug.Log($"NetworkRoom SceneLoadedForPlayer scene: {SceneManager.GetActiveScene().path} {conn}"); + + if (Utils.IsSceneActive(RoomScene)) + { + // cant be ready in room, add to ready list + PendingPlayer pending; + pending.conn = conn; + pending.roomPlayer = roomPlayer; + pendingPlayers.Add(pending); + return; + } + + GameObject gamePlayer = OnRoomServerCreateGamePlayer(conn, roomPlayer); + if (gamePlayer == null) + { + // get start position from base class + Transform startPos = GetStartPosition(); + gamePlayer = startPos != null + ? Instantiate(playerPrefab, startPos.position, startPos.rotation) + : Instantiate(playerPrefab, Vector3.zero, Quaternion.identity); + } + + if (!OnRoomServerSceneLoadedForPlayer(conn, roomPlayer, gamePlayer)) + return; + + // replace room player with game player + NetworkServer.ReplacePlayerForConnection(conn, gamePlayer, true); + } + + internal void CallOnClientEnterRoom() + { + OnRoomClientEnter(); + foreach (NetworkRoomPlayer player in roomSlots) + if (player != null) + { + player.OnClientEnterRoom(); + } + } + + internal void CallOnClientExitRoom() + { + OnRoomClientExit(); + foreach (NetworkRoomPlayer player in roomSlots) + if (player != null) + { + player.OnClientExitRoom(); + } + } + + /// + /// CheckReadyToBegin checks all of the players in the room to see if their readyToBegin flag is set. + /// If all of the players are ready, then the server switches from the RoomScene to the PlayScene, essentially starting the game. This is called automatically in response to NetworkRoomPlayer.CmdChangeReadyState. + /// + public void CheckReadyToBegin() + { + if (!Utils.IsSceneActive(RoomScene)) + return; + + int numberOfReadyPlayers = NetworkServer.connections.Count(conn => + conn.Value != null && + conn.Value.identity != null && + conn.Value.identity.TryGetComponent(out NetworkRoomPlayer nrp) && + nrp.readyToBegin); + + bool enoughReadyPlayers = minPlayers <= 0 || numberOfReadyPlayers >= minPlayers; + if (enoughReadyPlayers) + { + pendingPlayers.Clear(); + allPlayersReady = true; + } + else + allPlayersReady = false; + } + + #region server handlers + + /// + /// Called on the server when a new client connects. + /// Unity calls this on the Server when a Client connects to the Server. Use an override to tell the NetworkManager what to do when a client connects to the server. + /// + /// Connection from client. + public override void OnServerConnect(NetworkConnectionToClient conn) + { + // cannot join game in progress + if (!Utils.IsSceneActive(RoomScene)) + { + Debug.Log($"Not in Room scene...disconnecting {conn}"); + conn.Disconnect(); + return; + } + + base.OnServerConnect(conn); + OnRoomServerConnect(conn); + } + + /// + /// Called on the server when a client disconnects. + /// This is called on the Server when a Client disconnects from the Server. Use an override to decide what should happen when a disconnection is detected. + /// + /// Connection from client. + public override void OnServerDisconnect(NetworkConnectionToClient conn) + { + if (conn.identity != null) + { + NetworkRoomPlayer roomPlayer = conn.identity.GetComponent(); + + if (roomPlayer != null) + roomSlots.Remove(roomPlayer); + + foreach (NetworkIdentity clientOwnedObject in conn.owned) + { + roomPlayer = clientOwnedObject.GetComponent(); + if (roomPlayer != null) + roomSlots.Remove(roomPlayer); + } + } + + allPlayersReady = false; + + foreach (NetworkRoomPlayer player in roomSlots) + { + if (player != null) + player.GetComponent().readyToBegin = false; + } + + if (Utils.IsSceneActive(RoomScene)) + RecalculateRoomPlayerIndices(); + + OnRoomServerDisconnect(conn); + base.OnServerDisconnect(conn); + + if (Utils.IsHeadless()) + { + if (numPlayers < 1) + StopServer(); + } + } + + // Sequential index used in round-robin deployment of players into instances and score positioning + public int clientIndex; + + /// + /// Called on the server when a client is ready. + /// The default implementation of this function calls NetworkServer.SetClientReady() to continue the network setup process. + /// + /// Connection from client. + public override void OnServerReady(NetworkConnectionToClient conn) + { + //Debug.Log($"NetworkRoomManager OnServerReady {conn}"); + base.OnServerReady(conn); + + if (conn != null && conn.identity != null) + { + GameObject roomPlayer = conn.identity.gameObject; + + // if null or not a room player, don't replace it + if (roomPlayer != null && roomPlayer.GetComponent() != null) + SceneLoadedForPlayer(conn, roomPlayer); + } + } + + /// + /// Called on the server when a client adds a new player with NetworkClient.AddPlayer. + /// The default implementation for this function creates a new player object from the playerPrefab. + /// + /// Connection from client. + public override void OnServerAddPlayer(NetworkConnectionToClient conn) + { + // increment the index before adding the player, so first player starts at 1 + clientIndex++; + + if (Utils.IsSceneActive(RoomScene)) + { + allPlayersReady = false; + + //Debug.Log("NetworkRoomManager.OnServerAddPlayer playerPrefab: {roomPlayerPrefab.name}"); + + GameObject newRoomGameObject = OnRoomServerCreateRoomPlayer(conn); + if (newRoomGameObject == null) + newRoomGameObject = Instantiate(roomPlayerPrefab.gameObject, Vector3.zero, Quaternion.identity); + + NetworkServer.AddPlayerForConnection(conn, newRoomGameObject); + } + else + { + // Late joiners not supported...should've been kicked by OnServerDisconnect + Debug.Log($"Not in Room scene...disconnecting {conn}"); + conn.Disconnect(); + } + } + + [Server] + public void RecalculateRoomPlayerIndices() + { + if (roomSlots.Count > 0) + { + for (int i = 0; i < roomSlots.Count; i++) + { + roomSlots[i].index = i; + } + } + } + + /// + /// This causes the server to switch scenes and sets the networkSceneName. + /// Clients that connect to this server will automatically switch to this scene. This is called automatically if onlineScene or offlineScene are set, but it can be called from user code to switch scenes again while the game is in progress. This automatically sets clients to be not-ready. The clients must call NetworkClient.Ready() again to participate in the new scene. + /// + /// + public override void ServerChangeScene(string newSceneName) + { + if (newSceneName == RoomScene) + { + foreach (NetworkRoomPlayer roomPlayer in roomSlots) + { + if (roomPlayer == null) + continue; + + // find the game-player object for this connection, and destroy it + NetworkIdentity identity = roomPlayer.GetComponent(); + + if (NetworkServer.active) + { + // re-add the room object + roomPlayer.GetComponent().readyToBegin = false; + NetworkServer.ReplacePlayerForConnection(identity.connectionToClient, roomPlayer.gameObject); + } + } + + allPlayersReady = false; + } + + base.ServerChangeScene(newSceneName); + } + + /// + /// Called on the server when a scene is completed loaded, when the scene load was initiated by the server with ServerChangeScene(). + /// + /// The name of the new scene. + public override void OnServerSceneChanged(string sceneName) + { + if (sceneName != RoomScene) + { + // call SceneLoadedForPlayer on any players that become ready while we were loading the scene. + foreach (PendingPlayer pending in pendingPlayers) + SceneLoadedForPlayer(pending.conn, pending.roomPlayer); + + pendingPlayers.Clear(); + } + + OnRoomServerSceneChanged(sceneName); + } + + /// + /// This is invoked when a server is started - including when a host is started. + /// StartServer has multiple signatures, but they all cause this hook to be called. + /// + public override void OnStartServer() + { + if (string.IsNullOrWhiteSpace(RoomScene)) + { + Debug.LogError("NetworkRoomManager RoomScene is empty. Set the RoomScene in the inspector for the NetworkRoomManager"); + return; + } + + if (string.IsNullOrWhiteSpace(GameplayScene)) + { + Debug.LogError("NetworkRoomManager PlayScene is empty. Set the PlayScene in the inspector for the NetworkRoomManager"); + return; + } + + OnRoomStartServer(); + } + + /// + /// This is invoked when a host is started. + /// StartHost has multiple signatures, but they all cause this hook to be called. + /// + public override void OnStartHost() + { + OnRoomStartHost(); + } + + /// + /// This is called when a server is stopped - including when a host is stopped. + /// + public override void OnStopServer() + { + roomSlots.Clear(); + OnRoomStopServer(); + } + + /// + /// This is called when a host is stopped. + /// + public override void OnStopHost() + { + OnRoomStopHost(); + } + + #endregion + + #region client handlers + + /// + /// This is invoked when the client is started. + /// + public override void OnStartClient() + { + if (roomPlayerPrefab == null || roomPlayerPrefab.gameObject == null) + Debug.LogError("NetworkRoomManager no RoomPlayer prefab is registered. Please add a RoomPlayer prefab."); + else + NetworkClient.RegisterPrefab(roomPlayerPrefab.gameObject); + + if (playerPrefab == null) + Debug.LogError("NetworkRoomManager no GamePlayer prefab is registered. Please add a GamePlayer prefab."); + + OnRoomStartClient(); + } + + /// + /// Called on the client when connected to a server. + /// The default implementation of this function sets the client as ready and adds a player. Override the function to dictate what happens when the client connects. + /// + public override void OnClientConnect() + { + OnRoomClientConnect(); + base.OnClientConnect(); + } + + /// + /// Called on clients when disconnected from a server. + /// This is called on the client when it disconnects from the server. Override this function to decide what happens when the client disconnects. + /// + public override void OnClientDisconnect() + { + OnRoomClientDisconnect(); + base.OnClientDisconnect(); + } + + /// + /// This is called when a client is stopped. + /// + public override void OnStopClient() + { + OnRoomStopClient(); + CallOnClientExitRoom(); + roomSlots.Clear(); + } + + /// + /// Called on clients when a scene has completed loaded, when the scene load was initiated by the server. + /// Scene changes can cause player objects to be destroyed. The default implementation of OnClientSceneChanged in the NetworkManager is to add a player object for the connection if no player object exists. + /// + public override void OnClientSceneChanged() + { + if (Utils.IsSceneActive(RoomScene)) + { + if (NetworkClient.isConnected) + CallOnClientEnterRoom(); + } + else + CallOnClientExitRoom(); + + base.OnClientSceneChanged(); + OnRoomClientSceneChanged(); + } + + #endregion + + #region room server virtuals + + /// + /// This is called on the host when a host is started. + /// + public virtual void OnRoomStartHost() {} + + /// + /// This is called on the host when the host is stopped. + /// + public virtual void OnRoomStopHost() {} + + /// + /// This is called on the server when the server is started - including when a host is started. + /// + public virtual void OnRoomStartServer() {} + + /// + /// This is called on the server when the server is started - including when a host is stopped. + /// + public virtual void OnRoomStopServer() {} + + /// + /// This is called on the server when a new client connects to the server. + /// + /// The new connection. + public virtual void OnRoomServerConnect(NetworkConnectionToClient conn) {} + + /// + /// This is called on the server when a client disconnects. + /// + /// The connection that disconnected. + public virtual void OnRoomServerDisconnect(NetworkConnectionToClient conn) {} + + /// + /// This is called on the server when a networked scene finishes loading. + /// + /// Name of the new scene. + public virtual void OnRoomServerSceneChanged(string sceneName) {} + + /// + /// This allows customization of the creation of the room-player object on the server. + /// By default the roomPlayerPrefab is used to create the room-player, but this function allows that behaviour to be customized. + /// + /// The connection the player object is for. + /// The new room-player object. + public virtual GameObject OnRoomServerCreateRoomPlayer(NetworkConnectionToClient conn) + { + return null; + } + + /// + /// This allows customization of the creation of the GamePlayer object on the server. + /// By default the gamePlayerPrefab is used to create the game-player, but this function allows that behaviour to be customized. The object returned from the function will be used to replace the room-player on the connection. + /// + /// The connection the player object is for. + /// The room player object for this connection. + /// A new GamePlayer object. + public virtual GameObject OnRoomServerCreateGamePlayer(NetworkConnectionToClient conn, GameObject roomPlayer) + { + return null; + } + + /// + /// This allows customization of the creation of the GamePlayer object on the server. + /// This is only called for subsequent GamePlay scenes after the first one. + /// See OnRoomServerCreateGamePlayer(NetworkConnection, GameObject) to customize the player object for the initial GamePlay scene. + /// + /// The connection the player object is for. + public virtual void OnRoomServerAddPlayer(NetworkConnectionToClient conn) + { + base.OnServerAddPlayer(conn); + } + + // for users to apply settings from their room player object to their in-game player object + /// + /// This is called on the server when it is told that a client has finished switching from the room scene to a game player scene. + /// When switching from the room, the room-player is replaced with a game-player object. This callback function gives an opportunity to apply state from the room-player to the game-player object. + /// + /// The connection of the player + /// The room player object. + /// The game player object. + /// False to not allow this player to replace the room player. + public virtual bool OnRoomServerSceneLoadedForPlayer(NetworkConnectionToClient conn, GameObject roomPlayer, GameObject gamePlayer) + { + return true; + } + + /// + /// This is called on server from NetworkRoomPlayer.CmdChangeReadyState when client indicates change in Ready status. + /// + public virtual void ReadyStatusChanged() + { + int CurrentPlayers = 0; + int ReadyPlayers = 0; + + foreach (NetworkRoomPlayer item in roomSlots) + { + if (item != null) + { + CurrentPlayers++; + if (item.readyToBegin) + ReadyPlayers++; + } + } + + if (CurrentPlayers == ReadyPlayers) + CheckReadyToBegin(); + else + allPlayersReady = false; + } + + /// + /// This is called on the server when all the players in the room are ready. + /// The default implementation of this function uses ServerChangeScene() to switch to the game player scene. By implementing this callback you can customize what happens when all the players in the room are ready, such as adding a countdown or a confirmation for a group leader. + /// + public virtual void OnRoomServerPlayersReady() + { + // all players are readyToBegin, start the game + ServerChangeScene(GameplayScene); + } + + /// + /// This is called on the server when CheckReadyToBegin finds that players are not ready + /// May be called multiple times while not ready players are joining + /// + public virtual void OnRoomServerPlayersNotReady() {} + + #endregion + + #region room client virtuals + + /// + /// This is a hook to allow custom behaviour when the game client enters the room. + /// + public virtual void OnRoomClientEnter() {} + + /// + /// This is a hook to allow custom behaviour when the game client exits the room. + /// + public virtual void OnRoomClientExit() {} + + /// + /// This is called on the client when it connects to server. + /// + public virtual void OnRoomClientConnect() {} + + /// + /// This is called on the client when disconnected from a server. + /// + public virtual void OnRoomClientDisconnect() {} + + /// + /// This is called on the client when a client is started. + /// + public virtual void OnRoomStartClient() {} + + /// + /// This is called on the client when the client stops. + /// + public virtual void OnRoomStopClient() {} + + /// + /// This is called on the client when the client is finished loading a new networked scene. + /// + public virtual void OnRoomClientSceneChanged() {} + + #endregion + + #region optional UI + + /// + /// virtual so inheriting classes can roll their own + /// + public virtual void OnGUI() + { + if (!showRoomGUI) + return; + + if (NetworkServer.active && Utils.IsSceneActive(GameplayScene)) + { + GUILayout.BeginArea(new Rect(Screen.width - 150f, 10f, 140f, 30f)); + if (GUILayout.Button("Return to Room")) + ServerChangeScene(RoomScene); + GUILayout.EndArea(); + } + + if (Utils.IsSceneActive(RoomScene)) + GUI.Box(new Rect(10f, 180f, 520f, 150f), "PLAYERS"); + } + + #endregion + } +} diff --git a/Assets/Mirror/Components/NetworkRoomManager.cs.meta b/Assets/Mirror/Components/NetworkRoomManager.cs.meta new file mode 100644 index 0000000..76e7d42 --- /dev/null +++ b/Assets/Mirror/Components/NetworkRoomManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 615e6c6589cf9e54cad646b5a11e0529 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkRoomPlayer.cs b/Assets/Mirror/Components/NetworkRoomPlayer.cs new file mode 100644 index 0000000..6b7cda4 --- /dev/null +++ b/Assets/Mirror/Components/NetworkRoomPlayer.cs @@ -0,0 +1,195 @@ +using UnityEngine; + +namespace Mirror +{ + /// + /// This component works in conjunction with the NetworkRoomManager to make up the multiplayer room system. + /// The RoomPrefab object of the NetworkRoomManager must have this component on it. This component holds basic room player data required for the room to function. Game specific data for room players can be put in other components on the RoomPrefab or in scripts derived from NetworkRoomPlayer. + /// + [DisallowMultipleComponent] + [AddComponentMenu("Network/Network Room Player")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-room-player")] + public class NetworkRoomPlayer : NetworkBehaviour + { + /// + /// This flag controls whether the default UI is shown for the room player. + /// As this UI is rendered using the old GUI system, it is only recommended for testing purposes. + /// + [Tooltip("This flag controls whether the default UI is shown for the room player")] + public bool showRoomGUI = true; + + [Header("Diagnostics")] + + /// + /// Diagnostic flag indicating whether this player is ready for the game to begin. + /// Invoke CmdChangeReadyState method on the client to set this flag. + /// When all players are ready to begin, the game will start. This should not be set directly, CmdChangeReadyState should be called on the client to set it on the server. + /// + [ReadOnly, Tooltip("Diagnostic flag indicating whether this player is ready for the game to begin")] + [SyncVar(hook = nameof(ReadyStateChanged))] + public bool readyToBegin; + + /// + /// Diagnostic index of the player, e.g. Player1, Player2, etc. + /// + [ReadOnly, Tooltip("Diagnostic index of the player, e.g. Player1, Player2, etc.")] + [SyncVar(hook = nameof(IndexChanged))] + public int index; + + #region Unity Callbacks + + /// + /// Do not use Start - Override OnStartHost / OnStartClient instead! + /// + public virtual void Start() + { + if (NetworkManager.singleton is NetworkRoomManager room) + { + // NetworkRoomPlayer object must be set to DontDestroyOnLoad along with NetworkRoomManager + // in server and all clients, otherwise it will be respawned in the game scene which would + // have undesirable effects. + if (room.dontDestroyOnLoad) + DontDestroyOnLoad(gameObject); + + room.roomSlots.Add(this); + + if (NetworkServer.active) + room.RecalculateRoomPlayerIndices(); + + if (NetworkClient.active) + room.CallOnClientEnterRoom(); + } + else Debug.LogError("RoomPlayer could not find a NetworkRoomManager. The RoomPlayer requires a NetworkRoomManager object to function. Make sure that there is one in the scene."); + } + + public virtual void OnDisable() + { + if (NetworkClient.active && NetworkManager.singleton is NetworkRoomManager room) + { + // only need to call this on client as server removes it before object is destroyed + room.roomSlots.Remove(this); + + room.CallOnClientExitRoom(); + } + } + + #endregion + + #region Commands + + [Command] + public void CmdChangeReadyState(bool readyState) + { + readyToBegin = readyState; + NetworkRoomManager room = NetworkManager.singleton as NetworkRoomManager; + if (room != null) + { + room.ReadyStatusChanged(); + } + } + + #endregion + + #region SyncVar Hooks + + /// + /// This is a hook that is invoked on clients when the index changes. + /// + /// The old index value + /// The new index value + public virtual void IndexChanged(int oldIndex, int newIndex) {} + + /// + /// This is a hook that is invoked on clients when a RoomPlayer switches between ready or not ready. + /// This function is called when the a client player calls CmdChangeReadyState. + /// + /// New Ready State + public virtual void ReadyStateChanged(bool oldReadyState, bool newReadyState) {} + + #endregion + + #region Room Client Virtuals + + /// + /// This is a hook that is invoked on clients for all room player objects when entering the room. + /// Note: isLocalPlayer is not guaranteed to be set until OnStartLocalPlayer is called. + /// + public virtual void OnClientEnterRoom() {} + + /// + /// This is a hook that is invoked on clients for all room player objects when exiting the room. + /// + public virtual void OnClientExitRoom() {} + + #endregion + + #region Optional UI + + /// + /// Render a UI for the room. Override to provide your own UI + /// + public virtual void OnGUI() + { + if (!showRoomGUI) + return; + + NetworkRoomManager room = NetworkManager.singleton as NetworkRoomManager; + if (room) + { + if (!room.showRoomGUI) + return; + + if (!Utils.IsSceneActive(room.RoomScene)) + return; + + DrawPlayerReadyState(); + DrawPlayerReadyButton(); + } + } + + void DrawPlayerReadyState() + { + GUILayout.BeginArea(new Rect(20f + (index * 100), 200f, 90f, 130f)); + + GUILayout.Label($"Player [{index + 1}]"); + + if (readyToBegin) + GUILayout.Label("Ready"); + else + GUILayout.Label("Not Ready"); + + if (((isServer && index > 0) || isServerOnly) && GUILayout.Button("REMOVE")) + { + // This button only shows on the Host for all players other than the Host + // Host and Players can't remove themselves (stop the client instead) + // Host can kick a Player this way. + GetComponent().connectionToClient.Disconnect(); + } + + GUILayout.EndArea(); + } + + void DrawPlayerReadyButton() + { + if (NetworkClient.active && isLocalPlayer) + { + GUILayout.BeginArea(new Rect(20f, 300f, 120f, 20f)); + + if (readyToBegin) + { + if (GUILayout.Button("Cancel")) + CmdChangeReadyState(false); + } + else + { + if (GUILayout.Button("Ready")) + CmdChangeReadyState(true); + } + + GUILayout.EndArea(); + } + } + + #endregion + } +} diff --git a/Assets/Mirror/Components/NetworkRoomPlayer.cs.meta b/Assets/Mirror/Components/NetworkRoomPlayer.cs.meta new file mode 100644 index 0000000..0299bea --- /dev/null +++ b/Assets/Mirror/Components/NetworkRoomPlayer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 79874ac94d5b1314788ecf0e86bd23fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkStatistics.cs b/Assets/Mirror/Components/NetworkStatistics.cs new file mode 100644 index 0000000..c00bb19 --- /dev/null +++ b/Assets/Mirror/Components/NetworkStatistics.cs @@ -0,0 +1,194 @@ +using System; +using UnityEngine; + +namespace Mirror +{ + /// + /// Shows Network messages and bytes sent and received per second. + /// + /// + /// Add this component to the same object as Network Manager. + /// + [AddComponentMenu("Network/Network Statistics")] + [DisallowMultipleComponent] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-statistics")] + public class NetworkStatistics : MonoBehaviour + { + // update interval + double intervalStartTime; + + // --------------------------------------------------------------------- + + // CLIENT (public fields for other components to grab statistics) + // long bytes to support >2GB + [HideInInspector] public int clientIntervalReceivedPackets; + [HideInInspector] public long clientIntervalReceivedBytes; + [HideInInspector] public int clientIntervalSentPackets; + [HideInInspector] public long clientIntervalSentBytes; + + // results from last interval + // long bytes to support >2GB + [HideInInspector] public int clientReceivedPacketsPerSecond; + [HideInInspector] public long clientReceivedBytesPerSecond; + [HideInInspector] public int clientSentPacketsPerSecond; + [HideInInspector] public long clientSentBytesPerSecond; + + // --------------------------------------------------------------------- + + // SERVER (public fields for other components to grab statistics) + // capture interval + // long bytes to support >2GB + [HideInInspector] public int serverIntervalReceivedPackets; + [HideInInspector] public long serverIntervalReceivedBytes; + [HideInInspector] public int serverIntervalSentPackets; + [HideInInspector] public long serverIntervalSentBytes; + + // results from last interval + // long bytes to support >2GB + [HideInInspector] public int serverReceivedPacketsPerSecond; + [HideInInspector] public long serverReceivedBytesPerSecond; + [HideInInspector] public int serverSentPacketsPerSecond; + [HideInInspector] public long serverSentBytesPerSecond; + + // NetworkManager sets Transport.active in Awake(). + // so let's hook into it in Start(). + void Start() + { + // find available transport + Transport transport = Transport.active; + if (transport != null) + { + transport.OnClientDataReceived += OnClientReceive; + transport.OnClientDataSent += OnClientSend; + transport.OnServerDataReceived += OnServerReceive; + transport.OnServerDataSent += OnServerSend; + } + else Debug.LogError($"NetworkStatistics: no available or active Transport found on this platform: {Application.platform}"); + } + + void OnDestroy() + { + // remove transport hooks + Transport transport = Transport.active; + if (transport != null) + { + transport.OnClientDataReceived -= OnClientReceive; + transport.OnClientDataSent -= OnClientSend; + transport.OnServerDataReceived -= OnServerReceive; + transport.OnServerDataSent -= OnServerSend; + } + } + + void OnClientReceive(ArraySegment data, int channelId) + { + ++clientIntervalReceivedPackets; + clientIntervalReceivedBytes += data.Count; + } + + void OnClientSend(ArraySegment data, int channelId) + { + ++clientIntervalSentPackets; + clientIntervalSentBytes += data.Count; + } + + void OnServerReceive(int connectionId, ArraySegment data, int channelId) + { + ++serverIntervalReceivedPackets; + serverIntervalReceivedBytes += data.Count; + } + + void OnServerSend(int connectionId, ArraySegment data, int channelId) + { + ++serverIntervalSentPackets; + serverIntervalSentBytes += data.Count; + } + + void Update() + { + // calculate results every second + if (NetworkTime.localTime >= intervalStartTime + 1) + { + if (NetworkClient.active) UpdateClient(); + if (NetworkServer.active) UpdateServer(); + + intervalStartTime = NetworkTime.localTime; + } + } + + void UpdateClient() + { + clientReceivedPacketsPerSecond = clientIntervalReceivedPackets; + clientReceivedBytesPerSecond = clientIntervalReceivedBytes; + clientSentPacketsPerSecond = clientIntervalSentPackets; + clientSentBytesPerSecond = clientIntervalSentBytes; + + clientIntervalReceivedPackets = 0; + clientIntervalReceivedBytes = 0; + clientIntervalSentPackets = 0; + clientIntervalSentBytes = 0; + } + + void UpdateServer() + { + serverReceivedPacketsPerSecond = serverIntervalReceivedPackets; + serverReceivedBytesPerSecond = serverIntervalReceivedBytes; + serverSentPacketsPerSecond = serverIntervalSentPackets; + serverSentBytesPerSecond = serverIntervalSentBytes; + + serverIntervalReceivedPackets = 0; + serverIntervalReceivedBytes = 0; + serverIntervalSentPackets = 0; + serverIntervalSentBytes = 0; + } + + void OnGUI() + { + // only show if either server or client active + if (NetworkClient.active || NetworkServer.active) + { + // create main GUI area + // 120 is below NetworkManager HUD in all cases. + GUILayout.BeginArea(new Rect(10, 120, 215, 300)); + + // show client / server stats if active + if (NetworkClient.active) OnClientGUI(); + if (NetworkServer.active) OnServerGUI(); + + // end of GUI area + GUILayout.EndArea(); + } + } + + void OnClientGUI() + { + // background + GUILayout.BeginVertical("Box"); + GUILayout.Label("Client Statistics"); + + // sending ("msgs" instead of "packets" to fit larger numbers) + GUILayout.Label($"Send: {clientSentPacketsPerSecond} msgs @ {Utils.PrettyBytes(clientSentBytesPerSecond)}/s"); + + // receiving ("msgs" instead of "packets" to fit larger numbers) + GUILayout.Label($"Recv: {clientReceivedPacketsPerSecond} msgs @ {Utils.PrettyBytes(clientReceivedBytesPerSecond)}/s"); + + // end background + GUILayout.EndVertical(); + } + + void OnServerGUI() + { + // background + GUILayout.BeginVertical("Box"); + GUILayout.Label("Server Statistics"); + + // sending ("msgs" instead of "packets" to fit larger numbers) + GUILayout.Label($"Send: {serverSentPacketsPerSecond} msgs @ {Utils.PrettyBytes(serverSentBytesPerSecond)}/s"); + + // receiving ("msgs" instead of "packets" to fit larger numbers) + GUILayout.Label($"Recv: {serverReceivedPacketsPerSecond} msgs @ {Utils.PrettyBytes(serverReceivedBytesPerSecond)}/s"); + + // end background + GUILayout.EndVertical(); + } + } +} diff --git a/Assets/Mirror/Components/NetworkStatistics.cs.meta b/Assets/Mirror/Components/NetworkStatistics.cs.meta new file mode 100644 index 0000000..0bf4251 --- /dev/null +++ b/Assets/Mirror/Components/NetworkStatistics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6d7da4e566d24ea7b0e12178d934b648 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkTransform.meta b/Assets/Mirror/Components/NetworkTransform.meta new file mode 100644 index 0000000..1b6770d --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 36de72d9255741659bcbd1971ed29822 +timeCreated: 1668358590 \ No newline at end of file diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransform.cs b/Assets/Mirror/Components/NetworkTransform/NetworkTransform.cs new file mode 100644 index 0000000..8a1a24a --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransform.cs @@ -0,0 +1,8 @@ +using System; + +namespace Mirror +{ + // DEPRECATED 2023-06-15 + [Obsolete("NetworkTransform was renamed to NetworkTransformUnreliable.\nYou can easily swap the component's script by going into the Unity Inspector debug mode:\n1. Click the vertical dots on the top right in the Inspector tab.\n2. Find your NetworkTransform component\n3. Drag NetworkTransformUnreliable into the 'Script' field in the Inspector.\n4. Find the three dots and return to Normal mode.")] + public class NetworkTransform : NetworkTransformUnreliable {} +} diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransform.cs.meta b/Assets/Mirror/Components/NetworkTransform/NetworkTransform.cs.meta new file mode 100644 index 0000000..a569990 --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransform.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f74aedd71d9a4f55b3ce499326d45fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs b/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs new file mode 100644 index 0000000..e752c20 --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs @@ -0,0 +1,489 @@ +// Snapshot Interpolation: https://gafferongames.com/post/snapshot_interpolation/ +// +// Base class for NetworkTransform and NetworkTransformChild. +// => simple unreliable sync without any interpolation for now. +// => which means we don't need teleport detection either +// +// NOTE: several functions are virtual in case someone needs to modify a part. +// +// Channel: uses UNRELIABLE at all times. +// -> out of order packets are dropped automatically +// -> it's better than RELIABLE for several reasons: +// * head of line blocking would add delay +// * resending is mostly pointless +// * bigger data race: +// -> if we use a Cmd() at position X over reliable +// -> client gets Cmd() and X at the same time, but buffers X for bufferTime +// -> for unreliable, it would get X before the reliable Cmd(), still +// buffer for bufferTime but end up closer to the original time +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + public enum CoordinateSpace { Local, World } + + public abstract class NetworkTransformBase : NetworkBehaviour + { + // target transform to sync. can be on a child. + // TODO this field is kind of unnecessary since we now support child NetworkBehaviours + [Header("Target")] + [Tooltip("The Transform component to sync. May be on on this GameObject, or on a child.")] + public Transform target; + + // Is this a client with authority over this transform? + // This component could be on the player object or any object that has been assigned authority to this client. + protected bool IsClientWithAuthority => isClient && authority; + + // snapshots with initial capacity to avoid early resizing & allocations: see NetworkRigidbodyBenchmark example. + public readonly SortedList clientSnapshots = new SortedList(16); + public readonly SortedList serverSnapshots = new SortedList(16); + + // selective sync ////////////////////////////////////////////////////// + [Header("Selective Sync\nDon't change these at Runtime")] + public bool syncPosition = true; // do not change at runtime! + public bool syncRotation = true; // do not change at runtime! + public bool syncScale = false; // do not change at runtime! rare. off by default. + + [Header("Bandwidth Savings")] + [Tooltip("When true, changes are not sent unless greater than sensitivity values below.")] + public bool onlySyncOnChange = true; + [Tooltip("Apply smallest-three quaternion compression. This is lossy, you can disable it if the small rotation inaccuracies are noticeable in your project.")] + public bool compressRotation = true; + + // interpolation is on by default, but can be disabled to jump to + // the destination immediately. some projects need this. + [Header("Interpolation")] + [Tooltip("Set to false to have a snap-like effect on position movement.")] + public bool interpolatePosition = true; + [Tooltip("Set to false to have a snap-like effect on rotations.")] + public bool interpolateRotation = true; + [Tooltip("Set to false to remove scale smoothing. Example use-case: Instant flipping of sprites that use -X and +X for direction.")] + public bool interpolateScale = true; + + // CoordinateSpace /////////////////////////////////////////////////////////// + [Header("Coordinate Space")] + [Tooltip("Local by default. World may be better when changing hierarchy, or non-NetworkTransforms root position/rotation/scale values.")] + public CoordinateSpace coordinateSpace = CoordinateSpace.Local; + + [Header("Send Interval Multiplier")] + [Tooltip("Check/Sync every multiple of Network Manager send interval (= 1 / NM Send Rate), instead of every send interval.\n(30 NM send rate, and 3 interval, is a send every 0.1 seconds)\nA larger interval means less network sends, which has a variety of upsides. The drawbacks are delays and lower accuracy, you should find a nice balance between not sending too much, but the results looking good for your particular scenario.")] + [Range(1, 120)] + public uint sendIntervalMultiplier = 1; + + [Header("Timeline Offset")] + [Tooltip("Add a small timeline offset to account for decoupled arrival of NetworkTime and NetworkTransform snapshots.\nfixes: https://github.com/MirrorNetworking/Mirror/issues/3427")] + public bool timelineOffset = false; + + // Ninja's Notes on offset & mulitplier: + // + // In a no multiplier scenario: + // 1. Snapshots are sent every frame (frame being 1 NM send interval). + // 2. Time Interpolation is set to be 'behind' by 2 frames times. + // In theory where everything works, we probably have around 2 snapshots before we need to interpolate snapshots. From NT perspective, we should always have around 2 snapshots ready, so no stutter. + // + // In a multiplier scenario: + // 1. Snapshots are sent every 10 frames. + // 2. Time Interpolation remains 'behind by 2 frames'. + // When everything works, we are receiving NT snapshots every 10 frames, but start interpolating after 2. + // Even if I assume we had 2 snapshots to begin with to start interpolating (which we don't), by the time we reach 13th frame, we are out of snapshots, and have to wait 7 frames for next snapshot to come. This is the reason why we absolutely need the timestamp adjustment. We are starting way too early to interpolate. + // + protected double timeStampAdjustment => NetworkServer.sendInterval * (sendIntervalMultiplier - 1); + protected double offset => timelineOffset ? NetworkServer.sendInterval * sendIntervalMultiplier : 0; + + // debugging /////////////////////////////////////////////////////////// + [Header("Debug")] + public bool showGizmos; + public bool showOverlay; + public Color overlayColor = new Color(0, 0, 0, 0.5f); + + // initialization ////////////////////////////////////////////////////// + // make sure to call this when inheriting too! + protected virtual void Awake() { } + + protected override void OnValidate() + { + base.OnValidate(); + + // set target to self if none yet + if (target == null) target = transform; + + // time snapshot interpolation happens globally. + // value (transform) happens in here. + // both always need to be on the same send interval. + // force the setting to '0' in OnValidate to make it obvious that we + // actually use NetworkServer.sendInterval. + syncInterval = 0; + + // Unity doesn't support setting world scale. + // OnValidate force disables syncScale in world mode. + if (coordinateSpace == CoordinateSpace.World) syncScale = false; + } + + // snapshot functions ////////////////////////////////////////////////// + // get local/world position + protected virtual Vector3 GetPosition() => + coordinateSpace == CoordinateSpace.Local ? target.localPosition : target.position; + + // get local/world rotation + protected virtual Quaternion GetRotation() => + coordinateSpace == CoordinateSpace.Local ? target.localRotation : target.rotation; + + // get local/world scale + protected virtual Vector3 GetScale() => + coordinateSpace == CoordinateSpace.Local ? target.localScale : target.lossyScale; + + // set local/world position + protected virtual void SetPosition(Vector3 position) + { + if (coordinateSpace == CoordinateSpace.Local) + target.localPosition = position; + else + target.position = position; + } + + // set local/world rotation + protected virtual void SetRotation(Quaternion rotation) + { + if (coordinateSpace == CoordinateSpace.Local) + target.localRotation = rotation; + else + target.rotation = rotation; + } + + // set local/world position + protected virtual void SetScale(Vector3 scale) + { + if (coordinateSpace == CoordinateSpace.Local) + target.localScale = scale; + // Unity doesn't support setting world scale. + // OnValidate disables syncScale in world mode. + // else + // target.lossyScale = scale; // TODO + } + + // construct a snapshot of the current state + // => internal for testing + protected virtual TransformSnapshot Construct() + { + // NetworkTime.localTime for double precision until Unity has it too + return new TransformSnapshot( + // our local time is what the other end uses as remote time + NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet + 0, // the other end fills out local time itself + GetPosition(), + GetRotation(), + GetScale() + ); + } + + protected void AddSnapshot(SortedList snapshots, double timeStamp, Vector3? position, Quaternion? rotation, Vector3? scale) + { + // position, rotation, scale can have no value if same as last time. + // saves bandwidth. + // but we still need to feed it to snapshot interpolation. we can't + // just have gaps in there if nothing has changed. for example, if + // client sends snapshot at t=0 + // client sends nothing for 10s because not moved + // client sends snapshot at t=10 + // then the server would assume that it's one super slow move and + // replay it for 10 seconds. + + if (!position.HasValue) position = snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].position : GetPosition(); + if (!rotation.HasValue) rotation = snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].rotation : GetRotation(); + if (!scale.HasValue) scale = snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].scale : GetScale(); + + // insert transform snapshot + SnapshotInterpolation.InsertIfNotExists( + snapshots, + NetworkClient.snapshotSettings.bufferLimit, + new TransformSnapshot( + timeStamp, // arrival remote timestamp. NOT remote time. + NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet + position.Value, + rotation.Value, + scale.Value + ) + ); + } + + // apply a snapshot to the Transform. + // -> start, end, interpolated are all passed in caes they are needed + // -> a regular game would apply the 'interpolated' snapshot + // -> a board game might want to jump to 'goal' directly + // (it's easier to always interpolate and then apply selectively, + // instead of manually interpolating x, y, z, ... depending on flags) + // => internal for testing + // + // NOTE: stuck detection is unnecessary here. + // we always set transform.position anyway, we can't get stuck. + protected virtual void Apply(TransformSnapshot interpolated, TransformSnapshot endGoal) + { + // local position/rotation for VR support + // + // if syncPosition/Rotation/Scale is disabled then we received nulls + // -> current position/rotation/scale would've been added as snapshot + // -> we still interpolated + // -> but simply don't apply it. if the user doesn't want to sync + // scale, then we should not touch scale etc. + + // interpolate parts + if (syncPosition) SetPosition(interpolatePosition ? interpolated.position : endGoal.position); + if (syncRotation) SetRotation(interpolateRotation ? interpolated.rotation : endGoal.rotation); + if (syncScale) SetScale(interpolateScale ? interpolated.scale : endGoal.scale); + } + + // client->server teleport to force position without interpolation. + // otherwise it would interpolate to a (far away) new position. + // => manually calling Teleport is the only 100% reliable solution. + [Command] + public void CmdTeleport(Vector3 destination) + { + // client can only teleport objects that it has authority over. + if (syncDirection != SyncDirection.ClientToServer) return; + + // TODO what about host mode? + OnTeleport(destination); + + // if a client teleports, we need to broadcast to everyone else too + // TODO the teleported client should ignore the rpc though. + // otherwise if it already moved again after teleporting, + // the rpc would come a little bit later and reset it once. + // TODO or not? if client ONLY calls Teleport(pos), the position + // would only be set after the rpc. unless the client calls + // BOTH Teleport(pos) and target.position=pos + RpcTeleport(destination); + } + + // client->server teleport to force position and rotation without interpolation. + // otherwise it would interpolate to a (far away) new position. + // => manually calling Teleport is the only 100% reliable solution. + [Command] + public void CmdTeleport(Vector3 destination, Quaternion rotation) + { + // client can only teleport objects that it has authority over. + if (syncDirection != SyncDirection.ClientToServer) return; + + // TODO what about host mode? + OnTeleport(destination, rotation); + + // if a client teleports, we need to broadcast to everyone else too + // TODO the teleported client should ignore the rpc though. + // otherwise if it already moved again after teleporting, + // the rpc would come a little bit later and reset it once. + // TODO or not? if client ONLY calls Teleport(pos), the position + // would only be set after the rpc. unless the client calls + // BOTH Teleport(pos) and target.position=pos + RpcTeleport(destination, rotation); + } + + // server->client teleport to force position without interpolation. + // otherwise it would interpolate to a (far away) new position. + // => manually calling Teleport is the only 100% reliable solution. + [ClientRpc] + public void RpcTeleport(Vector3 destination) + { + // NOTE: even in client authority mode, the server is always allowed + // to teleport the player. for example: + // * CmdEnterPortal() might teleport the player + // * Some people use client authority with server sided checks + // so the server should be able to reset position if needed. + + // TODO what about host mode? + OnTeleport(destination); + } + + // server->client teleport to force position and rotation without interpolation. + // otherwise it would interpolate to a (far away) new position. + // => manually calling Teleport is the only 100% reliable solution. + [ClientRpc] + public void RpcTeleport(Vector3 destination, Quaternion rotation) + { + // NOTE: even in client authority mode, the server is always allowed + // to teleport the player. for example: + // * CmdEnterPortal() might teleport the player + // * Some people use client authority with server sided checks + // so the server should be able to reset position if needed. + + // TODO what about host mode? + OnTeleport(destination, rotation); + } + + [ClientRpc] + void RpcResetState() + { + ResetState(); + } + + // common Teleport code for client->server and server->client + protected virtual void OnTeleport(Vector3 destination) + { + // set the new position. + // interpolation will automatically continue. + target.position = destination; + + // reset interpolation to immediately jump to the new position. + // do not call Reset() here, this would cause delta compression to + // get out of sync for NetworkTransformReliable because NTReliable's + // 'override Reset()' resets lastDe/SerializedPosition: + // https://github.com/MirrorNetworking/Mirror/issues/3588 + // because client's next OnSerialize() will delta compress, + // but server's last delta will have been reset, causing offsets. + // + // instead, simply clear snapshots. + serverSnapshots.Clear(); + clientSnapshots.Clear(); + + // TODO + // what if we still receive a snapshot from before the interpolation? + // it could easily happen over unreliable. + // -> maybe add destination as first entry? + } + + // common Teleport code for client->server and server->client + protected virtual void OnTeleport(Vector3 destination, Quaternion rotation) + { + // set the new position. + // interpolation will automatically continue. + target.position = destination; + target.rotation = rotation; + + // reset interpolation to immediately jump to the new position. + // do not call Reset() here, this would cause delta compression to + // get out of sync for NetworkTransformReliable because NTReliable's + // 'override Reset()' resets lastDe/SerializedPosition: + // https://github.com/MirrorNetworking/Mirror/issues/3588 + // because client's next OnSerialize() will delta compress, + // but server's last delta will have been reset, causing offsets. + // + // instead, simply clear snapshots. + serverSnapshots.Clear(); + clientSnapshots.Clear(); + + // TODO + // what if we still receive a snapshot from before the interpolation? + // it could easily happen over unreliable. + // -> maybe add destination as first entry? + } + + public virtual void ResetState() + { + // disabled objects aren't updated anymore. + // so let's clear the buffers. + serverSnapshots.Clear(); + clientSnapshots.Clear(); + } + + public virtual void Reset() + { + ResetState(); + // default to ClientToServer so this works immediately for users + syncDirection = SyncDirection.ClientToServer; + } + + protected virtual void OnEnable() + { + ResetState(); + + if (NetworkServer.active) + NetworkIdentity.clientAuthorityCallback += OnClientAuthorityChanged; + } + + protected virtual void OnDisable() + { + ResetState(); + + if (NetworkServer.active) + NetworkIdentity.clientAuthorityCallback -= OnClientAuthorityChanged; + } + + [ServerCallback] + void OnClientAuthorityChanged(NetworkConnectionToClient conn, NetworkIdentity identity, bool authorityState) + { + if (identity != netIdentity) return; + + // If server gets authority or syncdirection is server to client, + // we don't reset buffers. + // This is because if syncdirection is S to C, we will never have + // snapshot issues since there is only ever 1 source. + + if (syncDirection == SyncDirection.ClientToServer) + { + ResetState(); + RpcResetState(); + } + } + + // OnGUI allocates even if it does nothing. avoid in release. +#if UNITY_EDITOR || DEVELOPMENT_BUILD + // debug /////////////////////////////////////////////////////////////// + protected virtual void OnGUI() + { + if (!showOverlay) return; + if (!Camera.main) return; + + // show data next to player for easier debugging. this is very useful! + // IMPORTANT: this is basically an ESP hack for shooter games. + // DO NOT make this available with a hotkey in release builds + if (!Debug.isDebugBuild) return; + + // project position to screen + Vector3 point = Camera.main.WorldToScreenPoint(target.position); + + // enough alpha, in front of camera and in screen? + if (point.z >= 0 && Utils.IsPointInScreen(point)) + { + GUI.color = overlayColor; + GUILayout.BeginArea(new Rect(point.x, Screen.height - point.y, 200, 100)); + + // always show both client & server buffers so it's super + // obvious if we accidentally populate both. + GUILayout.Label($"Server Buffer:{serverSnapshots.Count}"); + GUILayout.Label($"Client Buffer:{clientSnapshots.Count}"); + + GUILayout.EndArea(); + GUI.color = Color.white; + } + } + + protected virtual void DrawGizmos(SortedList buffer) + { + // only draw if we have at least two entries + if (buffer.Count < 2) return; + + // calculate threshold for 'old enough' snapshots + double threshold = NetworkTime.localTime - NetworkClient.bufferTime; + Color oldEnoughColor = new Color(0, 1, 0, 0.5f); + Color notOldEnoughColor = new Color(0.5f, 0.5f, 0.5f, 0.3f); + + // draw the whole buffer for easier debugging. + // it's worth seeing how much we have buffered ahead already + for (int i = 0; i < buffer.Count; ++i) + { + // color depends on if old enough or not + TransformSnapshot entry = buffer.Values[i]; + bool oldEnough = entry.localTime <= threshold; + Gizmos.color = oldEnough ? oldEnoughColor : notOldEnoughColor; + Gizmos.DrawWireCube(entry.position, Vector3.one); + } + + // extra: lines between start<->position<->goal + Gizmos.color = Color.green; + Gizmos.DrawLine(buffer.Values[0].position, target.position); + Gizmos.color = Color.white; + Gizmos.DrawLine(target.position, buffer.Values[1].position); + } + + protected virtual void OnDrawGizmos() + { + // This fires in edit mode but that spams NRE's so check isPlaying + if (!Application.isPlaying) return; + if (!showGizmos) return; + + if (isServer) DrawGizmos(serverSnapshots); + if (isClient) DrawGizmos(clientSnapshots); + } +#endif + } +} diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs.meta b/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs.meta new file mode 100644 index 0000000..ef58471 --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7c44135fde488424eaf28566206ce473 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformChild.cs b/Assets/Mirror/Components/NetworkTransform/NetworkTransformChild.cs new file mode 100644 index 0000000..a844d9d --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformChild.cs @@ -0,0 +1,12 @@ +// A component to synchronize the position of child transforms of networked objects. +// There must be a NetworkTransform on the root object of the hierarchy. There can be multiple NetworkTransformChild components on an object. This does not use physics for synchronization, it simply synchronizes the localPosition and localRotation of the child transform and lerps towards the recieved values. +using System; +using UnityEngine; + +namespace Mirror +{ + // Deprecated 2022-10-25 + [AddComponentMenu("")] + [Obsolete("NetworkTransformChild is not needed anymore. The .target is now exposed in NetworkTransform itself. Note you can open the Inspector in debug view and replace the source script instead of reassigning everything.")] + public class NetworkTransformChild : NetworkTransform {} +} diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformChild.cs.meta b/Assets/Mirror/Components/NetworkTransform/NetworkTransformChild.cs.meta new file mode 100644 index 0000000..ae36756 --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformChild.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 734b48bea0b204338958ee3d885e11f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs b/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs new file mode 100644 index 0000000..f6e851b --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs @@ -0,0 +1,420 @@ +// NetworkTransform V3 (reliable) by mischa (2022-10) +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Mirror +{ + [AddComponentMenu("Network/Network Transform (Reliable)")] + public class NetworkTransformReliable : NetworkTransformBase + { + uint sendIntervalCounter = 0; + double lastSendIntervalTime = double.MinValue; + + [Tooltip("If we only sync on change, then we need to correct old snapshots if more time than sendInterval * multiplier has elapsed.\n\nOtherwise the first move will always start interpolating from the last move sequence's time, which will make it stutter when starting every time.")] + public float onlySyncOnChangeCorrectionMultiplier = 2; + + [Header("Rotation")] + [Tooltip("Sensitivity of changes needed before an updated state is sent over the network")] + public float rotationSensitivity = 0.01f; + + // delta compression is capable of detecting byte-level changes. + // if we scale float position to bytes, + // then small movements will only change one byte. + // this gives optimal bandwidth. + // benchmark with 0.01 precision: 130 KB/s => 60 KB/s + // benchmark with 0.1 precision: 130 KB/s => 30 KB/s + [Header("Precision")] + [Tooltip("Position is rounded in order to drastically minimize bandwidth.\n\nFor example, a precision of 0.01 rounds to a centimeter. In other words, sub-centimeter movements aren't synced until they eventually exceeded an actual centimeter.\n\nDepending on how important the object is, a precision of 0.01-0.10 (1-10 cm) is recommended.\n\nFor example, even a 1cm precision combined with delta compression cuts the Benchmark demo's bandwidth in half, compared to sending every tiny change.")] + [Range(0.00_01f, 1f)] // disallow 0 division. 1mm to 1m precision is enough range. + public float positionPrecision = 0.01f; // 1 cm + [Range(0.00_01f, 1f)] // disallow 0 division. 1mm to 1m precision is enough range. + public float scalePrecision = 0.01f; // 1 cm + + // delta compression needs to remember 'last' to compress against + protected Vector3Long lastSerializedPosition = Vector3Long.zero; + protected Vector3Long lastDeserializedPosition = Vector3Long.zero; + + protected Vector3Long lastSerializedScale = Vector3Long.zero; + protected Vector3Long lastDeserializedScale = Vector3Long.zero; + + // Used to store last sent snapshots + protected TransformSnapshot last; + + protected int lastClientCount = 1; + + // update ////////////////////////////////////////////////////////////// + void Update() + { + // if server then always sync to others. + if (isServer) UpdateServer(); + // 'else if' because host mode shouldn't send anything to server. + // it is the server. don't overwrite anything there. + else if (isClient) UpdateClient(); + } + + void LateUpdate() + { + // set dirty to trigger OnSerialize. either always, or only if changed. + // It has to be checked in LateUpdate() for onlySyncOnChange to avoid + // the possibility of Update() running first before the object's movement + // script's Update(), which then causes NT to send every alternate frame + // instead. + if (isServer || (IsClientWithAuthority && NetworkClient.ready)) + { + if (sendIntervalCounter == sendIntervalMultiplier && (!onlySyncOnChange || Changed(Construct()))) + SetDirty(); + + CheckLastSendTime(); + } + } + + protected virtual void UpdateServer() + { + // apply buffered snapshots IF client authority + // -> in server authority, server moves the object + // so no need to apply any snapshots there. + // -> don't apply for host mode player objects either, even if in + // client authority mode. if it doesn't go over the network, + // then we don't need to do anything. + // -> connectionToClient is briefly null after scene changes: + // https://github.com/MirrorNetworking/Mirror/issues/3329 + if (syncDirection == SyncDirection.ClientToServer && + connectionToClient != null && + !isOwned) + { + if (serverSnapshots.Count > 0) + { + // step the transform interpolation without touching time. + // NetworkClient is responsible for time globally. + SnapshotInterpolation.StepInterpolation( + serverSnapshots, + connectionToClient.remoteTimeline, + out TransformSnapshot from, + out TransformSnapshot to, + out double t); + + // interpolate & apply + TransformSnapshot computed = TransformSnapshot.Interpolate(from, to, t); + Apply(computed, to); + } + } + } + + protected virtual void UpdateClient() + { + // client authority, and local player (= allowed to move myself)? + if (!IsClientWithAuthority) + { + // only while we have snapshots + if (clientSnapshots.Count > 0) + { + // step the interpolation without touching time. + // NetworkClient is responsible for time globally. + SnapshotInterpolation.StepInterpolation( + clientSnapshots, + NetworkTime.time, // == NetworkClient.localTimeline from snapshot interpolation + out TransformSnapshot from, + out TransformSnapshot to, + out double t); + + // interpolate & apply + TransformSnapshot computed = TransformSnapshot.Interpolate(from, to, t); + Apply(computed, to); + } + + lastClientCount = clientSnapshots.Count; + } + } + + protected virtual void CheckLastSendTime() + { + // timeAsDouble not available in older Unity versions. + if (AccurateInterval.Elapsed(NetworkTime.localTime, NetworkServer.sendInterval, ref lastSendIntervalTime)) + { + if (sendIntervalCounter == sendIntervalMultiplier) + sendIntervalCounter = 0; + sendIntervalCounter++; + } + } + + // check if position / rotation / scale changed since last sync + protected virtual bool Changed(TransformSnapshot current) => + // position is quantized and delta compressed. + // only consider it changed if the quantized representation is changed. + // careful: don't use 'serialized / deserialized last'. as it depends on sync mode etc. + QuantizedChanged(last.position, current.position, positionPrecision) || + // rotation isn't quantized / delta compressed. + // check with sensitivity. + Quaternion.Angle(last.rotation, current.rotation) > rotationSensitivity || + // scale is quantized and delta compressed. + // only consider it changed if the quantized representation is changed. + // careful: don't use 'serialized / deserialized last'. as it depends on sync mode etc. + QuantizedChanged(last.scale, current.scale, scalePrecision); + + // helper function to compare quantized representations of a Vector3 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected bool QuantizedChanged(Vector3 u, Vector3 v, float precision) + { + Compression.ScaleToLong(u, precision, out Vector3Long uQuantized); + Compression.ScaleToLong(v, precision, out Vector3Long vQuantized); + return uQuantized != vQuantized; + } + + // NT may be used on client/server/host to Owner/Observers with + // ServerToClient or ClientToServer. + // however, OnSerialize should always delta against last. + public override void OnSerialize(NetworkWriter writer, bool initialState) + { + // get current snapshot for broadcasting. + TransformSnapshot snapshot = Construct(); + + // ClientToServer optimization: + // for interpolated client owned identities, + // always broadcast the latest known snapshot so other clients can + // interpolate immediately instead of catching up too + + // TODO dirty mask? [compression is very good w/o it already] + // each vector's component is delta compressed. + // an unchanged component would still require 1 byte. + // let's use a dirty bit mask to filter those out as well. + + // initial + if (initialState) + { + // If there is a last serialized snapshot, we use it. + // This prevents the new client getting a snapshot that is different + // from what the older clients last got. If this happens, and on the next + // regular serialisation the delta compression will get wrong values. + // Notes: + // 1. Interestingly only the older clients have it wrong, because at the end + // of this function, last = snapshot which is the initial state's snapshot + // 2. Regular NTR gets by this bug because it sends every frame anyway so initialstate + // snapshot constructed would have been the same as the last anyway. + if (last.remoteTime > 0) snapshot = last; + if (syncPosition) writer.WriteVector3(snapshot.position); + if (syncRotation) + { + // (optional) smallest three compression for now. no delta. + if (compressRotation) + writer.WriteUInt(Compression.CompressQuaternion(snapshot.rotation)); + else + writer.WriteQuaternion(snapshot.rotation); + } + if (syncScale) writer.WriteVector3(snapshot.scale); + } + // delta + else + { + // int before = writer.Position; + + if (syncPosition) + { + // quantize -> delta -> varint + Compression.ScaleToLong(snapshot.position, positionPrecision, out Vector3Long quantized); + DeltaCompression.Compress(writer, lastSerializedPosition, quantized); + } + if (syncRotation) + { + // (optional) smallest three compression for now. no delta. + if (compressRotation) + writer.WriteUInt(Compression.CompressQuaternion(snapshot.rotation)); + else + writer.WriteQuaternion(snapshot.rotation); + } + if (syncScale) + { + // quantize -> delta -> varint + Compression.ScaleToLong(snapshot.scale, scalePrecision, out Vector3Long quantized); + DeltaCompression.Compress(writer, lastSerializedScale, quantized); + } + } + + // save serialized as 'last' for next delta compression + if (syncPosition) Compression.ScaleToLong(snapshot.position, positionPrecision, out lastSerializedPosition); + if (syncScale) Compression.ScaleToLong(snapshot.scale, scalePrecision, out lastSerializedScale); + + // set 'last' + last = snapshot; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + Vector3? position = null; + Quaternion? rotation = null; + Vector3? scale = null; + + // initial + if (initialState) + { + if (syncPosition) position = reader.ReadVector3(); + if (syncRotation) + { + // (optional) smallest three compression for now. no delta. + if (compressRotation) + rotation = Compression.DecompressQuaternion(reader.ReadUInt()); + else + rotation = reader.ReadQuaternion(); + } + if (syncScale) scale = reader.ReadVector3(); + } + // delta + else + { + // varint -> delta -> quantize + if (syncPosition) + { + Vector3Long quantized = DeltaCompression.Decompress(reader, lastDeserializedPosition); + position = Compression.ScaleToFloat(quantized, positionPrecision); + } + if (syncRotation) + { + // (optional) smallest three compression for now. no delta. + if (compressRotation) + rotation = Compression.DecompressQuaternion(reader.ReadUInt()); + else + rotation = reader.ReadQuaternion(); + } + if (syncScale) + { + Vector3Long quantized = DeltaCompression.Decompress(reader, lastDeserializedScale); + scale = Compression.ScaleToFloat(quantized, scalePrecision); + } + } + + // handle depending on server / client / host. + // server has priority for host mode. + if (isServer) OnClientToServerSync(position, rotation, scale); + else if (isClient) OnServerToClientSync(position, rotation, scale); + + // save deserialized as 'last' for next delta compression + if (syncPosition) Compression.ScaleToLong(position.Value, positionPrecision, out lastDeserializedPosition); + if (syncScale) Compression.ScaleToLong(scale.Value, scalePrecision, out lastDeserializedScale); + } + + // sync //////////////////////////////////////////////////////////////// + + // local authority client sends sync message to server for broadcasting + protected virtual void OnClientToServerSync(Vector3? position, Quaternion? rotation, Vector3? scale) + { + // only apply if in client authority mode + if (syncDirection != SyncDirection.ClientToServer) return; + + // protect against ever growing buffer size attacks + if (serverSnapshots.Count >= connectionToClient.snapshotBufferSizeLimit) return; + + // 'only sync on change' needs a correction on every new move sequence. + if (onlySyncOnChange && + NeedsCorrection(serverSnapshots, connectionToClient.remoteTimeStamp, NetworkServer.sendInterval * sendIntervalMultiplier, onlySyncOnChangeCorrectionMultiplier)) + { + RewriteHistory( + serverSnapshots, + connectionToClient.remoteTimeStamp, + NetworkTime.localTime, // arrival remote timestamp. NOT remote timeline. + NetworkServer.sendInterval * sendIntervalMultiplier, // Unity 2019 doesn't have timeAsDouble yet + GetPosition(), + GetRotation(), + GetScale()); + } + + // add a small timeline offset to account for decoupled arrival of + // NetworkTime and NetworkTransform snapshots. + // needs to be sendInterval. half sendInterval doesn't solve it. + // https://github.com/MirrorNetworking/Mirror/issues/3427 + // remove this after LocalWorldState. + AddSnapshot(serverSnapshots, connectionToClient.remoteTimeStamp + timeStampAdjustment + offset, position, rotation, scale); + } + + // server broadcasts sync message to all clients + protected virtual void OnServerToClientSync(Vector3? position, Quaternion? rotation, Vector3? scale) + { + // don't apply for local player with authority + if (IsClientWithAuthority) return; + + // 'only sync on change' needs a correction on every new move sequence. + if (onlySyncOnChange && + NeedsCorrection(clientSnapshots, NetworkClient.connection.remoteTimeStamp, NetworkClient.sendInterval * sendIntervalMultiplier, onlySyncOnChangeCorrectionMultiplier)) + { + RewriteHistory( + clientSnapshots, + NetworkClient.connection.remoteTimeStamp, // arrival remote timestamp. NOT remote timeline. + NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet + NetworkClient.sendInterval * sendIntervalMultiplier, + GetPosition(), + GetRotation(), + GetScale()); + } + + // add a small timeline offset to account for decoupled arrival of + // NetworkTime and NetworkTransform snapshots. + // needs to be sendInterval. half sendInterval doesn't solve it. + // https://github.com/MirrorNetworking/Mirror/issues/3427 + // remove this after LocalWorldState. + AddSnapshot(clientSnapshots, NetworkClient.connection.remoteTimeStamp + timeStampAdjustment + offset, position, rotation, scale); + } + + // only sync on change ///////////////////////////////////////////////// + // snap interp. needs a continous flow of packets. + // 'only sync on change' interrupts it while not changed. + // once it restarts, snap interp. will interp from the last old position. + // this will cause very noticeable stutter for the first move each time. + // the fix is quite simple. + + // 1. detect if the remaining snapshot is too old from a past move. + static bool NeedsCorrection( + SortedList snapshots, + double remoteTimestamp, + double bufferTime, + double toleranceMultiplier) => + snapshots.Count == 1 && + remoteTimestamp - snapshots.Keys[0] >= bufferTime * toleranceMultiplier; + + // 2. insert a fake snapshot at current position, + // exactly one 'sendInterval' behind the newly received one. + static void RewriteHistory( + SortedList snapshots, + // timestamp of packet arrival, not interpolated remote time! + double remoteTimeStamp, + double localTime, + double sendInterval, + Vector3 position, + Quaternion rotation, + Vector3 scale) + { + // clear the previous snapshot + snapshots.Clear(); + + // insert a fake one at where we used to be, + // 'sendInterval' behind the new one. + SnapshotInterpolation.InsertIfNotExists( + snapshots, + NetworkClient.snapshotSettings.bufferLimit, + new TransformSnapshot( + remoteTimeStamp - sendInterval, // arrival remote timestamp. NOT remote time. + localTime - sendInterval, // Unity 2019 doesn't have timeAsDouble yet + position, + rotation, + scale + ) + ); + } + + // reset state for next session. + // do not ever call this during a session (i.e. after teleport). + // calling this will break delta compression. + public override void ResetState() + { + base.ResetState(); + + // reset delta + lastSerializedPosition = Vector3Long.zero; + lastDeserializedPosition = Vector3Long.zero; + + lastSerializedScale = Vector3Long.zero; + lastDeserializedScale = Vector3Long.zero; + + // reset 'last' for delta too + last = new TransformSnapshot(0, 0, Vector3.zero, Quaternion.identity, Vector3.zero); + } + } +} diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs.meta b/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs.meta new file mode 100644 index 0000000..ece9c7d --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ff3ba0becae47b8b9381191598957c8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformUnreliable.cs b/Assets/Mirror/Components/NetworkTransform/NetworkTransformUnreliable.cs new file mode 100644 index 0000000..ec5d3e1 --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformUnreliable.cs @@ -0,0 +1,678 @@ +// NetworkTransform V2 by mischa (2021-07) +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + [AddComponentMenu("Network/Network Transform (Unreliable)")] + public class NetworkTransformUnreliable : NetworkTransformBase + { + uint sendIntervalCounter = 0; + double lastSendIntervalTime = double.MinValue; + + // Testing under really bad network conditions, 2%-5% packet loss and 250-1200ms ping, 5 proved to eliminate any twitching, however this should not be the default as it is a rare case Developers may want to cover. + [Tooltip("How much time, as a multiple of send interval, has passed before clearing buffers.\nA larger buffer means more delay, but results in smoother movement.\nExample: 1 for faster responses minimal smoothing, 5 covers bad pings but has noticable delay, 3 is recommended for balanced results,.")] + public float bufferResetMultiplier = 3; + [Tooltip("Detect and send only changed data, such as Position X and Z, not the full Vector3 of X Y Z. Lowers network data at cost of extra calculations.")] + public bool changedDetection = true; + + [Header("Sensitivity"), Tooltip("Sensitivity of changes needed before an updated state is sent over the network")] + public float positionSensitivity = 0.01f; + public float rotationSensitivity = 0.01f; + public float scaleSensitivity = 0.01f; + + protected bool positionChanged; + protected bool rotationChanged; + protected bool scaleChanged; + + // Used to store last sent snapshots + protected TransformSnapshot lastSnapshot; + protected bool cachedSnapshotComparison; + protected Changed cachedChangedComparison; + protected bool hasSentUnchangedPosition; + + // update ////////////////////////////////////////////////////////////// + // Update applies interpolation + void Update() + { + if (isServer) UpdateServerInterpolation(); + // for all other clients (and for local player if !authority), + // we need to apply snapshots from the buffer. + // 'else if' because host mode shouldn't interpolate client + else if (isClient && !IsClientWithAuthority) UpdateClientInterpolation(); + } + + // LateUpdate broadcasts. + // movement scripts may change positions in Update. + // use LateUpdate to ensure changes are detected in the same frame. + // otherwise this may run before user update, delaying detection until next frame. + // this could cause visible jitter. + void LateUpdate() + { + // if server then always sync to others. + if (isServer) UpdateServerBroadcast(); + // client authority, and local player (= allowed to move myself)? + // 'else if' because host mode shouldn't send anything to server. + // it is the server. don't overwrite anything there. + else if (isClient && IsClientWithAuthority) UpdateClientBroadcast(); + } + + protected virtual void CheckLastSendTime() + { + // We check interval every frame, and then send if interval is reached. + // So by the time sendIntervalCounter == sendIntervalMultiplier, data is sent, + // thus we reset the counter here. + // This fixes previous issue of, if sendIntervalMultiplier = 1, we send every frame, + // because intervalCounter is always = 1 in the previous version. + + // Changing == to >= https://github.com/MirrorNetworking/Mirror/issues/3571 + + if (sendIntervalCounter >= sendIntervalMultiplier) + sendIntervalCounter = 0; + + // timeAsDouble not available in older Unity versions. + if (AccurateInterval.Elapsed(NetworkTime.localTime, NetworkServer.sendInterval, ref lastSendIntervalTime)) + sendIntervalCounter++; + } + + void UpdateServerBroadcast() + { + // broadcast to all clients each 'sendInterval' + // (client with authority will drop the rpc) + // NetworkTime.localTime for double precision until Unity has it too + // + // IMPORTANT: + // snapshot interpolation requires constant sending. + // DO NOT only send if position changed. for example: + // --- + // * client sends first position at t=0 + // * ... 10s later ... + // * client moves again, sends second position at t=10 + // --- + // * server gets first position at t=0 + // * server gets second position at t=10 + // * server moves from first to second within a time of 10s + // => would be a super slow move, instead of a wait & move. + // + // IMPORTANT: + // DO NOT send nulls if not changed 'since last send' either. we + // send unreliable and don't know which 'last send' the other end + // received successfully. + // + // Checks to ensure server only sends snapshots if object is + // on server authority(!clientAuthority) mode because on client + // authority mode snapshots are broadcasted right after the authoritative + // client updates server in the command function(see above), OR, + // since host does not send anything to update the server, any client + // authoritative movement done by the host will have to be broadcasted + // here by checking IsClientWithAuthority. + // TODO send same time that NetworkServer sends time snapshot? + CheckLastSendTime(); + + if (sendIntervalCounter == sendIntervalMultiplier && // same interval as time interpolation! + (syncDirection == SyncDirection.ServerToClient || IsClientWithAuthority)) + { + // send snapshot without timestamp. + // receiver gets it from batch timestamp to save bandwidth. + TransformSnapshot snapshot = Construct(); + + if (changedDetection) + { + cachedChangedComparison = CompareChangedSnapshots(snapshot); + + if ((cachedChangedComparison == Changed.None || cachedChangedComparison == Changed.CompressRot) && hasSentUnchangedPosition && onlySyncOnChange) { return; } + + SyncData syncData = new SyncData(cachedChangedComparison, snapshot); + + RpcServerToClientSync(syncData); + + if (cachedChangedComparison == Changed.None || cachedChangedComparison == Changed.CompressRot) + { + hasSentUnchangedPosition = true; + } + else + { + hasSentUnchangedPosition = false; + UpdateLastSentSnapshot(cachedChangedComparison, snapshot); + } + } + else + { + cachedSnapshotComparison = CompareSnapshots(snapshot); + if (cachedSnapshotComparison && hasSentUnchangedPosition && onlySyncOnChange) { return; } + + if (compressRotation) + { + RpcServerToClientSyncCompressRotation( + // only sync what the user wants to sync + syncPosition && positionChanged ? snapshot.position : default(Vector3?), + syncRotation && rotationChanged ? Compression.CompressQuaternion(snapshot.rotation) : default(uint?), + syncScale && scaleChanged ? snapshot.scale : default(Vector3?) + ); + } + else + { + RpcServerToClientSync( + // only sync what the user wants to sync + syncPosition && positionChanged ? snapshot.position : default(Vector3?), + syncRotation && rotationChanged ? snapshot.rotation : default(Quaternion?), + syncScale && scaleChanged ? snapshot.scale : default(Vector3?) + ); + } + + if (cachedSnapshotComparison) + { + hasSentUnchangedPosition = true; + } + else + { + hasSentUnchangedPosition = false; + + // Fixes https://github.com/MirrorNetworking/Mirror/issues/3572 + // This also fixes https://github.com/MirrorNetworking/Mirror/issues/3573 + // with the exception of Quaternion.Angle sensitivity has to be > 0.16. + // Unity issue, we are leaving it as is. + + if (positionChanged) lastSnapshot.position = snapshot.position; + if (rotationChanged) lastSnapshot.rotation = snapshot.rotation; + if (positionChanged) lastSnapshot.scale = snapshot.scale; + } + } + } + } + + void UpdateServerInterpolation() + { + // apply buffered snapshots IF client authority + // -> in server authority, server moves the object + // so no need to apply any snapshots there. + // -> don't apply for host mode player objects either, even if in + // client authority mode. if it doesn't go over the network, + // then we don't need to do anything. + // -> connectionToClient is briefly null after scene changes: + // https://github.com/MirrorNetworking/Mirror/issues/3329 + if (syncDirection == SyncDirection.ClientToServer && + connectionToClient != null && + !isOwned) + { + if (serverSnapshots.Count == 0) return; + + // step the transform interpolation without touching time. + // NetworkClient is responsible for time globally. + SnapshotInterpolation.StepInterpolation( + serverSnapshots, + connectionToClient.remoteTimeline, + out TransformSnapshot from, + out TransformSnapshot to, + out double t); + + // interpolate & apply + TransformSnapshot computed = TransformSnapshot.Interpolate(from, to, t); + Apply(computed, to); + } + } + + void UpdateClientBroadcast() + { + // https://github.com/vis2k/Mirror/pull/2992/ + if (!NetworkClient.ready) return; + + // send to server each 'sendInterval' + // NetworkTime.localTime for double precision until Unity has it too + // + // IMPORTANT: + // snapshot interpolation requires constant sending. + // DO NOT only send if position changed. for example: + // --- + // * client sends first position at t=0 + // * ... 10s later ... + // * client moves again, sends second position at t=10 + // --- + // * server gets first position at t=0 + // * server gets second position at t=10 + // * server moves from first to second within a time of 10s + // => would be a super slow move, instead of a wait & move. + // + // IMPORTANT: + // DO NOT send nulls if not changed 'since last send' either. we + // send unreliable and don't know which 'last send' the other end + // received successfully. + CheckLastSendTime(); + if (sendIntervalCounter == sendIntervalMultiplier) // same interval as time interpolation! + { + // send snapshot without timestamp. + // receiver gets it from batch timestamp to save bandwidth. + TransformSnapshot snapshot = Construct(); + + if (changedDetection) + { + cachedChangedComparison = CompareChangedSnapshots(snapshot); + + if ((cachedChangedComparison == Changed.None || cachedChangedComparison == Changed.CompressRot) && hasSentUnchangedPosition && onlySyncOnChange) { return; } + + SyncData syncData = new SyncData(cachedChangedComparison, snapshot); + + CmdClientToServerSync(syncData); + + if (cachedChangedComparison == Changed.None || cachedChangedComparison == Changed.CompressRot) + { + hasSentUnchangedPosition = true; + } + else + { + hasSentUnchangedPosition = false; + UpdateLastSentSnapshot(cachedChangedComparison, snapshot); + } + } + else + { + cachedSnapshotComparison = CompareSnapshots(snapshot); + if (cachedSnapshotComparison && hasSentUnchangedPosition && onlySyncOnChange) { return; } + + if (compressRotation) + { + CmdClientToServerSyncCompressRotation( + // only sync what the user wants to sync + syncPosition && positionChanged ? snapshot.position : default(Vector3?), + syncRotation && rotationChanged ? Compression.CompressQuaternion(snapshot.rotation) : default(uint?), + syncScale && scaleChanged ? snapshot.scale : default(Vector3?) + ); + } + else + { + CmdClientToServerSync( + // only sync what the user wants to sync + syncPosition && positionChanged ? snapshot.position : default(Vector3?), + syncRotation && rotationChanged ? snapshot.rotation : default(Quaternion?), + syncScale && scaleChanged ? snapshot.scale : default(Vector3?) + ); + } + + if (cachedSnapshotComparison) + { + hasSentUnchangedPosition = true; + } + else + { + hasSentUnchangedPosition = false; + + // Fixes https://github.com/MirrorNetworking/Mirror/issues/3572 + // This also fixes https://github.com/MirrorNetworking/Mirror/issues/3573 + // with the exception of Quaternion.Angle sensitivity has to be > 0.16. + // Unity issue, we are leaving it as is. + if (positionChanged) lastSnapshot.position = snapshot.position; + if (rotationChanged) lastSnapshot.rotation = snapshot.rotation; + if (positionChanged) lastSnapshot.scale = snapshot.scale; + } + } + } + } + + void UpdateClientInterpolation() + { + // only while we have snapshots + if (clientSnapshots.Count == 0) return; + + // step the interpolation without touching time. + // NetworkClient is responsible for time globally. + SnapshotInterpolation.StepInterpolation( + clientSnapshots, + NetworkTime.time, // == NetworkClient.localTimeline from snapshot interpolation + out TransformSnapshot from, + out TransformSnapshot to, + out double t); + + // interpolate & apply + TransformSnapshot computed = TransformSnapshot.Interpolate(from, to, t); + Apply(computed, to); + } + + public override void OnSerialize(NetworkWriter writer, bool initialState) + { + // sync target component's position on spawn. + // fixes https://github.com/vis2k/Mirror/pull/3051/ + // (Spawn message wouldn't sync NTChild positions either) + if (initialState) + { + if (syncPosition) writer.WriteVector3(GetPosition()); + if (syncRotation) writer.WriteQuaternion(GetRotation()); + if (syncScale) writer.WriteVector3(GetScale()); + } + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + // sync target component's position on spawn. + // fixes https://github.com/vis2k/Mirror/pull/3051/ + // (Spawn message wouldn't sync NTChild positions either) + if (initialState) + { + if (syncPosition) SetPosition(reader.ReadVector3()); + if (syncRotation) SetRotation(reader.ReadQuaternion()); + if (syncScale) SetScale(reader.ReadVector3()); + } + } + + // Returns true if position, rotation AND scale are unchanged, within given sensitivity range. + protected virtual bool CompareSnapshots(TransformSnapshot currentSnapshot) + { + positionChanged = Vector3.SqrMagnitude(lastSnapshot.position - currentSnapshot.position) > positionSensitivity * positionSensitivity; + rotationChanged = Quaternion.Angle(lastSnapshot.rotation, currentSnapshot.rotation) > rotationSensitivity; + scaleChanged = Vector3.SqrMagnitude(lastSnapshot.scale - currentSnapshot.scale) > scaleSensitivity * scaleSensitivity; + + return (!positionChanged && !rotationChanged && !scaleChanged); + } + + // cmd ///////////////////////////////////////////////////////////////// + // only unreliable. see comment above of this file. + [Command(channel = Channels.Unreliable)] + void CmdClientToServerSync(Vector3? position, Quaternion? rotation, Vector3? scale) + { + OnClientToServerSync(position, rotation, scale); + //For client authority, immediately pass on the client snapshot to all other + //clients instead of waiting for server to send its snapshots. + if (syncDirection == SyncDirection.ClientToServer) + RpcServerToClientSync(position, rotation, scale); + } + + // cmd ///////////////////////////////////////////////////////////////// + // only unreliable. see comment above of this file. + [Command(channel = Channels.Unreliable)] + void CmdClientToServerSyncCompressRotation(Vector3? position, uint? rotation, Vector3? scale) + { + // A fix to not apply current interpolated GetRotation when receiving null/unchanged value, instead use last sent snapshot rotation. + Quaternion newRotation; + if (rotation.HasValue) + { + newRotation = Compression.DecompressQuaternion((uint)rotation); + } + else + { + newRotation = serverSnapshots.Count > 0 ? serverSnapshots.Values[serverSnapshots.Count - 1].rotation : GetRotation(); + } + OnClientToServerSync(position, newRotation, scale); + //For client authority, immediately pass on the client snapshot to all other + //clients instead of waiting for server to send its snapshots. + if (syncDirection == SyncDirection.ClientToServer) + RpcServerToClientSyncCompressRotation(position, rotation, scale); + } + + // local authority client sends sync message to server for broadcasting + protected virtual void OnClientToServerSync(Vector3? position, Quaternion? rotation, Vector3? scale) + { + // only apply if in client authority mode + if (syncDirection != SyncDirection.ClientToServer) return; + + // protect against ever growing buffer size attacks + if (serverSnapshots.Count >= connectionToClient.snapshotBufferSizeLimit) return; + + // only player owned objects (with a connection) can send to + // server. we can get the timestamp from the connection. + double timestamp = connectionToClient.remoteTimeStamp; + + if (onlySyncOnChange) + { + double timeIntervalCheck = bufferResetMultiplier * sendIntervalMultiplier * NetworkClient.sendInterval; + + if (serverSnapshots.Count > 0 && serverSnapshots.Values[serverSnapshots.Count - 1].remoteTime + timeIntervalCheck < timestamp) + ResetState(); + } + + AddSnapshot(serverSnapshots, connectionToClient.remoteTimeStamp + timeStampAdjustment + offset, position, rotation, scale); + } + + // rpc ///////////////////////////////////////////////////////////////// + // only unreliable. see comment above of this file. + [ClientRpc(channel = Channels.Unreliable)] + void RpcServerToClientSync(Vector3? position, Quaternion? rotation, Vector3? scale) => + OnServerToClientSync(position, rotation, scale); + + // rpc ///////////////////////////////////////////////////////////////// + // only unreliable. see comment above of this file. + [ClientRpc(channel = Channels.Unreliable)] + void RpcServerToClientSyncCompressRotation(Vector3? position, uint? rotation, Vector3? scale) + { + // A fix to not apply current interpolated GetRotation when receiving null/unchanged value, instead use last sent snapshot rotation. + Quaternion newRotation; + if (rotation.HasValue) + { + newRotation = Compression.DecompressQuaternion((uint)rotation); + } + else + { + newRotation = clientSnapshots.Count > 0 ? clientSnapshots.Values[clientSnapshots.Count - 1].rotation : GetRotation(); + } + OnServerToClientSync(position, newRotation, scale); + } + + // server broadcasts sync message to all clients + protected virtual void OnServerToClientSync(Vector3? position, Quaternion? rotation, Vector3? scale) + { + // in host mode, the server sends rpcs to all clients. + // the host client itself will receive them too. + // -> host server is always the source of truth + // -> we can ignore any rpc on the host client + // => otherwise host objects would have ever growing clientBuffers + // (rpc goes to clients. if isServer is true too then we are host) + if (isServer) return; + + // don't apply for local player with authority + if (IsClientWithAuthority) return; + + // on the client, we receive rpcs for all entities. + // not all of them have a connectionToServer. + // but all of them go through NetworkClient.connection. + // we can get the timestamp from there. + double timestamp = NetworkClient.connection.remoteTimeStamp; + + if (onlySyncOnChange) + { + double timeIntervalCheck = bufferResetMultiplier * sendIntervalMultiplier * NetworkServer.sendInterval; + + if (clientSnapshots.Count > 0 && clientSnapshots.Values[clientSnapshots.Count - 1].remoteTime + timeIntervalCheck < timestamp) + ResetState(); + } + + AddSnapshot(clientSnapshots, NetworkClient.connection.remoteTimeStamp + timeStampAdjustment + offset, position, rotation, scale); + } + + protected virtual void UpdateLastSentSnapshot(Changed change, TransformSnapshot currentSnapshot) + { + if (change == Changed.None || change == Changed.CompressRot) return; + + if ((change & Changed.PosX) > 0) lastSnapshot.position.x = currentSnapshot.position.x; + if ((change & Changed.PosY) > 0) lastSnapshot.position.y = currentSnapshot.position.y; + if ((change & Changed.PosZ) > 0) lastSnapshot.position.z = currentSnapshot.position.z; + + if (compressRotation) + { + if ((change & Changed.Rot) > 0) lastSnapshot.rotation = currentSnapshot.rotation; + } + else + { + Vector3 newRotation; + newRotation.x = (change & Changed.RotX) > 0 ? currentSnapshot.rotation.eulerAngles.x : lastSnapshot.rotation.eulerAngles.x; + newRotation.y = (change & Changed.RotY) > 0 ? currentSnapshot.rotation.eulerAngles.y : lastSnapshot.rotation.eulerAngles.y; + newRotation.z = (change & Changed.RotZ) > 0 ? currentSnapshot.rotation.eulerAngles.z : lastSnapshot.rotation.eulerAngles.z; + + lastSnapshot.rotation = Quaternion.Euler(newRotation); + } + + if ((change & Changed.Scale) > 0) lastSnapshot.scale = currentSnapshot.scale; + } + + // Returns true if position, rotation AND scale are unchanged, within given sensitivity range. + // Note the sensitivity comparison are different for pos, rot and scale. + protected virtual Changed CompareChangedSnapshots(TransformSnapshot currentSnapshot) + { + Changed change = Changed.None; + + if (syncPosition) + { + bool positionChanged = Vector3.SqrMagnitude(lastSnapshot.position - currentSnapshot.position) > positionSensitivity * positionSensitivity; + if (positionChanged) + { + if (Mathf.Abs(lastSnapshot.position.x - currentSnapshot.position.x) > positionSensitivity) change |= Changed.PosX; + if (Mathf.Abs(lastSnapshot.position.y - currentSnapshot.position.y) > positionSensitivity) change |= Changed.PosY; + if (Mathf.Abs(lastSnapshot.position.z - currentSnapshot.position.z) > positionSensitivity) change |= Changed.PosZ; + } + } + + if (syncRotation) + { + if (compressRotation) + { + bool rotationChanged = Quaternion.Angle(lastSnapshot.rotation, currentSnapshot.rotation) > rotationSensitivity; + if (rotationChanged) + { + // Here we set all Rot enum flags, to tell us if there was a change in rotation + // when using compression. If no change, we don't write the compressed Quat. + change |= Changed.CompressRot; + change |= Changed.Rot; + } + else + { + change |= Changed.CompressRot; + } + } + else + { + if (Mathf.Abs(lastSnapshot.rotation.eulerAngles.x - currentSnapshot.rotation.eulerAngles.x) > rotationSensitivity) change |= Changed.RotX; + if (Mathf.Abs(lastSnapshot.rotation.eulerAngles.y - currentSnapshot.rotation.eulerAngles.y) > rotationSensitivity) change |= Changed.RotY; + if (Mathf.Abs(lastSnapshot.rotation.eulerAngles.z - currentSnapshot.rotation.eulerAngles.z) > rotationSensitivity) change |= Changed.RotZ; + } + } + + if (syncScale) + { + if (Vector3.SqrMagnitude(lastSnapshot.scale - currentSnapshot.scale) > scaleSensitivity * scaleSensitivity) change |= Changed.Scale; + } + + return change; + } + + [Command(channel = Channels.Unreliable)] + void CmdClientToServerSync(SyncData syncData) + { + OnClientToServerSync(syncData); + //For client authority, immediately pass on the client snapshot to all other + //clients instead of waiting for server to send its snapshots. + if (syncDirection == SyncDirection.ClientToServer) + RpcServerToClientSync(syncData); + } + + protected virtual void OnClientToServerSync(SyncData syncData) + { + // only apply if in client authority mode + if (syncDirection != SyncDirection.ClientToServer) return; + + // protect against ever growing buffer size attacks + if (serverSnapshots.Count >= connectionToClient.snapshotBufferSizeLimit) return; + + // only player owned objects (with a connection) can send to + // server. we can get the timestamp from the connection. + double timestamp = connectionToClient.remoteTimeStamp; + + if (onlySyncOnChange) + { + double timeIntervalCheck = bufferResetMultiplier * sendIntervalMultiplier * NetworkClient.sendInterval; + + if (serverSnapshots.Count > 0 && serverSnapshots.Values[serverSnapshots.Count - 1].remoteTime + timeIntervalCheck < timestamp) + ResetState(); + } + + UpdateSyncData(ref syncData, serverSnapshots); + + AddSnapshot(serverSnapshots, connectionToClient.remoteTimeStamp + timeStampAdjustment + offset, syncData.position, syncData.quatRotation, syncData.scale); + } + + + [ClientRpc(channel = Channels.Unreliable)] + void RpcServerToClientSync(SyncData syncData) => + OnServerToClientSync(syncData); + + protected virtual void OnServerToClientSync(SyncData syncData) + { + // in host mode, the server sends rpcs to all clients. + // the host client itself will receive them too. + // -> host server is always the source of truth + // -> we can ignore any rpc on the host client + // => otherwise host objects would have ever growing clientBuffers + // (rpc goes to clients. if isServer is true too then we are host) + if (isServer) return; + + // don't apply for local player with authority + if (IsClientWithAuthority) return; + + // on the client, we receive rpcs for all entities. + // not all of them have a connectionToServer. + // but all of them go through NetworkClient.connection. + // we can get the timestamp from there. + double timestamp = NetworkClient.connection.remoteTimeStamp; + + if (onlySyncOnChange) + { + double timeIntervalCheck = bufferResetMultiplier * sendIntervalMultiplier * NetworkServer.sendInterval; + + if (clientSnapshots.Count > 0 && clientSnapshots.Values[clientSnapshots.Count - 1].remoteTime + timeIntervalCheck < timestamp) + ResetState(); + } + + UpdateSyncData(ref syncData, clientSnapshots); + + AddSnapshot(clientSnapshots, NetworkClient.connection.remoteTimeStamp + timeStampAdjustment + offset, syncData.position, syncData.quatRotation, syncData.scale); + } + + protected virtual void UpdateSyncData(ref SyncData syncData, SortedList snapshots) + { + if (syncData.changedDataByte == Changed.None || syncData.changedDataByte == Changed.CompressRot) + { + syncData.position = snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].position : GetPosition(); + syncData.quatRotation = snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].rotation : GetRotation(); + syncData.scale = snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].scale : GetScale(); + } + else + { + // Just going to update these without checking if syncposition or not, + // because if not syncing position, NT will not apply any position data + // to the target during Apply(). + + syncData.position.x = (syncData.changedDataByte & Changed.PosX) > 0 ? syncData.position.x : (snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].position.x : GetPosition().x); + syncData.position.y = (syncData.changedDataByte & Changed.PosY) > 0 ? syncData.position.y : (snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].position.y : GetPosition().y); + syncData.position.z = (syncData.changedDataByte & Changed.PosZ) > 0 ? syncData.position.z : (snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].position.z : GetPosition().z); + + // If compressRot is true, we already have the Quat in syncdata. + if ((syncData.changedDataByte & Changed.CompressRot) == 0) + { + syncData.vecRotation.x = (syncData.changedDataByte & Changed.RotX) > 0 ? syncData.vecRotation.x : (snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].rotation.eulerAngles.x : GetRotation().eulerAngles.x); + syncData.vecRotation.y = (syncData.changedDataByte & Changed.RotY) > 0 ? syncData.vecRotation.y : (snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].rotation.eulerAngles.y : GetRotation().eulerAngles.y); ; + syncData.vecRotation.z = (syncData.changedDataByte & Changed.RotZ) > 0 ? syncData.vecRotation.z : (snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].rotation.eulerAngles.z : GetRotation().eulerAngles.z); + + syncData.quatRotation = Quaternion.Euler(syncData.vecRotation); + } + else + { + syncData.quatRotation = (syncData.changedDataByte & Changed.Rot) > 0 ? syncData.quatRotation : (snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].rotation : GetRotation()); + } + + syncData.scale = (syncData.changedDataByte & Changed.Scale) > 0 ? syncData.scale : (snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].scale : GetScale()); + } + } + + // This is to extract position/rotation/scale data from payload. Override + // Construct and Deconstruct if you are implementing a different SyncData logic. + // Note however that snapshot interpolation still requires the basic 3 data + // position, rotation and scale, which are computed from here. + protected virtual void DeconstructSyncData(System.ArraySegment receivedPayload, out byte? changedFlagData, out Vector3? position, out Quaternion? rotation, out Vector3? scale) + { + using (NetworkReaderPooled reader = NetworkReaderPool.Get(receivedPayload)) + { + SyncData syncData = reader.Read(); + changedFlagData = (byte)syncData.changedDataByte; + position = syncData.position; + rotation = syncData.quatRotation; + scale = syncData.scale; + } + } + } +} diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformUnreliable.cs.meta b/Assets/Mirror/Components/NetworkTransform/NetworkTransformUnreliable.cs.meta new file mode 100644 index 0000000..3a4a75a --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformUnreliable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a553cb17010b2403e8523b558bffbc14 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkTransform/TransformSnapshot.cs b/Assets/Mirror/Components/NetworkTransform/TransformSnapshot.cs new file mode 100644 index 0000000..01b863c --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/TransformSnapshot.cs @@ -0,0 +1,68 @@ +// snapshot for snapshot interpolation +// https://gafferongames.com/post/snapshot_interpolation/ +// position, rotation, scale for compatibility for now. +using UnityEngine; + +namespace Mirror +{ + // NetworkTransform Snapshot + public struct TransformSnapshot : Snapshot + { + // time or sequence are needed to throw away older snapshots. + // + // glenn fiedler starts with a 16 bit sequence number. + // supposedly this is meant as a simplified example. + // in the end we need the remote timestamp for accurate interpolation + // and buffering over time. + // + // note: in theory, IF server sends exactly(!) at the same interval then + // the 16 bit ushort timestamp would be enough to calculate the + // remote time (sequence * sendInterval). but Unity's update is + // not guaranteed to run on the exact intervals / do catchup. + // => remote timestamp is better for now + // + // [REMOTE TIME, NOT LOCAL TIME] + // => DOUBLE for long term accuracy & batching gives us double anyway + public double remoteTime { get; set; } + + // the local timestamp (when we received it) + // used to know if the first two snapshots are old enough to start. + public double localTime { get; set; } + + public Vector3 position; + public Quaternion rotation; + public Vector3 scale; + + public TransformSnapshot(double remoteTime, double localTime, Vector3 position, Quaternion rotation, Vector3 scale) + { + this.remoteTime = remoteTime; + this.localTime = localTime; + this.position = position; + this.rotation = rotation; + this.scale = scale; + } + + public static TransformSnapshot Interpolate(TransformSnapshot from, TransformSnapshot to, double t) + { + // NOTE: + // Vector3 & Quaternion components are float anyway, so we can + // keep using the functions with 't' as float instead of double. + return new TransformSnapshot( + // interpolated snapshot is applied directly. don't need timestamps. + 0, 0, + // lerp position/rotation/scale unclamped in case we ever need + // to extrapolate. atm SnapshotInterpolation never does. + Vector3.LerpUnclamped(from.position, to.position, (float)t), + // IMPORTANT: LerpUnclamped(0, 60, 1.5) extrapolates to ~86. + // SlerpUnclamped(0, 60, 1.5) extrapolates to 90! + // (0, 90, 1.5) is even worse. for Lerp. + // => Slerp works way better for our euler angles. + Quaternion.SlerpUnclamped(from.rotation, to.rotation, (float)t), + Vector3.LerpUnclamped(from.scale, to.scale, (float)t) + ); + } + + public override string ToString() => + $"TransformSnapshot(remoteTime={remoteTime:F2}, localTime={localTime:F2}, pos={position}, rot={rotation}, scale={scale})"; + } +} diff --git a/Assets/Mirror/Components/NetworkTransform/TransformSnapshot.cs.meta b/Assets/Mirror/Components/NetworkTransform/TransformSnapshot.cs.meta new file mode 100644 index 0000000..f43458f --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/TransformSnapshot.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3dae77b43dc4e1dbb2012924b2da79c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/NetworkTransform/TransformSyncData.cs b/Assets/Mirror/Components/NetworkTransform/TransformSyncData.cs new file mode 100644 index 0000000..9b6d51c --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/TransformSyncData.cs @@ -0,0 +1,156 @@ +using UnityEngine; +using System; +using Mirror; + +namespace Mirror +{ + [Serializable] + public struct SyncData + { + public Changed changedDataByte; + public Vector3 position; + public Quaternion quatRotation; + public Vector3 vecRotation; + public Vector3 scale; + + public SyncData(Changed _dataChangedByte, Vector3 _position, Quaternion _rotation, Vector3 _scale) + { + this.changedDataByte = _dataChangedByte; + this.position = _position; + this.quatRotation = _rotation; + this.vecRotation = quatRotation.eulerAngles; + this.scale = _scale; + } + + public SyncData(Changed _dataChangedByte, TransformSnapshot _snapshot) + { + this.changedDataByte = _dataChangedByte; + this.position = _snapshot.position; + this.quatRotation = _snapshot.rotation; + this.vecRotation = quatRotation.eulerAngles; + this.scale = _snapshot.scale; + } + + public SyncData(Changed _dataChangedByte, Vector3 _position, Vector3 _vecRotation, Vector3 _scale) + { + this.changedDataByte = _dataChangedByte; + this.position = _position; + this.vecRotation = _vecRotation; + this.quatRotation = Quaternion.Euler(vecRotation); + this.scale = _scale; + } + } + + [Flags] + public enum Changed : byte + { + None = 0, + PosX = 1 << 0, + PosY = 1 << 1, + PosZ = 1 << 2, + CompressRot = 1 << 3, + RotX = 1 << 4, + RotY = 1 << 5, + RotZ = 1 << 6, + Scale = 1 << 7, + + Pos = PosX | PosY | PosZ, + Rot = RotX | RotY | RotZ + } + + + public static class SyncDataReaderWriter + { + public static void WriteSyncData(this NetworkWriter writer, SyncData syncData) + { + writer.WriteByte((byte)syncData.changedDataByte); + + // Write position + if ((syncData.changedDataByte & Changed.PosX) > 0) + { + writer.WriteFloat(syncData.position.x); + } + + if ((syncData.changedDataByte & Changed.PosY) > 0) + { + writer.WriteFloat(syncData.position.y); + } + + if ((syncData.changedDataByte & Changed.PosZ) > 0) + { + writer.WriteFloat(syncData.position.z); + } + + // Write rotation + if ((syncData.changedDataByte & Changed.CompressRot) > 0) + { + if((syncData.changedDataByte & Changed.Rot) > 0) + { + writer.WriteUInt(Compression.CompressQuaternion(syncData.quatRotation)); + } + } + else + { + if ((syncData.changedDataByte & Changed.RotX) > 0) + { + writer.WriteFloat(syncData.quatRotation.eulerAngles.x); + } + + if ((syncData.changedDataByte & Changed.RotY) > 0) + { + writer.WriteFloat(syncData.quatRotation.eulerAngles.y); + } + + if ((syncData.changedDataByte & Changed.RotZ) > 0) + { + writer.WriteFloat(syncData.quatRotation.eulerAngles.z); + } + } + + // Write scale + if ((syncData.changedDataByte & Changed.Scale) > 0) + { + writer.WriteVector3(syncData.scale); + } + } + + public static SyncData ReadSyncData(this NetworkReader reader) + { + Changed changedData = (Changed)reader.ReadByte(); + + // If we have nothing to read here, let's say because posX is unchanged, then we can write anything + // for now, but in the NT, we will need to check changedData again, to put the right values of the axis + // back. We don't have it here. + + Vector3 position = + new Vector3( + (changedData & Changed.PosX) > 0 ? reader.ReadFloat() : 0, + (changedData & Changed.PosY) > 0 ? reader.ReadFloat() : 0, + (changedData & Changed.PosZ) > 0 ? reader.ReadFloat() : 0 + ); + + Vector3 vecRotation = new Vector3(); + Quaternion quatRotation = new Quaternion(); + + if ((changedData & Changed.CompressRot) > 0) + { + quatRotation = (changedData & Changed.RotX) > 0 ? Compression.DecompressQuaternion(reader.ReadUInt()) : new Quaternion(); + } + else + { + vecRotation = + new Vector3( + (changedData & Changed.RotX) > 0 ? reader.ReadFloat() : 0, + (changedData & Changed.RotY) > 0 ? reader.ReadFloat() : 0, + (changedData & Changed.RotZ) > 0 ? reader.ReadFloat() : 0 + ); + } + + Vector3 scale = (changedData & Changed.Scale) == Changed.Scale ? reader.ReadVector3() : new Vector3(); + + SyncData _syncData = (changedData & Changed.CompressRot) > 0 ? new SyncData(changedData, position, quatRotation, scale) : new SyncData(changedData, position, vecRotation, scale); + + return _syncData; + } + } +} diff --git a/Assets/Mirror/Components/NetworkTransform/TransformSyncData.cs.meta b/Assets/Mirror/Components/NetworkTransform/TransformSyncData.cs.meta new file mode 100644 index 0000000..15bb004 --- /dev/null +++ b/Assets/Mirror/Components/NetworkTransform/TransformSyncData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1c0832ca88e749ff96fe04cebb617ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/PredictedRigidbody.meta b/Assets/Mirror/Components/PredictedRigidbody.meta new file mode 100644 index 0000000..3bd5cec --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 09cc6745984c453a8cfb4cf4244d2570 +timeCreated: 1693576410 \ No newline at end of file diff --git a/Assets/Mirror/Components/PredictedRigidbody/LocalGhostMaterial.mat b/Assets/Mirror/Components/PredictedRigidbody/LocalGhostMaterial.mat new file mode 100644 index 0000000..ff29a73 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/LocalGhostMaterial.mat @@ -0,0 +1,85 @@ +%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: LocalGhostMaterial + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _ALPHAPREMULTIPLY_ON + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 3000 + stringTagMap: + RenderType: Transparent + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 10 + - _GlossMapScale: 1 + - _Glossiness: 0.92 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 3 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 0 + m_Colors: + - _Color: {r: 1, g: 0, b: 0.067070484, a: 0.15686275} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] diff --git a/Assets/Mirror/Components/PredictedRigidbody/LocalGhostMaterial.mat.meta b/Assets/Mirror/Components/PredictedRigidbody/LocalGhostMaterial.mat.meta new file mode 100644 index 0000000..bd5cfe5 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/LocalGhostMaterial.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 411a48b4a197d4924bec3e3809bc9320 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs new file mode 100644 index 0000000..9c2a66d --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs @@ -0,0 +1,841 @@ +// PredictedRigidbody which stores & indidvidually rewinds history per Rigidbody. +// +// This brings significant performance savings because: +// - if a scene has 1000 objects +// - and a player interacts with say 3 objects at a time +// - Physics.Simulate() would resimulate 1000 objects +// - where as this component only resimulates the 3 changed objects +// +// The downside is that history rewinding is done manually via Vector math, +// instead of real physics. It's not 100% correct - but it sure is fast! +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + public enum CorrectionMode + { + Set, // rigidbody.position/rotation = ... + Move, // rigidbody.MovePosition/Rotation + } + + // [RequireComponent(typeof(Rigidbody))] <- RB is moved out at runtime, can't require it. + public class PredictedRigidbody : NetworkBehaviour + { + Transform tf; // this component is performance critical. cache .transform getter! + protected Rigidbody predictedRigidbody; // always valid, even while moved onto the ghost. + Vector3 lastPosition; + + // motion smoothing happen on-demand, because it requires moving physics components to another GameObject. + // this only starts at a given velocity and ends when stopped moving. + // to avoid constant on/off/on effects, it also stays on for a minimum time. + [Header("Motion Smoothing")] + [Tooltip("Smoothing via Ghost-following only happens on demand, while moving with a minimum velocity.")] + public float motionSmoothingVelocityThreshold = 0.1f; + public float motionSmoothingAngularVelocityThreshold = 0.1f; + public float motionSmoothingTimeTolerance = 0.5f; + double motionSmoothingLastMovedTime; + + // client keeps state history for correction & reconciliation. + // this needs to be a SortedList because we need to be able to insert inbetween. + // RingBuffer would be faster iteration, but can't do insertions. + [Header("State History")] + public int stateHistoryLimit = 32; // 32 x 50 ms = 1.6 seconds is definitely enough + readonly SortedList stateHistory = new SortedList(); + public float recordInterval = 0.050f; + + [Tooltip("(Optional) performance optimization where FixedUpdate.RecordState() only inserts state into history if the state actually changed.\nThis is generally a good idea.")] + public bool onlyRecordChanges = true; + + [Tooltip("(Optional) performance optimization where received state is compared to the LAST recorded state first, before sampling the whole history.\n\nThis can save significant traversal overhead for idle objects with a tiny chance of missing corrections for objects which revisisted the same position in the recent history twice.")] + public bool compareLastFirst = true; + + [Header("Reconciliation")] + [Tooltip("Correction threshold in meters. For example, 0.1 means that if the client is off by more than 10cm, it gets corrected.")] + public double positionCorrectionThreshold = 0.10; + [Tooltip("Correction threshold in degrees. For example, 5 means that if the client is off by more than 5 degrees, it gets corrected.")] + public double rotationCorrectionThreshold = 5; + + [Tooltip("Applying server corrections one frame ahead gives much better results. We don't know why yet, so this is an option for now.")] + public bool oneFrameAhead = true; + + [Header("Smoothing")] + [Tooltip("Configure how to apply the corrected state.")] + public CorrectionMode correctionMode = CorrectionMode.Move; + + [Tooltip("Snap to the server state directly when velocity is < threshold. This is useful to reduce jitter/fighting effects before coming to rest.\nNote this applies position, rotation and velocity(!) so it's still smooth.")] + public float snapThreshold = 2; // 0.5 has too much fighting-at-rest, 2 seems ideal. + + [Header("Visual Interpolation")] + [Tooltip("After creating the visual interpolation object, keep showing the original Rigidbody with a ghost (transparent) material for debugging.")] + public bool showGhost = true; + [Tooltip("Physics components are moved onto a ghost object beyond this threshold. Main object visually interpolates to it.")] + public float ghostVelocityThreshold = 0.1f; + + [Tooltip("After creating the visual interpolation object, replace this object's renderer materials with the ghost (ideally transparent) material.")] + public Material localGhostMaterial; + public Material remoteGhostMaterial; + + [Tooltip("How fast to interpolate to the target position, relative to how far we are away from it.\nHigher value will be more jitter but sharper moves, lower value will be less jitter but a little too smooth / rounded moves.")] + public float positionInterpolationSpeed = 15; // 10 is a little too low for billiards at least + public float rotationInterpolationSpeed = 10; + + [Tooltip("Teleport if we are further than 'multiplier x collider size' behind.")] + public float teleportDistanceMultiplier = 10; + + [Header("Bandwidth")] + [Tooltip("Reduce sends while velocity==0. Client's objects may slightly move due to gravity/physics, so we still want to send corrections occasionally even if an object is idle on the server the whole time.")] + public bool reduceSendsWhileIdle = true; + + [Header("Debugging")] + public float lineTime = 10; + + // Rigidbody & Collider are moved out into a separate object. + // this way the visual object can smoothly follow. + protected GameObject physicsCopy; + // protected Transform physicsCopyTransform; // caching to avoid GetComponent + // protected Rigidbody physicsCopyRigidbody => rb; // caching to avoid GetComponent + // protected Collider physicsCopyCollider; // caching to avoid GetComponent + float smoothFollowThreshold; // caching to avoid calculation in LateUpdate + + // we also create one extra ghost for the exact known server state. + protected GameObject remoteCopy; + + // joints + Vector3 initialPosition; + Quaternion initialRotation; + // Vector3 initialScale; // don't change scale for now. causes issues with parenting. + + void Awake() + { + tf = transform; + predictedRigidbody = GetComponent(); + if (predictedRigidbody == null) throw new InvalidOperationException($"Prediction: {name} is missing a Rigidbody component."); + + // cache some threshold to avoid calculating them in LateUpdate + float colliderSize = GetComponentInChildren().bounds.size.magnitude; + smoothFollowThreshold = colliderSize * teleportDistanceMultiplier; + + // cache initial position/rotation/scale to be used when moving physics components (configurable joints' range of motion) + initialPosition = tf.position; + initialRotation = tf.rotation; + // initialScale = tf.localScale; + } + + protected virtual void CopyRenderersAsGhost(GameObject destination, Material material) + { + // find the MeshRenderer component, which sometimes is on a child. + MeshRenderer originalMeshRenderer = GetComponentInChildren(true); + MeshFilter originalMeshFilter = GetComponentInChildren(true); + if (originalMeshRenderer != null && originalMeshFilter != null) + { + MeshFilter meshFilter = destination.AddComponent(); + meshFilter.mesh = originalMeshFilter.mesh; + + MeshRenderer meshRenderer = destination.AddComponent(); + meshRenderer.material = originalMeshRenderer.material; + + // renderers often have multiple materials. copy all. + if (originalMeshRenderer.materials != null) + { + Material[] materials = new Material[originalMeshRenderer.materials.Length]; + for (int i = 0; i < materials.Length; ++i) + { + materials[i] = material; + } + meshRenderer.materials = materials; // need to reassign to see it in effect + } + } + // if we didn't find a renderer, show a warning + else Debug.LogWarning($"PredictedRigidbody: {name} found no renderer to copy onto the visual object. If you are using a custom setup, please overwrite PredictedRigidbody.CreateVisualCopy()."); + } + + // instantiate a physics-only copy of the gameobject to apply corrections. + // this way the main visual object can smoothly follow. + // it's best to separate the physics instead of separating the renderers. + // some projects have complex rendering / animation setups which we can't touch. + // besides, Rigidbody+Collider are two components, where as renders may be many. + protected virtual void CreateGhosts() + { + // skip if host mode or already separated + if (isServer || physicsCopy != null) return; + + Debug.Log($"Separating Physics for {name}"); + + // create an empty GameObject with the same name + _Physical + // it's important to copy world position/rotation/scale, not local! + // because the original object may be a child of another. + // + // for example: + // parent (scale=1.5) + // child (scale=0.5) + // + // if we copy localScale then the copy has scale=0.5, where as the + // original would have a global scale of ~1.0. + physicsCopy = new GameObject($"{name}_Physical"); + + // assign the same Layer for the physics copy. + // games may use a custom physics collision matrix, layer matters. + physicsCopy.layer = gameObject.layer; + + // add the PredictedRigidbodyPhysical component + PredictedRigidbodyPhysicsGhost physicsGhostRigidbody = physicsCopy.AddComponent(); + physicsGhostRigidbody.target = tf; + + // when moving (Configurable)Joints, their range of motion is + // relative to the initial position. if we move them after the + // GameObject rotated, the range of motion is wrong. + // the easiest solution is to move to initial position, + // then move physics components, then move back. + // => remember previous + Vector3 position = tf.position; + Quaternion rotation = tf.rotation; + // Vector3 scale = tf.localScale; // don't change scale for now. causes issues with parenting. + // => reset to initial + physicsGhostRigidbody.transform.position = tf.position = initialPosition; + physicsGhostRigidbody.transform.rotation = tf.rotation = initialRotation; + physicsGhostRigidbody.transform.localScale = tf.lossyScale;// world scale! // = initialScale; // don't change scale for now. causes issues with parenting. + // => move physics components + PredictionUtils.MovePhysicsComponents(gameObject, physicsCopy); + // => reset previous + physicsGhostRigidbody.transform.position = tf.position = position; + physicsGhostRigidbody.transform.rotation = tf.rotation = rotation; + //physicsGhostRigidbody.transform.localScale = tf.lossyScale; // world scale! //= scale; // don't change scale for now. causes issues with parenting. + + // show ghost by copying all renderers / materials with ghost material applied + if (showGhost) + { + // one for the locally predicted rigidbody + CopyRenderersAsGhost(physicsCopy, localGhostMaterial); + + // one for the latest remote state for comparison + // it's important to copy world position/rotation/scale, not local! + // because the original object may be a child of another. + // + // for example: + // parent (scale=1.5) + // child (scale=0.5) + // + // if we copy localScale then the copy has scale=0.5, where as the + // original would have a global scale of ~1.0. + remoteCopy = new GameObject($"{name}_Remote"); + remoteCopy.transform.position = tf.position; // world position! + remoteCopy.transform.rotation = tf.rotation; // world rotation! + remoteCopy.transform.localScale = tf.lossyScale; // world scale! + CopyRenderersAsGhost(remoteCopy, remoteGhostMaterial); + } + + // assign our Rigidbody reference to the ghost + predictedRigidbody = physicsCopy.GetComponent(); + } + + protected virtual void DestroyGhosts() + { + // move the copy's Rigidbody back onto self. + // important for scene objects which may be reused for AOI spawn/despawn. + // otherwise next time they wouldn't have a collider anymore. + if (physicsCopy != null) + { + // when moving (Configurable)Joints, their range of motion is + // relative to the initial position. if we move them after the + // GameObject rotated, the range of motion is wrong. + // the easiest solution is to move to initial position, + // then move physics components, then move back. + // => remember previous + Vector3 position = tf.position; + Quaternion rotation = tf.rotation; + Vector3 scale = tf.localScale; + // => reset to initial + physicsCopy.transform.position = tf.position = initialPosition; + physicsCopy.transform.rotation = tf.rotation = initialRotation; + physicsCopy.transform.localScale = tf.lossyScale;// = initialScale; + // => move physics components + PredictionUtils.MovePhysicsComponents(physicsCopy, gameObject); + // => reset previous + tf.position = position; + tf.rotation = rotation; + tf.localScale = scale; + + // when moving components back, we need to undo the joints initial-delta rotation that we added. + Destroy(physicsCopy); + + // reassign our Rigidbody reference + predictedRigidbody = GetComponent(); + } + + // simply destroy the remote copy + if (remoteCopy != null) Destroy(remoteCopy); + } + + // this shows in profiler LateUpdates! need to make this as fast as possible! + protected virtual void SmoothFollowPhysicsCopy() + { + // hard follow: + // tf.position = physicsCopyCollider.position; + // tf.rotation = physicsCopyCollider.rotation; + + // ORIGINAL VERSION: CLEAN AND SIMPLE + /* + // if we are further than N colliders sizes behind, then teleport + float colliderSize = physicsCopyCollider.bounds.size.magnitude; + float threshold = colliderSize * teleportDistanceMultiplier; + float distance = Vector3.Distance(tf.position, physicsCopyRigidbody.position); + if (distance > threshold) + { + tf.position = physicsCopyRigidbody.position; + tf.rotation = physicsCopyRigidbody.rotation; + Debug.Log($"[PredictedRigidbody] Teleported because distance to physics copy = {distance:F2} > threshold {threshold:F2}"); + return; + } + + // smoothly interpolate to the target position. + // speed relative to how far away we are + float positionStep = distance * positionInterpolationSpeed; + tf.position = Vector3.MoveTowards(tf.position, physicsCopyRigidbody.position, positionStep * Time.deltaTime); + + // smoothly interpolate to the target rotation. + // Quaternion.RotateTowards doesn't seem to work at all, so let's use SLerp. + tf.rotation = Quaternion.Slerp(tf.rotation, physicsCopyRigidbody.rotation, rotationInterpolationSpeed * Time.deltaTime); + */ + + // FAST VERSION: this shows in profiler a lot, so cache EVERYTHING! + tf.GetPositionAndRotation(out Vector3 currentPosition, out Quaternion currentRotation); // faster than tf.position + tf.rotation + Vector3 physicsPosition = predictedRigidbody.position; + Quaternion physicsRotation = predictedRigidbody.rotation; + float deltaTime = Time.deltaTime; + + float distance = Vector3.Distance(currentPosition, physicsPosition); + if (distance > smoothFollowThreshold) + { + tf.SetPositionAndRotation(physicsPosition, physicsRotation); // faster than .position and .rotation manually + Debug.Log($"[PredictedRigidbody] Teleported because distance to physics copy = {distance:F2} > threshold {smoothFollowThreshold:F2}"); + return; + } + + // smoothly interpolate to the target position. + // speed relative to how far away we are. + // => speed increases by distance² because the further away, the + // sooner we need to catch the fuck up + // float positionStep = (distance * distance) * interpolationSpeed; + float positionStep = distance * positionInterpolationSpeed; + Vector3 newPosition = Vector3.MoveTowards(currentPosition, physicsPosition, positionStep * deltaTime); + + // smoothly interpolate to the target rotation. + // Quaternion.RotateTowards doesn't seem to work at all, so let's use SLerp. + // Quaternions always need to be normalized in order to be a valid rotation after operations + Quaternion newRotation = Quaternion.Slerp(currentRotation, physicsRotation, rotationInterpolationSpeed * deltaTime).normalized; + + // assign position and rotation together. faster than accessing manually. + tf.SetPositionAndRotation(newPosition, newRotation); + } + + // destroy visual copy only in OnStopClient(). + // OnDestroy() wouldn't be called for scene objects that are only disabled instead of destroyed. + public override void OnStopClient() + { + DestroyGhosts(); + } + + void UpdateServer() + { + // bandwidth optimization while idle. + if (reduceSendsWhileIdle) + { + // while moving, always sync every frame for immediate corrections. + // while idle, only sync once per second. + // + // we still need to sync occasionally because objects on client + // may still slide or move slightly due to gravity, physics etc. + // and those still need to get corrected if not moving on server. + // + // TODO + // next round of optimizations: if client received nothing for 1s, + // force correct to last received state. then server doesn't need + // to send once per second anymore. + syncInterval = IsMoving() ? 0 : 1; + } + + // always set dirty to always serialize in next sync interval. + SetDirty(); + } + + // movement detection is virtual, in case projects want to use other methods. + protected virtual bool IsMoving() => + predictedRigidbody.linearVelocity.magnitude >= motionSmoothingVelocityThreshold || + predictedRigidbody.angularVelocity.magnitude >= motionSmoothingAngularVelocityThreshold; + + void UpdateGhosting() + { + // client only uses ghosts on demand while interacting. + // this way 1000 GameObjects don't need +1000 Ghost GameObjects all the time! + + // no ghost at the moment + if (physicsCopy == null) + { + // faster than velocity threshold? then create the ghosts. + // with 10% buffer zone so we don't flip flop all the time. + if (IsMoving()) + { + CreateGhosts(); + OnBeginPrediction(); + } + } + // ghosting at the moment + else + { + // always set last moved time while moving. + // this way we can avoid on/off/oneffects when stopping. + if (IsMoving()) + { + motionSmoothingLastMovedTime = NetworkTime.time; + } + // slower than velocity threshold? then destroy the ghosts. + // with a minimum time since starting to move, to avoid on/off/on effects. + else + { + if (NetworkTime.time >= motionSmoothingLastMovedTime + motionSmoothingTimeTolerance) + { + DestroyGhosts(); + OnEndPrediction(); + physicsCopy = null; // TESTING + } + } + } + } + + void Update() + { + if (isServer) UpdateServer(); + if (isClientOnly) UpdateGhosting(); + } + + void LateUpdate() + { + // only follow on client-only, not in server or host mode + if (isClientOnly && physicsCopy) SmoothFollowPhysicsCopy(); + } + + void FixedUpdate() + { + // on clients (not host) we record the current state every FixedUpdate. + // this is cheap, and allows us to keep a dense history. + if (isClientOnly) + { + // OPTIMIZATION: RecordState() is expensive because it inserts into a SortedList. + // only record if state actually changed! + // risks not having up to date states when correcting, + // but it doesn't matter since we'll always compare with the 'newest' anyway. + // + // we check in here instead of in RecordState() because RecordState() should definitely record if we call it! + if (onlyRecordChanges) + { + // TODO maybe don't reuse the correction thresholds? + tf.GetPositionAndRotation(out Vector3 position, out Quaternion rotation); + if (Vector3.Distance(lastRecorded.position, position) < positionCorrectionThreshold && + Quaternion.Angle(lastRecorded.rotation, rotation) < rotationCorrectionThreshold) + { + // Debug.Log($"FixedUpdate for {name}: taking optimized early return instead of recording state."); + return; + } + } + + RecordState(); + } + } + + // manually store last recorded so we can easily check against this + // without traversing the SortedList. + RigidbodyState lastRecorded; + double lastRecordTime; + void RecordState() + { + // instead of recording every fixedupdate, let's record in an interval. + // we don't want to record every tiny move and correct too hard. + if (NetworkTime.time < lastRecordTime + recordInterval) return; + lastRecordTime = NetworkTime.time; + + // NetworkTime.time is always behind by bufferTime. + // prediction aims to be on the exact same server time (immediately). + // use predictedTime to record state, otherwise we would record in the past. + double predictedTime = NetworkTime.predictedTime; + + // FixedUpdate may run twice in the same frame / NetworkTime.time. + // for now, simply don't record if already recorded there. + // previously we checked ContainsKey which is O(logN) for SortedList + // if (stateHistory.ContainsKey(predictedTime)) + // return; + // instead, simply store the last recorded time and don't insert if same. + if (predictedTime == lastRecorded.timestamp) return; + + // keep state history within limit + if (stateHistory.Count >= stateHistoryLimit) + stateHistory.RemoveAt(0); + + // grab current position/rotation/velocity only once. + // this is performance critical, avoid calling .transform multiple times. + tf.GetPositionAndRotation(out Vector3 currentPosition, out Quaternion currentRotation); // faster than accessing .position + .rotation manually + Vector3 currentVelocity = predictedRigidbody.linearVelocity; + Vector3 currentAngularVelocity = predictedRigidbody.angularVelocity; + + // calculate delta to previous state (if any) + Vector3 positionDelta = Vector3.zero; + Vector3 velocityDelta = Vector3.zero; + Vector3 angularVelocityDelta = Vector3.zero; + Quaternion rotationDelta = Quaternion.identity; + if (stateHistory.Count > 0) + { + RigidbodyState last = stateHistory.Values[stateHistory.Count - 1]; + positionDelta = currentPosition - last.position; + velocityDelta = currentVelocity - last.velocity; + // Quaternions always need to be normalized in order to be valid rotations after operations + rotationDelta = (currentRotation * Quaternion.Inverse(last.rotation)).normalized; + angularVelocityDelta = currentAngularVelocity - last.angularVelocity; + + // debug draw the recorded state + // Debug.DrawLine(last.position, currentPosition, Color.red, lineTime); + } + + // create state to insert + RigidbodyState state = new RigidbodyState( + predictedTime, + positionDelta, + currentPosition, + rotationDelta, + currentRotation, + velocityDelta, + currentVelocity, + angularVelocityDelta, + currentAngularVelocity + ); + + // add state to history + stateHistory.Add(predictedTime, state); + + // manually remember last inserted state for faster .Last comparisons + lastRecorded = state; + } + + // optional user callbacks, in case people need to know about events. + protected virtual void OnSnappedIntoPlace() {} + protected virtual void OnBeforeApplyState() {} + protected virtual void OnCorrected() {} + protected virtual void OnBeginPrediction() {} // when the Rigidbody moved above threshold and we created a ghost + protected virtual void OnEndPrediction() {} // when the Rigidbody came to rest and we destroyed the ghost + + void ApplyState(double timestamp, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity) + { + // fix rigidbodies seemingly dancing in place instead of coming to rest. + // hard snap to the position below a threshold velocity. + // this is fine because the visual object still smoothly interpolates to it. + // => consider both velocity and angular velocity (in case of Rigidbodies only rotating with joints etc.) + if (predictedRigidbody.linearVelocity.magnitude <= snapThreshold && + predictedRigidbody.angularVelocity.magnitude <= snapThreshold) + { + // Debug.Log($"Prediction: snapped {name} into place because velocity {predictedRigidbody.velocity.magnitude:F3} <= {snapThreshold:F3}"); + + // apply server state immediately. + // important to apply velocity as well, instead of Vector3.zero. + // in case an object is still slightly moving, we don't want it + // to stop and start moving again on client - slide as well here. + predictedRigidbody.position = position; + predictedRigidbody.rotation = rotation; + // projects may keep Rigidbodies as kinematic sometimes. in that case, setting velocity would log an error + if (!predictedRigidbody.isKinematic) + { + predictedRigidbody.linearVelocity = velocity; + predictedRigidbody.angularVelocity = angularVelocity; + } + + // clear history and insert the exact state we just applied. + // this makes future corrections more accurate. + stateHistory.Clear(); + stateHistory.Add(timestamp, new RigidbodyState( + timestamp, + Vector3.zero, + position, + Quaternion.identity, + rotation, + Vector3.zero, + velocity, + Vector3.zero, + angularVelocity + )); + + // user callback + OnSnappedIntoPlace(); + return; + } + + // we have a callback for snapping into place (above). + // we also need one for corrections without snapping into place. + // call it before applying pos/rot/vel in case we need to set kinematic etc. + OnBeforeApplyState(); + + // Rigidbody .position teleports, while .MovePosition interpolates + // TODO is this a good idea? what about next capture while it's interpolating? + if (correctionMode == CorrectionMode.Move) + { + predictedRigidbody.MovePosition(position); + predictedRigidbody.MoveRotation(rotation); + } + else if (correctionMode == CorrectionMode.Set) + { + predictedRigidbody.position = position; + predictedRigidbody.rotation = rotation; + } + + // there's only one way to set velocity. + // (projects may keep Rigidbodies as kinematic sometimes. in that case, setting velocity would log an error) + if (!predictedRigidbody.isKinematic) + { + predictedRigidbody.linearVelocity = velocity; + predictedRigidbody.angularVelocity = angularVelocity; + } + } + + // process a received server state. + // compares it against our history and applies corrections if needed. + void OnReceivedState(double timestamp, RigidbodyState state) + { + // always update remote state ghost + if (remoteCopy != null) + { + Transform remoteCopyTransform = remoteCopy.transform; + remoteCopyTransform.SetPositionAndRotation(state.position, state.rotation); // faster than .position + .rotation setters + remoteCopyTransform.localScale = tf.lossyScale; // world scale! see CreateGhosts comment. + } + + // OPTIONAL performance optimization when comparing idle objects. + // even idle objects will have a history of ~32 entries. + // sampling & traversing through them is unnecessarily costly. + // instead, compare directly against the current rigidbody position! + // => this is technically not 100% correct if an object runs in + // circles where it may revisit the same position twice. + // => but practically, objects that didn't move will have their + // whole history look like the last inserted state. + // => comparing against that is free and gives us a significant + // performance saving vs. a tiny chance of incorrect results due + // to objects running in circles. + // => the RecordState() call below is expensive too, so we want to + // do this before even recording the latest state. the only way + // to do this (in case last recorded state is too old), is to + // compare against live rigidbody.position without any recording. + // this is as fast as it gets for skipping idle objects. + // + // if this ever causes issues, feel free to disable it. + if (compareLastFirst && + Vector3.Distance(state.position, predictedRigidbody.position) < positionCorrectionThreshold && + Quaternion.Angle(state.rotation, predictedRigidbody.rotation) < rotationCorrectionThreshold) + { + // Debug.Log($"OnReceivedState for {name}: taking optimized early return!"); + return; + } + + // we only capture state every 'interval' milliseconds. + // so the newest entry in 'history' may be up to 'interval' behind 'now'. + // if there's no latency, we may receive a server state for 'now'. + // sampling would fail, if we haven't recorded anything in a while. + // to solve this, always record the current state when receiving a server state. + RecordState(); + + // correction requires at least 2 existing states for 'before' and 'after'. + // if we don't have two yet, drop this state and try again next time once we recorded more. + if (stateHistory.Count < 2) return; + + RigidbodyState oldest = stateHistory.Values[0]; + RigidbodyState newest = stateHistory.Values[stateHistory.Count - 1]; + + // edge case: is the state older than the oldest state in history? + // this can happen if the client gets so far behind the server + // that it doesn't have a recored history to sample from. + // in that case, we should hard correct the client. + // otherwise it could be out of sync as long as it's too far behind. + if (state.timestamp < oldest.timestamp) + { + // when starting, client may only have 2-3 states in history. + // it's expected that server states would be behind those 2-3. + // only show a warning if it's behind the full history limit! + if (stateHistory.Count >= stateHistoryLimit) + Debug.LogWarning($"Hard correcting client object {name} because the client is too far behind the server. History of size={stateHistory.Count} @ t={timestamp:F3} oldest={oldest.timestamp:F3} newest={newest.timestamp:F3}. This would cause the client to be out of sync as long as it's behind."); + + // force apply the state + ApplyState(state.timestamp, state.position, state.rotation, state.velocity, state.angularVelocity); + return; + } + + // edge case: is it newer than the newest state in history? + // this can happen if client's predictedTime predicts too far ahead of the server. + // in that case, log a warning for now but still apply the correction. + // otherwise it could be out of sync as long as it's too far ahead. + // + // for example, when running prediction on the same machine with near zero latency. + // when applying corrections here, this looks just fine on the local machine. + if (newest.timestamp < state.timestamp) + { + // the correction is for a state in the future. + // we clamp it to 'now'. + // but only correct if off by threshold. + // TODO maybe we should interpolate this back to 'now'? + if (Vector3.Distance(state.position, predictedRigidbody.position) >= positionCorrectionThreshold) + { + double ahead = state.timestamp - newest.timestamp; + Debug.Log($"Hard correction because the client is ahead of the server by {(ahead*1000):F1}ms. History of size={stateHistory.Count} @ t={timestamp:F3} oldest={oldest.timestamp:F3} newest={newest.timestamp:F3}. This can happen when latency is near zero, and is fine unless it shows jitter."); + ApplyState(state.timestamp, state.position, state.rotation, state.velocity, state.angularVelocity); + } + return; + } + + // find the two closest client states between timestamp + if (!Prediction.Sample(stateHistory, timestamp, out RigidbodyState before, out RigidbodyState after, out int afterIndex, out double t)) + { + // something went very wrong. sampling should've worked. + // hard correct to recover the error. + Debug.LogError($"Failed to sample history of size={stateHistory.Count} @ t={timestamp:F3} oldest={oldest.timestamp:F3} newest={newest.timestamp:F3}. This should never happen because the timestamp is within history."); + ApplyState(state.timestamp, state.position, state.rotation, state.velocity, state.angularVelocity); + return; + } + + // interpolate between them to get the best approximation + RigidbodyState interpolated = RigidbodyState.Interpolate(before, after, (float)t); + + // calculate the difference between where we were and where we should be + // TODO only position for now. consider rotation etc. too later + float positionDifference = Vector3.Distance(state.position, interpolated.position); + float rotationDifference = Quaternion.Angle(state.rotation, interpolated.rotation); + // Debug.Log($"Sampled history of size={stateHistory.Count} @ {timestamp:F3}: client={interpolated.position} server={state.position} difference={difference:F3} / {correctionThreshold:F3}"); + + // too far off? then correct it + if (positionDifference >= positionCorrectionThreshold || + rotationDifference >= rotationCorrectionThreshold) + { + // Debug.Log($"CORRECTION NEEDED FOR {name} @ {timestamp:F3}: client={interpolated.position} server={state.position} difference={difference:F3}"); + + // show the received correction position + velocity for debugging. + // helps to compare with the interpolated/applied correction locally. + //Debug.DrawLine(state.position, state.position + state.velocity * 0.1f, Color.white, lineTime); + + // insert the correction and correct the history on top of it. + // returns the final recomputed state after rewinding. + RigidbodyState recomputed = Prediction.CorrectHistory(stateHistory, stateHistoryLimit, state, before, after, afterIndex); + + // log, draw & apply the final position. + // always do this here, not when iterating above, in case we aren't iterating. + // for example, on same machine with near zero latency. + // int correctedAmount = stateHistory.Count - afterIndex; + // Debug.Log($"Correcting {name}: {correctedAmount} / {stateHistory.Count} states to final position from: {rb.position} to: {last.position}"); + //Debug.DrawLine(physicsCopyRigidbody.position, recomputed.position, Color.green, lineTime); + ApplyState(recomputed.timestamp, recomputed.position, recomputed.rotation, recomputed.velocity, recomputed.angularVelocity); + + // user callback + OnCorrected(); + } + } + + // send state to clients every sendInterval. + // reliable for now. + // TODO we should use the one from FixedUpdate + public override void OnSerialize(NetworkWriter writer, bool initialState) + { + // Time.time was at the beginning of this frame. + // NetworkLateUpdate->Broadcast->OnSerialize is at the end of the frame. + // as result, client should use this to correct the _next_ frame. + // otherwise we see noticeable resets that seem off by one frame. + // + // to solve this, we can send the current deltaTime. + // server is technically supposed to be at a fixed frame rate, but this can vary. + // sending server's current deltaTime is the safest option. + // client then applies it on top of remoteTimestamp. + + + // FAST VERSION: this shows in profiler a lot, so cache EVERYTHING! + tf.GetPositionAndRotation(out Vector3 position, out Quaternion rotation); // faster than tf.position + tf.rotation. server's rigidbody is on the same transform. + writer.WriteFloat(Time.deltaTime); + writer.WriteVector3(position); + writer.WriteQuaternion(rotation); + writer.WriteVector3(predictedRigidbody.linearVelocity); + writer.WriteVector3(predictedRigidbody.angularVelocity); + } + + // read the server's state, compare with client state & correct if necessary. + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + // deserialize data + // we want to know the time on the server when this was sent, which is remoteTimestamp. + double timestamp = NetworkClient.connection.remoteTimeStamp; + + // server send state at the end of the frame. + // parse and apply the server's delta time to our timestamp. + // otherwise we see noticeable resets that seem off by one frame. + double serverDeltaTime = reader.ReadFloat(); + timestamp += serverDeltaTime; + + // however, adding yet one more frame delay gives much(!) better results. + // we don't know why yet, so keep this as an option for now. + // possibly because client captures at the beginning of the frame, + // with physics happening at the end of the frame? + if (oneFrameAhead) timestamp += serverDeltaTime; + + // parse state + Vector3 position = reader.ReadVector3(); + Quaternion rotation = reader.ReadQuaternion(); + Vector3 velocity = reader.ReadVector3(); + Vector3 angularVelocity = reader.ReadVector3(); + + // process received state + OnReceivedState(timestamp, new RigidbodyState(timestamp, Vector3.zero, position, Quaternion.identity, rotation, Vector3.zero, velocity, Vector3.zero, angularVelocity)); + } + + protected override void OnValidate() + { + base.OnValidate(); + + // force syncDirection to be ServerToClient + syncDirection = SyncDirection.ServerToClient; + + // state should be synced immediately for now. + // later when we have prediction fully dialed in, + // then we can maybe relax this a bit. + syncInterval = 0; + } + + // helper function for Physics tests to check if a Rigidbody belongs to + // a PredictedRigidbody component (either on it, or on its ghost). + public static bool IsPredicted(Rigidbody rb, out PredictedRigidbody predictedRigidbody) + { + // by default, Rigidbody is on the PredictedRigidbody GameObject + if (rb.TryGetComponent(out predictedRigidbody)) + return true; + + // it might be on a ghost while interacting + if (rb.TryGetComponent(out PredictedRigidbodyPhysicsGhost ghost)) + { + predictedRigidbody = ghost.target.GetComponent(); + return true; + } + + // otherwise the Rigidbody does not belong to any PredictedRigidbody. + predictedRigidbody = null; + return false; + } + + // helper function for Physics tests to check if a Collider (which may be in children) belongs to + // a PredictedRigidbody component (either on it, or on its ghost). + public static bool IsPredicted(Collider co, out PredictedRigidbody predictedRigidbody) + { + // by default, Collider is on the PredictedRigidbody GameObject or it's children. + predictedRigidbody = co.GetComponentInParent(); + if (predictedRigidbody != null) + return true; + + // it might be on a ghost while interacting + PredictedRigidbodyPhysicsGhost ghost = co.GetComponentInParent(); + if (ghost != null && ghost.target != null && ghost.target.TryGetComponent(out predictedRigidbody)) + return true; + + // otherwise the Rigidbody does not belong to any PredictedRigidbody. + predictedRigidbody = null; + return false; + } + } +} diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs.meta b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs.meta new file mode 100644 index 0000000..6456058 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: d38927cdc6024b9682b5fe9778b9ef99 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: + - localGhostMaterial: {fileID: 2100000, guid: 411a48b4a197d4924bec3e3809bc9320, + type: 2} + - remoteGhostMaterial: {fileID: 2100000, guid: 04f0b2088c857414393bab3b80356776, + type: 2} + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyPhysicsGhost.cs b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyPhysicsGhost.cs new file mode 100644 index 0000000..f28d49f --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyPhysicsGhost.cs @@ -0,0 +1,15 @@ +// Prediction moves out the Rigidbody & Collider into a separate object. +// this component simply points back to the owner component. +// in case Raycasts hit it and need to know the owner, etc. +using UnityEngine; + +namespace Mirror +{ + public class PredictedRigidbodyPhysicsGhost : MonoBehaviour + { + // this is performance critical, so store target's .Transform instead of + // PredictedRigidbody, this way we don't need to call the .transform getter. + [Tooltip("The predicted rigidbody owner.")] + public Transform target; + } +} diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyPhysicsGhost.cs.meta b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyPhysicsGhost.cs.meta new file mode 100644 index 0000000..e4b8787 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyPhysicsGhost.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 25593abc9bf0d44878a4ad6018204061 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyRemoteGhost.cs b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyRemoteGhost.cs new file mode 100644 index 0000000..636f397 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyRemoteGhost.cs @@ -0,0 +1 @@ +// removed 2024-02-09 diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyRemoteGhost.cs.meta b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyRemoteGhost.cs.meta new file mode 100644 index 0000000..f79f911 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbodyRemoteGhost.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 62e7e9424c7e48d69b6a3517796142a1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictionUtils.cs b/Assets/Mirror/Components/PredictedRigidbody/PredictionUtils.cs new file mode 100644 index 0000000..83c9515 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictionUtils.cs @@ -0,0 +1,419 @@ +// standalone utility functions for PredictedRigidbody component. +using System; +using UnityEngine; + +namespace Mirror +{ + public static class PredictionUtils + { + // rigidbody /////////////////////////////////////////////////////////// + // move a Rigidbody + settings from one GameObject to another. + public static void MoveRigidbody(GameObject source, GameObject destination) + { + // create a new Rigidbody component on destination. + // note that adding a Joint automatically adds a Rigidbody. + // so first check if one was added yet. + Rigidbody original = source.GetComponent(); + if (original == null) throw new Exception($"Prediction: attempted to move {source}'s Rigidbody to the predicted copy, but there was no component."); + Rigidbody rigidbodyCopy; + if (!destination.TryGetComponent(out rigidbodyCopy)) + rigidbodyCopy = destination.AddComponent(); + + // copy all properties + rigidbodyCopy.mass = original.mass; + rigidbodyCopy.linearDamping = original.linearDamping; + rigidbodyCopy.angularDamping = original.angularDamping; + rigidbodyCopy.useGravity = original.useGravity; + rigidbodyCopy.isKinematic = original.isKinematic; + rigidbodyCopy.interpolation = original.interpolation; + rigidbodyCopy.collisionDetectionMode = original.collisionDetectionMode; + rigidbodyCopy.constraints = original.constraints; + rigidbodyCopy.sleepThreshold = original.sleepThreshold; + rigidbodyCopy.freezeRotation = original.freezeRotation; + + // moving (Configurable)Joints messes up their range of motion unless + // we reset to initial position first (we do this in PredictedRigibody.cs). + // so here we don't set the Rigidbody's physics position at all. + // rigidbodyCopy.position = original.position; + // rigidbodyCopy.rotation = original.rotation; + + // projects may keep Rigidbodies as kinematic sometimes. in that case, setting velocity would log an error + if (!original.isKinematic) + { + rigidbodyCopy.linearVelocity = original.linearVelocity; + rigidbodyCopy.angularVelocity = original.angularVelocity; + } + + // destroy original + GameObject.Destroy(original); + } + + // helper function: if a collider is on a child, copy that child first. + // this way child's relative position/rotation/scale are preserved. + public static GameObject CopyRelativeTransform(GameObject source, Transform sourceChild, GameObject destination) + { + // is this on the source root? then we want to put it on the destination root. + if (sourceChild == source.transform) return destination; + + // is this on a child? then create the same child with the same transform on destination. + // note this is technically only correct for the immediate child since + // .localPosition is relative to parent, but this is good enough. + GameObject child = new GameObject(sourceChild.name); + child.transform.SetParent(destination.transform, true); + child.transform.localPosition = sourceChild.localPosition; + child.transform.localRotation = sourceChild.localRotation; + child.transform.localScale = sourceChild.localScale; + + // assign the same Layer for the physics copy. + // games may use a custom physics collision matrix, layer matters. + child.layer = sourceChild.gameObject.layer; + + return child; + } + + // colliders /////////////////////////////////////////////////////////// + // move all BoxColliders + settings from one GameObject to another. + public static void MoveBoxColliders(GameObject source, GameObject destination) + { + // colliders may be on children + BoxCollider[] sourceColliders = source.GetComponentsInChildren(); + foreach (BoxCollider sourceCollider in sourceColliders) + { + // copy the relative transform: + // if collider is on root, it returns destination root. + // if collider is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceCollider.transform, destination); + BoxCollider colliderCopy = target.AddComponent(); + colliderCopy.center = sourceCollider.center; + colliderCopy.size = sourceCollider.size; + colliderCopy.isTrigger = sourceCollider.isTrigger; + colliderCopy.material = sourceCollider.material; + GameObject.Destroy(sourceCollider); + } + } + + // move all SphereColliders + settings from one GameObject to another. + public static void MoveSphereColliders(GameObject source, GameObject destination) + { + // colliders may be on children + SphereCollider[] sourceColliders = source.GetComponentsInChildren(); + foreach (SphereCollider sourceCollider in sourceColliders) + { + // copy the relative transform: + // if collider is on root, it returns destination root. + // if collider is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceCollider.transform, destination); + SphereCollider colliderCopy = target.AddComponent(); + colliderCopy.center = sourceCollider.center; + colliderCopy.radius = sourceCollider.radius; + colliderCopy.isTrigger = sourceCollider.isTrigger; + colliderCopy.material = sourceCollider.material; + GameObject.Destroy(sourceCollider); + } + } + + // move all CapsuleColliders + settings from one GameObject to another. + public static void MoveCapsuleColliders(GameObject source, GameObject destination) + { + // colliders may be on children + CapsuleCollider[] sourceColliders = source.GetComponentsInChildren(); + foreach (CapsuleCollider sourceCollider in sourceColliders) + { + // copy the relative transform: + // if collider is on root, it returns destination root. + // if collider is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceCollider.transform, destination); + CapsuleCollider colliderCopy = target.AddComponent(); + colliderCopy.center = sourceCollider.center; + colliderCopy.radius = sourceCollider.radius; + colliderCopy.height = sourceCollider.height; + colliderCopy.direction = sourceCollider.direction; + colliderCopy.isTrigger = sourceCollider.isTrigger; + colliderCopy.material = sourceCollider.material; + GameObject.Destroy(sourceCollider); + } + } + + // move all MeshColliders + settings from one GameObject to another. + public static void MoveMeshColliders(GameObject source, GameObject destination) + { + // colliders may be on children + MeshCollider[] sourceColliders = source.GetComponentsInChildren(); + foreach (MeshCollider sourceCollider in sourceColliders) + { + // when Models have Mesh->Read/Write disabled, it means that Unity + // uploads the mesh directly to the GPU and erases it on the CPU. + // on some platforms this makes moving a MeshCollider in builds impossible: + // + // "CollisionMeshData couldn't be created because the mesh has been marked as non-accessible." + // + // on other platforms, this works fine. + // let's show an explicit log message so in case collisions don't + // work at runtime, it's obvious why it happens and how to fix it. + if (!sourceCollider.sharedMesh.isReadable) + { + Debug.Log($"[Prediction]: MeshCollider on {sourceCollider.name} isn't readable, which may indicate that the Mesh only exists on the GPU. If {sourceCollider.name} is missing collisions, then please select the model in the Project Area, and enable Mesh->Read/Write so it's also available on the CPU!"); + // don't early return. keep trying, it may work. + } + + // copy the relative transform: + // if collider is on root, it returns destination root. + // if collider is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceCollider.transform, destination); + MeshCollider colliderCopy = target.AddComponent(); + colliderCopy.sharedMesh = sourceCollider.sharedMesh; + colliderCopy.convex = sourceCollider.convex; + colliderCopy.isTrigger = sourceCollider.isTrigger; + colliderCopy.material = sourceCollider.material; + GameObject.Destroy(sourceCollider); + } + } + + // move all Colliders + settings from one GameObject to another. + public static void MoveAllColliders(GameObject source, GameObject destination) + { + MoveBoxColliders(source, destination); + MoveSphereColliders(source, destination); + MoveCapsuleColliders(source, destination); + MoveMeshColliders(source, destination); + } + + // joints ////////////////////////////////////////////////////////////// + // move all CharacterJoints + settings from one GameObject to another. + public static void MoveCharacterJoints(GameObject source, GameObject destination) + { + // colliders may be on children + CharacterJoint[] sourceJoints = source.GetComponentsInChildren(); + foreach (CharacterJoint sourceJoint in sourceJoints) + { + // copy the relative transform: + // if joint is on root, it returns destination root. + // if joint is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination); + CharacterJoint jointCopy = target.AddComponent(); + // apply settings, in alphabetical order + jointCopy.anchor = sourceJoint.anchor; + jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor; + jointCopy.axis = sourceJoint.axis; + jointCopy.breakForce = sourceJoint.breakForce; + jointCopy.breakTorque = sourceJoint.breakTorque; + jointCopy.connectedAnchor = sourceJoint.connectedAnchor; + jointCopy.connectedBody = sourceJoint.connectedBody; + jointCopy.connectedMassScale = sourceJoint.connectedMassScale; + jointCopy.enableCollision = sourceJoint.enableCollision; + jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing; + jointCopy.enableProjection = sourceJoint.enableProjection; + jointCopy.highTwistLimit = sourceJoint.highTwistLimit; + jointCopy.lowTwistLimit = sourceJoint.lowTwistLimit; + jointCopy.massScale = sourceJoint.massScale; + jointCopy.projectionAngle = sourceJoint.projectionAngle; + jointCopy.projectionDistance = sourceJoint.projectionDistance; + jointCopy.swing1Limit = sourceJoint.swing1Limit; + jointCopy.swing2Limit = sourceJoint.swing2Limit; + jointCopy.swingAxis = sourceJoint.swingAxis; + jointCopy.swingLimitSpring = sourceJoint.swingLimitSpring; + jointCopy.twistLimitSpring = sourceJoint.twistLimitSpring; +#if UNITY_2020_3_OR_NEWER + jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody; +#endif + + GameObject.Destroy(sourceJoint); + } + } + + // move all ConfigurableJoints + settings from one GameObject to another. + public static void MoveConfigurableJoints(GameObject source, GameObject destination) + { + // colliders may be on children + ConfigurableJoint[] sourceJoints = source.GetComponentsInChildren(); + foreach (ConfigurableJoint sourceJoint in sourceJoints) + { + // copy the relative transform: + // if joint is on root, it returns destination root. + // if joint is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination); + ConfigurableJoint jointCopy = target.AddComponent(); + // apply settings, in alphabetical order + jointCopy.anchor = sourceJoint.anchor; + jointCopy.angularXLimitSpring = sourceJoint.angularXLimitSpring; + jointCopy.angularXDrive = sourceJoint.angularXDrive; + jointCopy.angularXMotion = sourceJoint.angularXMotion; + jointCopy.angularYLimit = sourceJoint.angularYLimit; + jointCopy.angularYMotion = sourceJoint.angularYMotion; + jointCopy.angularYZDrive = sourceJoint.angularYZDrive; + jointCopy.angularYZLimitSpring = sourceJoint.angularYZLimitSpring; + jointCopy.angularZLimit = sourceJoint.angularZLimit; + jointCopy.angularZMotion = sourceJoint.angularZMotion; + jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor; + jointCopy.axis = sourceJoint.axis; + jointCopy.breakForce = sourceJoint.breakForce; + jointCopy.breakTorque = sourceJoint.breakTorque; + jointCopy.configuredInWorldSpace = sourceJoint.configuredInWorldSpace; + jointCopy.connectedAnchor = sourceJoint.connectedAnchor; + jointCopy.connectedBody = sourceJoint.connectedBody; + jointCopy.connectedMassScale = sourceJoint.connectedMassScale; + jointCopy.enableCollision = sourceJoint.enableCollision; + jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing; + jointCopy.highAngularXLimit = sourceJoint.highAngularXLimit; // moving this only works if the object is at initial position/rotation/scale, see PredictedRigidbody.cs + jointCopy.linearLimitSpring = sourceJoint.linearLimitSpring; + jointCopy.linearLimit = sourceJoint.linearLimit; + jointCopy.lowAngularXLimit = sourceJoint.lowAngularXLimit; // moving this only works if the object is at initial position/rotation/scale, see PredictedRigidbody.cs + jointCopy.massScale = sourceJoint.massScale; + jointCopy.projectionAngle = sourceJoint.projectionAngle; + jointCopy.projectionDistance = sourceJoint.projectionDistance; + jointCopy.projectionMode = sourceJoint.projectionMode; + jointCopy.rotationDriveMode = sourceJoint.rotationDriveMode; + jointCopy.secondaryAxis = sourceJoint.secondaryAxis; + jointCopy.slerpDrive = sourceJoint.slerpDrive; + jointCopy.swapBodies = sourceJoint.swapBodies; + jointCopy.targetAngularVelocity = sourceJoint.targetAngularVelocity; + jointCopy.targetPosition = sourceJoint.targetPosition; + jointCopy.targetRotation = sourceJoint.targetRotation; + jointCopy.targetVelocity = sourceJoint.targetVelocity; + jointCopy.xDrive = sourceJoint.xDrive; + jointCopy.xMotion = sourceJoint.xMotion; + jointCopy.yDrive = sourceJoint.yDrive; + jointCopy.yMotion = sourceJoint.yMotion; + jointCopy.zDrive = sourceJoint.zDrive; + jointCopy.zMotion = sourceJoint.zMotion; +#if UNITY_2020_3_OR_NEWER + jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody; +#endif + + GameObject.Destroy(sourceJoint); + } + } + + // move all FixedJoints + settings from one GameObject to another. + public static void MoveFixedJoints(GameObject source, GameObject destination) + { + // colliders may be on children + FixedJoint[] sourceJoints = source.GetComponentsInChildren(); + foreach (FixedJoint sourceJoint in sourceJoints) + { + // copy the relative transform: + // if joint is on root, it returns destination root. + // if joint is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination); + FixedJoint jointCopy = target.AddComponent(); + // apply settings, in alphabetical order + jointCopy.anchor = sourceJoint.anchor; + jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor; + jointCopy.axis = sourceJoint.axis; + jointCopy.breakForce = sourceJoint.breakForce; + jointCopy.breakTorque = sourceJoint.breakTorque; + jointCopy.connectedAnchor = sourceJoint.connectedAnchor; + jointCopy.connectedBody = sourceJoint.connectedBody; + jointCopy.connectedMassScale = sourceJoint.connectedMassScale; + jointCopy.enableCollision = sourceJoint.enableCollision; + jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing; + jointCopy.massScale = sourceJoint.massScale; +#if UNITY_2020_3_OR_NEWER + jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody; +#endif + + GameObject.Destroy(sourceJoint); + } + } + + // move all HingeJoints + settings from one GameObject to another. + public static void MoveHingeJoints(GameObject source, GameObject destination) + { + // colliders may be on children + HingeJoint[] sourceJoints = source.GetComponentsInChildren(); + foreach (HingeJoint sourceJoint in sourceJoints) + { + // copy the relative transform: + // if joint is on root, it returns destination root. + // if joint is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination); + HingeJoint jointCopy = target.AddComponent(); + // apply settings, in alphabetical order + jointCopy.anchor = sourceJoint.anchor; + jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor; + jointCopy.axis = sourceJoint.axis; + jointCopy.breakForce = sourceJoint.breakForce; + jointCopy.breakTorque = sourceJoint.breakTorque; + jointCopy.connectedAnchor = sourceJoint.connectedAnchor; + jointCopy.connectedBody = sourceJoint.connectedBody; + jointCopy.connectedMassScale = sourceJoint.connectedMassScale; + jointCopy.enableCollision = sourceJoint.enableCollision; + jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing; + jointCopy.limits = sourceJoint.limits; + jointCopy.massScale = sourceJoint.massScale; + jointCopy.motor = sourceJoint.motor; + jointCopy.spring = sourceJoint.spring; + jointCopy.useLimits = sourceJoint.useLimits; + jointCopy.useMotor = sourceJoint.useMotor; + jointCopy.useSpring = sourceJoint.useSpring; +#if UNITY_2020_3_OR_NEWER + jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody; +#endif +#if UNITY_2022_3_OR_NEWER + jointCopy.extendedLimits = sourceJoint.extendedLimits; + jointCopy.useAcceleration = sourceJoint.useAcceleration; +#endif + + GameObject.Destroy(sourceJoint); + } + } + + // move all SpringJoints + settings from one GameObject to another. + public static void MoveSpringJoints(GameObject source, GameObject destination) + { + // colliders may be on children + SpringJoint[] sourceJoints = source.GetComponentsInChildren(); + foreach (SpringJoint sourceJoint in sourceJoints) + { + // copy the relative transform: + // if joint is on root, it returns destination root. + // if joint is on a child, it creates and returns a child on destination. + GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination); + SpringJoint jointCopy = target.AddComponent(); + // apply settings, in alphabetical order + jointCopy.anchor = sourceJoint.anchor; + jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor; + jointCopy.axis = sourceJoint.axis; + jointCopy.breakForce = sourceJoint.breakForce; + jointCopy.breakTorque = sourceJoint.breakTorque; + jointCopy.connectedAnchor = sourceJoint.connectedAnchor; + jointCopy.connectedBody = sourceJoint.connectedBody; + jointCopy.connectedMassScale = sourceJoint.connectedMassScale; + jointCopy.damper = sourceJoint.damper; + jointCopy.enableCollision = sourceJoint.enableCollision; + jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing; + jointCopy.massScale = sourceJoint.massScale; + jointCopy.maxDistance = sourceJoint.maxDistance; + jointCopy.minDistance = sourceJoint.minDistance; + jointCopy.spring = sourceJoint.spring; + jointCopy.tolerance = sourceJoint.tolerance; +#if UNITY_2020_3_OR_NEWER + jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody; +#endif + + GameObject.Destroy(sourceJoint); + } + } + + // move all Joints + settings from one GameObject to another. + public static void MoveAllJoints(GameObject source, GameObject destination) + { + MoveCharacterJoints(source, destination); + MoveConfigurableJoints(source, destination); + MoveFixedJoints(source, destination); + MoveHingeJoints(source, destination); + MoveSpringJoints(source, destination); + } + + // all ///////////////////////////////////////////////////////////////// + // move all physics components from one GameObject to another. + public static void MovePhysicsComponents(GameObject source, GameObject destination) + { + // need to move joints first, otherwise we might see: + // 'can't move Rigidbody because a Joint depends on it' + MoveAllJoints(source, destination); + MoveAllColliders(source, destination); + MoveRigidbody(source, destination); + } + } +} diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictionUtils.cs.meta b/Assets/Mirror/Components/PredictedRigidbody/PredictionUtils.cs.meta new file mode 100644 index 0000000..52cc737 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictionUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17cfe1beb3f94a69b94bf60afc37ef7a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/PredictedRigidbody/RemoteGhostMaterial.mat b/Assets/Mirror/Components/PredictedRigidbody/RemoteGhostMaterial.mat new file mode 100644 index 0000000..d652a50 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/RemoteGhostMaterial.mat @@ -0,0 +1,85 @@ +%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: RemoteGhostMaterial + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _ALPHAPREMULTIPLY_ON + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 3000 + stringTagMap: + RenderType: Transparent + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 10 + - _GlossMapScale: 1 + - _Glossiness: 0.92 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 3 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 0 + m_Colors: + - _Color: {r: 0.09849727, g: 1, b: 0, a: 0.15686275} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] diff --git a/Assets/Mirror/Components/PredictedRigidbody/RemoteGhostMaterial.mat.meta b/Assets/Mirror/Components/PredictedRigidbody/RemoteGhostMaterial.mat.meta new file mode 100644 index 0000000..50854eb --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/RemoteGhostMaterial.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 04f0b2088c857414393bab3b80356776 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/PredictedRigidbody/RigidbodyState.cs b/Assets/Mirror/Components/PredictedRigidbody/RigidbodyState.cs new file mode 100644 index 0000000..be8eaae --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/RigidbodyState.cs @@ -0,0 +1,58 @@ +// PredictedRigidbody stores a history of its rigidbody states. +using UnityEngine; + +namespace Mirror +{ + public struct RigidbodyState : PredictedState + { + public double timestamp { get; private set; } + + // we want to store position delta (last + delta = current), and current. + // this way we can apply deltas on top of corrected positions to get the corrected final position. + public Vector3 positionDelta { get; set; } // delta to get from last to this position + public Vector3 position { get; set; } + + public Quaternion rotationDelta { get; set; } // delta to get from last to this rotation + public Quaternion rotation { get; set; } + + public Vector3 velocityDelta { get; set; } // delta to get from last to this velocity + public Vector3 velocity { get; set; } + + public Vector3 angularVelocityDelta { get; set; } // delta to get from last to this velocity + public Vector3 angularVelocity { get; set; } + + public RigidbodyState( + double timestamp, + Vector3 positionDelta, + Vector3 position, + Quaternion rotationDelta, + Quaternion rotation, + Vector3 velocityDelta, + Vector3 velocity, + Vector3 angularVelocityDelta, + Vector3 angularVelocity) + { + this.timestamp = timestamp; + this.positionDelta = positionDelta; + this.position = position; + this.rotationDelta = rotationDelta; + this.rotation = rotation; + this.velocityDelta = velocityDelta; + this.velocity = velocity; + this.angularVelocityDelta = angularVelocityDelta; + this.angularVelocity = angularVelocity; + } + + public static RigidbodyState Interpolate(RigidbodyState a, RigidbodyState b, float t) + { + return new RigidbodyState + { + position = Vector3.Lerp(a.position, b.position, t), + // Quaternions always need to be normalized in order to be a valid rotation after operations + rotation = Quaternion.Slerp(a.rotation, b.rotation, t).normalized, + velocity = Vector3.Lerp(a.velocity, b.velocity, t), + angularVelocity = Vector3.Lerp(a.angularVelocity, b.angularVelocity, t) + }; + } + } +} diff --git a/Assets/Mirror/Components/PredictedRigidbody/RigidbodyState.cs.meta b/Assets/Mirror/Components/PredictedRigidbody/RigidbodyState.cs.meta new file mode 100644 index 0000000..93affc5 --- /dev/null +++ b/Assets/Mirror/Components/PredictedRigidbody/RigidbodyState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed0e1c0c874c4c9db6be2d5885bb7bee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Components/RemoteStatistics.cs b/Assets/Mirror/Components/RemoteStatistics.cs new file mode 100644 index 0000000..aa18815 --- /dev/null +++ b/Assets/Mirror/Components/RemoteStatistics.cs @@ -0,0 +1,441 @@ +// remote statistics panel from Mirror II to show connections, load, etc. +// server syncs statistics to clients if authenticated. +// +// attach this to a player. +// requires NetworkStatistics component on the Network object. +// +// Unity's OnGUI is the easiest to use solution at the moment. +// * playfab is super complex to set up +// * http servers would be nice, but still need to open ports, live refresh, etc +// +// for safety reasons, let's keep this read-only. +// at least until there's safe authentication. +using System; +using System.IO; +using UnityEngine; + +namespace Mirror +{ + // server -> client + struct Stats + { + // general + public int connections; + public double uptime; + public int configuredTickRate; + public int actualTickRate; + + // traffic + public long sentBytesPerSecond; + public long receiveBytesPerSecond; + + // cpu + public float serverTickInterval; + public double fullUpdateAvg; + public double serverEarlyAvg; + public double serverLateAvg; + public double transportEarlyAvg; + public double transportLateAvg; + + // C# boilerplate + public Stats( + // general + int connections, + double uptime, + int configuredTickRate, + int actualTickRate, + // traffic + long sentBytesPerSecond, + long receiveBytesPerSecond, + // cpu + float serverTickInterval, + double fullUpdateAvg, + double serverEarlyAvg, + double serverLateAvg, + double transportEarlyAvg, + double transportLateAvg + ) + { + // general + this.connections = connections; + this.uptime = uptime; + this.configuredTickRate = configuredTickRate; + this.actualTickRate = actualTickRate; + + // traffic + this.sentBytesPerSecond = sentBytesPerSecond; + this.receiveBytesPerSecond = receiveBytesPerSecond; + + // cpu + this.serverTickInterval = serverTickInterval; + this.fullUpdateAvg = fullUpdateAvg; + this.serverEarlyAvg = serverEarlyAvg; + this.serverLateAvg = serverLateAvg; + this.transportEarlyAvg = transportEarlyAvg; + this.transportLateAvg = transportLateAvg; + } + } + + // [RequireComponent(typeof(NetworkStatistics))] <- needs to be on Network GO, not on NI + public class RemoteStatistics : NetworkBehaviour + { + // components ("fake statics" for similar API) + protected NetworkStatistics NetworkStatistics; + + // broadcast to client. + // stats are quite huge, let's only send every few seconds via TargetRpc. + // instead of sending multiple times per second via NB.OnSerialize. + [Tooltip("Send stats every 'interval' seconds to client.")] + public float sendInterval = 1; + double lastSendTime; + + [Header("GUI")] + public bool showGui; + public KeyCode hotKey = KeyCode.F11; + Rect windowRect = new Rect(0, 0, 400, 400); + + // password can't be stored in code or in Unity project. + // it would be available in clients otherwise. + // this is not perfectly secure. that's why RemoteStatistics is read-only. + [Header("Authentication")] + public string passwordFile = "remote_statistics.txt"; + protected bool serverAuthenticated; // client needs to authenticate + protected bool clientAuthenticated; // show GUI until authenticated + protected string serverPassword = null; // null means not found, auth impossible + protected string clientPassword = ""; // for GUI + + // statistics synced to client + Stats stats; + + void LoadPassword() + { + // TODO only load once, not for all players? + // let's avoid static state for now. + + // load the password + string path = Path.GetFullPath(passwordFile); + if (File.Exists(path)) + { + // don't spam the server logs for every player's loaded file + // Debug.Log($"RemoteStatistics: loading password file: {path}"); + try + { + serverPassword = File.ReadAllText(path); + } + catch (Exception exception) + { + Debug.LogWarning($"RemoteStatistics: failed to read password file: {exception}"); + } + } + else + { + Debug.LogWarning($"RemoteStatistics: password file has not been created. Authentication will be impossible. Please save the password in: {path}"); + } + } + + protected override void OnValidate() + { + base.OnValidate(); + syncMode = SyncMode.Owner; + } + + // make sure to call base function when overwriting! + // public so it can also be called from tests (and be overwritten by users) + public override void OnStartServer() + { + NetworkStatistics = NetworkManager.singleton.GetComponent(); + if (NetworkStatistics == null) throw new Exception($"RemoteStatistics requires a NetworkStatistics component on {NetworkManager.singleton.name}!"); + + // server needs to load the password + LoadPassword(); + } + + public override void OnStartLocalPlayer() + { + // center the window initially + windowRect.x = Screen.width / 2 - windowRect.width / 2; + windowRect.y = Screen.height / 2 - windowRect.height / 2; + } + + [TargetRpc] + void TargetRpcSync(Stats v) + { + // store stats and flag as authenticated + clientAuthenticated = true; + stats = v; + } + + [Command] + public void CmdAuthenticate(string v) + { + // was a valid password loaded on the server, + // and did the client send the correct one? + if (!string.IsNullOrWhiteSpace(serverPassword) && + serverPassword.Equals(v)) + { + serverAuthenticated = true; + Debug.Log($"RemoteStatistics: connectionId {connectionToClient.connectionId} authenticated with player {name}"); + } + } + + void UpdateServer() + { + // only sync if client has authenticated on the server + if (!serverAuthenticated) return; + + // NetworkTime.localTime has defines for 2019 / 2020 compatibility + if (NetworkTime.localTime >= lastSendTime + sendInterval) + { + lastSendTime = NetworkTime.localTime; + + // target rpc to owner client + TargetRpcSync(new Stats( + // general + NetworkServer.connections.Count, + NetworkTime.time, + NetworkServer.tickRate, + NetworkServer.actualTickRate, + + // traffic + NetworkStatistics.serverSentBytesPerSecond, + NetworkStatistics.serverReceivedBytesPerSecond, + + // cpu + NetworkServer.tickInterval, + NetworkServer.fullUpdateDuration.average, + NetworkServer.earlyUpdateDuration.average, + NetworkServer.lateUpdateDuration.average, + 0, // TODO ServerTransport.earlyUpdateDuration.average, + 0 // TODO ServerTransport.lateUpdateDuration.average + )); + } + } + + void UpdateClient() + { + if (Input.GetKeyDown(hotKey)) + showGui = !showGui; + } + + void Update() + { + if (isServer) UpdateServer(); + if (isLocalPlayer) UpdateClient(); + } + + void OnGUI() + { + if (!isLocalPlayer) return; + if (!showGui) return; + + windowRect = GUILayout.Window(0, windowRect, OnWindow, "Remote Statistics"); + windowRect = Utils.KeepInScreen(windowRect); + } + + // Text: value + void GUILayout_TextAndValue(string text, string value) + { + GUILayout.BeginHorizontal(); + GUILayout.Label(text); + GUILayout.FlexibleSpace(); + GUILayout.Label(value); + GUILayout.EndHorizontal(); + } + + // fake a progress bar via horizontal scroll bar with ratio as width + void GUILayout_ProgressBar(double ratio, int width) + { + // clamp ratio, otherwise >1 would make it extremely large + ratio = Mathd.Clamp01(ratio); + GUILayout.HorizontalScrollbar(0, (float)ratio, 0, 1, GUILayout.Width(width)); + } + + // need to specify progress bar & caption width, + // otherwise differently sized captions would always misalign the + // progress bars. + void GUILayout_TextAndProgressBar(string text, double ratio, int progressbarWidth, string caption, int captionWidth, Color captionColor) + { + GUILayout.BeginHorizontal(); + GUILayout.Label(text); + GUILayout.FlexibleSpace(); + GUILayout_ProgressBar(ratio, progressbarWidth); + + // coloring the caption is enough. otherwise it's too much. + GUI.color = captionColor; + GUILayout.Label(caption, GUILayout.Width(captionWidth)); + GUI.color = Color.white; + + GUILayout.EndHorizontal(); + } + + void GUI_Authenticate() + { + GUILayout.BeginVertical("Box"); // start general + GUILayout.Label("Authentication"); + + // warning if insecure connection + // if (ClientTransport.IsEncrypted()) + // { + // GUILayout.Label("Connection is encrypted!"); + // } + // else + // { + GUILayout.Label("Connection is not encrypted. Use with care!"); + // } + + // input + clientPassword = GUILayout.PasswordField(clientPassword, '*'); + + // button + GUI.enabled = !string.IsNullOrWhiteSpace(clientPassword); + if (GUILayout.Button("Authenticate")) + { + CmdAuthenticate(clientPassword); + } + GUI.enabled = true; + + GUILayout.EndVertical(); // end general + } + + void GUI_General( + int connections, + double uptime, + int configuredTickRate, + int actualTickRate) + { + GUILayout.BeginVertical("Box"); // start general + GUILayout.Label("General"); + + // connections + GUILayout_TextAndValue("Connections:", $"{connections}"); + + // uptime + GUILayout_TextAndValue("Uptime:", $"{Utils.PrettySeconds(uptime)}"); // TODO + + // tick rate + // might be lower under heavy load. + // might be higher in editor if targetFrameRate can't be set. + GUI.color = actualTickRate < configuredTickRate ? Color.red : Color.green; + GUILayout_TextAndValue("Tick Rate:", $"{actualTickRate} Hz / {configuredTickRate} Hz"); + GUI.color = Color.white; + + GUILayout.EndVertical(); // end general + } + + void GUI_Traffic( + long serverSentBytesPerSecond, + long serverReceivedBytesPerSecond) + { + GUILayout.BeginVertical("Box"); + GUILayout.Label("Network"); + + GUILayout_TextAndValue("Outgoing:", $"{Utils.PrettyBytes(serverSentBytesPerSecond) }/s"); + GUILayout_TextAndValue("Incoming:", $"{Utils.PrettyBytes(serverReceivedBytesPerSecond)}/s"); + + GUILayout.EndVertical(); + } + + void GUI_Cpu( + float serverTickInterval, + double fullUpdateAvg, + double serverEarlyAvg, + double serverLateAvg, + double transportEarlyAvg, + double transportLateAvg) + { + const int barWidth = 120; + const int captionWidth = 90; + + GUILayout.BeginVertical("Box"); + GUILayout.Label("CPU"); + + // unity update + // happens every 'tickInterval'. progress bar shows it in relation. + // <= 90% load is green, otherwise red + double fullRatio = fullUpdateAvg / serverTickInterval; + GUILayout_TextAndProgressBar( + "World Update Avg:", + fullRatio, + barWidth, $"{fullUpdateAvg * 1000:F1} ms", + captionWidth, + fullRatio <= 0.9 ? Color.green : Color.red); + + // server update + // happens every 'tickInterval'. progress bar shows it in relation. + // <= 90% load is green, otherwise red + double serverRatio = (serverEarlyAvg + serverLateAvg) / serverTickInterval; + GUILayout_TextAndProgressBar( + "Server Update Avg:", + serverRatio, + barWidth, $"{serverEarlyAvg * 1000:F1} + {serverLateAvg * 1000:F1} ms", + captionWidth, + serverRatio <= 0.9 ? Color.green : Color.red); + + // transport: early + late update milliseconds. + // for threaded transport, this is the thread's update time. + // happens every 'tickInterval'. progress bar shows it in relation. + // <= 90% load is green, otherwise red + // double transportRatio = (transportEarlyAvg + transportLateAvg) / serverTickInterval; + // GUILayout_TextAndProgressBar( + // "Transport Avg:", + // transportRatio, + // barWidth, + // $"{transportEarlyAvg * 1000:F1} + {transportLateAvg * 1000:F1} ms", + // captionWidth, + // transportRatio <= 0.9 ? Color.green : Color.red); + + GUILayout.EndVertical(); + } + + void GUI_Notice() + { + // for security reasons, let's keep this read-only for now. + + // single line keeps input & visuals simple + // GUILayout.BeginVertical("Box"); + // GUILayout.Label("Global Notice"); + // notice = GUILayout.TextField(notice); + // if (GUILayout.Button("Send")) + // { + // // TODO + // } + // GUILayout.EndVertical(); + } + + void OnWindow(int windowID) + { + if (!clientAuthenticated) + { + GUI_Authenticate(); + } + else + { + GUI_General( + stats.connections, + stats.uptime, + stats.configuredTickRate, + stats.actualTickRate + ); + + GUI_Traffic( + stats.sentBytesPerSecond, + stats.receiveBytesPerSecond + ); + + GUI_Cpu( + stats.serverTickInterval, + stats.fullUpdateAvg, + stats.serverEarlyAvg, + stats.serverLateAvg, + stats.transportEarlyAvg, + stats.transportLateAvg + ); + + GUI_Notice(); + } + + // dragable window in any case + GUI.DragWindow(new Rect(0, 0, 10000, 10000)); + } + } +} diff --git a/Assets/Mirror/Components/RemoteStatistics.cs.meta b/Assets/Mirror/Components/RemoteStatistics.cs.meta new file mode 100644 index 0000000..4c4d043 --- /dev/null +++ b/Assets/Mirror/Components/RemoteStatistics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ba360e4ff6b44fc6898f56322b90c6c8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core.meta b/Assets/Mirror/Core.meta new file mode 100644 index 0000000..85ee3eb --- /dev/null +++ b/Assets/Mirror/Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9f4328ccc5f724e45afe2215d275b5d5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/AssemblyInfo.cs b/Assets/Mirror/Core/AssemblyInfo.cs new file mode 100644 index 0000000..f342716 --- /dev/null +++ b/Assets/Mirror/Core/AssemblyInfo.cs @@ -0,0 +1,12 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Mirror.Tests.Common")] +[assembly: InternalsVisibleTo("Mirror.Tests")] +// need to use Unity.*.CodeGen assembly name to import Unity.CompilationPipeline +// for ILPostProcessor tests. +[assembly: InternalsVisibleTo("Unity.Mirror.Tests.CodeGen")] +[assembly: InternalsVisibleTo("Mirror.Tests.Generated")] +[assembly: InternalsVisibleTo("Mirror.Tests.Runtime")] +[assembly: InternalsVisibleTo("Mirror.Tests.Performance.Editor")] +[assembly: InternalsVisibleTo("Mirror.Tests.Performance.Runtime")] +[assembly: InternalsVisibleTo("Mirror.Editor")] diff --git a/Assets/Mirror/Core/AssemblyInfo.cs.meta b/Assets/Mirror/Core/AssemblyInfo.cs.meta new file mode 100644 index 0000000..50cc028 --- /dev/null +++ b/Assets/Mirror/Core/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e28d5f410e25b42e6a76a2ffc10e4675 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Attributes.cs b/Assets/Mirror/Core/Attributes.cs new file mode 100644 index 0000000..df8236a --- /dev/null +++ b/Assets/Mirror/Core/Attributes.cs @@ -0,0 +1,91 @@ +using System; +using UnityEngine; + +namespace Mirror +{ + /// + /// SyncVars are used to synchronize a variable from the server to all clients automatically. + /// Value must be changed on server, not directly by clients. Hook parameter allows you to define a client-side method to be invoked when the client gets an update from the server. + /// + [AttributeUsage(AttributeTargets.Field)] + public class SyncVarAttribute : PropertyAttribute + { + public string hook; + } + + /// + /// Call this from a client to run this function on the server. + /// Make sure to validate input etc. It's not possible to call this from a server. + /// + [AttributeUsage(AttributeTargets.Method)] + public class CommandAttribute : Attribute + { + public int channel = Channels.Reliable; + public bool requiresAuthority = true; + } + + /// + /// The server uses a Remote Procedure Call (RPC) to run this function on clients. + /// + [AttributeUsage(AttributeTargets.Method)] + public class ClientRpcAttribute : Attribute + { + public int channel = Channels.Reliable; + public bool includeOwner = true; + } + + /// + /// The server uses a Remote Procedure Call (RPC) to run this function on a specific client. + /// + [AttributeUsage(AttributeTargets.Method)] + public class TargetRpcAttribute : Attribute + { + public int channel = Channels.Reliable; + } + + /// + /// Prevents clients from running this method. + /// Prints a warning if a client tries to execute this method. + /// + [AttributeUsage(AttributeTargets.Method)] + public class ServerAttribute : Attribute {} + + /// + /// Prevents clients from running this method. + /// No warning is thrown. + /// + [AttributeUsage(AttributeTargets.Method)] + public class ServerCallbackAttribute : Attribute {} + + /// + /// Prevents the server from running this method. + /// Prints a warning if the server tries to execute this method. + /// + [AttributeUsage(AttributeTargets.Method)] + public class ClientAttribute : Attribute {} + + /// + /// Prevents the server from running this method. + /// No warning is printed. + /// + [AttributeUsage(AttributeTargets.Method)] + public class ClientCallbackAttribute : Attribute {} + + /// + /// Converts a string property into a Scene property in the inspector + /// + public class SceneAttribute : PropertyAttribute {} + + /// + /// Used to show private SyncList in the inspector, + /// Use instead of SerializeField for non Serializable types + /// + [AttributeUsage(AttributeTargets.Field)] + public class ShowInInspectorAttribute : Attribute {} + + /// + /// Used to make a field readonly in the inspector + /// + [AttributeUsage(AttributeTargets.Field)] + public class ReadOnlyAttribute : PropertyAttribute {} +} diff --git a/Assets/Mirror/Core/Attributes.cs.meta b/Assets/Mirror/Core/Attributes.cs.meta new file mode 100644 index 0000000..c50a489 --- /dev/null +++ b/Assets/Mirror/Core/Attributes.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c04c722ee2ffd49c8a56ab33667b10b0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Batching.meta b/Assets/Mirror/Core/Batching.meta new file mode 100644 index 0000000..bf23600 --- /dev/null +++ b/Assets/Mirror/Core/Batching.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1c38e1bebe9947f8b842a8a57aa2b71c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Batching/Batcher.cs b/Assets/Mirror/Core/Batching/Batcher.cs new file mode 100644 index 0000000..5e30f08 --- /dev/null +++ b/Assets/Mirror/Core/Batching/Batcher.cs @@ -0,0 +1,150 @@ +// batching functionality encapsulated into one class. +// -> less complexity +// -> easy to test +// +// IMPORTANT: we use THRESHOLD batching, not MAXED SIZE batching. +// see threshold comments below. +// +// includes timestamp for tick batching. +// -> allows NetworkTransform etc. to use timestamp without including it in +// every single message +using System; +using System.Collections.Generic; + +namespace Mirror +{ + public class Batcher + { + // batching threshold instead of max size. + // -> small messages are fit into threshold sized batches + // -> messages larger than threshold are single batches + // + // in other words, we fit up to 'threshold' but still allow larger ones + // for two reasons: + // 1.) data races: skipping batching for larger messages would send a + // large spawn message immediately, while others are batched and + // only flushed at the end of the frame + // 2) timestamp batching: if each batch is expected to contain a + // timestamp, then large messages have to be a batch too. otherwise + // they would not contain a timestamp + readonly int threshold; + + // TimeStamp header size. each batch has one. + public const int TimestampSize = sizeof(double); + + // Message header size. each message has one. + public static int MessageHeaderSize(int messageSize) => + Compression.VarUIntSize((ulong)messageSize); + + // maximum overhead for a single message. + // useful for the outside to calculate max message sizes. + public static int MaxMessageOverhead(int messageSize) => + TimestampSize + MessageHeaderSize(messageSize); + + // full batches ready to be sent. + // DO NOT queue NetworkMessage, it would box. + // DO NOT queue each serialization separately. + // it would allocate too many writers. + // https://github.com/vis2k/Mirror/pull/3127 + // => best to build batches on the fly. + readonly Queue batches = new Queue(); + + // current batch in progress + NetworkWriterPooled batch; + + public Batcher(int threshold) + { + this.threshold = threshold; + } + + // add a message for batching + // we allow any sized messages. + // caller needs to make sure they are within max packet size. + public void AddMessage(ArraySegment message, double timeStamp) + { + // predict the needed size, which is varint(size) + content + int headerSize = Compression.VarUIntSize((ulong)message.Count); + int neededSize = headerSize + message.Count; + + // when appending to a batch in progress, check final size. + // if it expands beyond threshold, then we should finalize it first. + // => less than or exactly threshold is fine. + // GetBatch() will finalize it. + // => see unit tests. + if (batch != null && + batch.Position + neededSize > threshold) + { + batches.Enqueue(batch); + batch = null; + } + + // initialize a new batch if necessary + if (batch == null) + { + // borrow from pool. we return it in GetBatch. + batch = NetworkWriterPool.Get(); + + // write timestamp first. + // -> double precision for accuracy over long periods of time + // -> batches are per-frame, it doesn't matter which message's + // timestamp we use. + batch.WriteDouble(timeStamp); + } + + // add serialization to current batch. even if > threshold. + // -> we do allow > threshold sized messages as single batch + // -> WriteBytes instead of WriteSegment because the latter + // would add a size header. we want to write directly. + // + // include size prefix as varint! + // -> fixes NetworkMessage serialization mismatch corrupting the + // next message in a batch. + // -> a _lot_ of time was wasted debugging corrupt batches. + // no easy way to figure out which NetworkMessage has a mismatch. + // -> this is worth everyone's sanity. + // -> varint means we prefix with 1 byte most of the time. + // -> the same issue in NetworkIdentity was why Mirror started! + Compression.CompressVarUInt(batch, (ulong)message.Count); + batch.WriteBytes(message.Array, message.Offset, message.Count); + } + + // helper function to copy a batch to writer and return it to pool + static void CopyAndReturn(NetworkWriterPooled batch, NetworkWriter writer) + { + // make sure the writer is fresh to avoid uncertain situations + if (writer.Position != 0) + throw new ArgumentException($"GetBatch needs a fresh writer!"); + + // copy to the target writer + ArraySegment segment = batch.ToArraySegment(); + writer.WriteBytes(segment.Array, segment.Offset, segment.Count); + + // return batch to pool for reuse + NetworkWriterPool.Return(batch); + } + + // get the next batch which is available for sending (if any). + // TODO safely get & return a batch instead of copying to writer? + // TODO could return pooled writer & use GetBatch in a 'using' statement! + public bool GetBatch(NetworkWriter writer) + { + // get first batch from queue (if any) + if (batches.TryDequeue(out NetworkWriterPooled first)) + { + CopyAndReturn(first, writer); + return true; + } + + // if queue was empty, we can send the batch in progress. + if (batch != null) + { + CopyAndReturn(batch, writer); + batch = null; + return true; + } + + // nothing was written + return false; + } + } +} diff --git a/Assets/Mirror/Core/Batching/Batcher.cs.meta b/Assets/Mirror/Core/Batching/Batcher.cs.meta new file mode 100644 index 0000000..a774908 --- /dev/null +++ b/Assets/Mirror/Core/Batching/Batcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0afaaa611a2142d48a07bdd03b68b2b3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Batching/Unbatcher.cs b/Assets/Mirror/Core/Batching/Unbatcher.cs new file mode 100644 index 0000000..6b2c405 --- /dev/null +++ b/Assets/Mirror/Core/Batching/Unbatcher.cs @@ -0,0 +1,129 @@ +// un-batching functionality encapsulated into one class. +// -> less complexity +// -> easy to test +// +// includes timestamp for tick batching. +// -> allows NetworkTransform etc. to use timestamp without including it in +// every single message +using System; +using System.Collections.Generic; + +namespace Mirror +{ + public class Unbatcher + { + // supporting adding multiple batches before GetNextMessage is called. + // just in case. + readonly Queue batches = new Queue(); + + public int BatchesCount => batches.Count; + + // NetworkReader is only created once, + // then pointed to the first batch. + readonly NetworkReader reader = new NetworkReader(new byte[0]); + + // timestamp that was written into the batch remotely. + // for the batch that our reader is currently pointed at. + double readerRemoteTimeStamp; + + // helper function to start reading a batch. + void StartReadingBatch(NetworkWriterPooled batch) + { + // point reader to it + reader.SetBuffer(batch.ToArraySegment()); + + // read remote timestamp (double) + // -> AddBatch quarantees that we have at least 8 bytes to read + readerRemoteTimeStamp = reader.ReadDouble(); + } + + // add a new batch. + // returns true if valid. + // returns false if not, in which case the connection should be disconnected. + public bool AddBatch(ArraySegment batch) + { + // IMPORTANT: ArraySegment is only valid until returning. we copy it! + // + // NOTE: it's not possible to create empty ArraySegments, so we + // don't need to check against that. + + // make sure we have at least 8 bytes to read for tick timestamp + if (batch.Count < Batcher.TimestampSize) + return false; + + // put into a (pooled) writer + // -> WriteBytes instead of WriteSegment because the latter + // would add a size header. we want to write directly. + // -> will be returned to pool when sending! + NetworkWriterPooled writer = NetworkWriterPool.Get(); + writer.WriteBytes(batch.Array, batch.Offset, batch.Count); + + // first batch? then point reader there + if (batches.Count == 0) + StartReadingBatch(writer); + + // add batch + batches.Enqueue(writer); + //Debug.Log($"Adding Batch {BitConverter.ToString(batch.Array, batch.Offset, batch.Count)} => batches={batches.Count} reader={reader}"); + return true; + } + + // get next message, unpacked from batch (if any) + // message ArraySegment is only valid until the next call. + // timestamp is the REMOTE time when the batch was created remotely. + public bool GetNextMessage(out ArraySegment message, out double remoteTimeStamp) + { + message = default; + remoteTimeStamp = 0; + + // do nothing if we don't have any batches. + // otherwise the below queue.Dequeue() would throw an + // InvalidOperationException if operating on empty queue. + if (batches.Count == 0) + return false; + + // was our reader pointed to anything yet? + if (reader.Capacity == 0) + return false; + + // no more data to read? + if (reader.Remaining == 0) + { + // retire the batch + NetworkWriterPooled writer = batches.Dequeue(); + NetworkWriterPool.Return(writer); + + // do we have another batch? + if (batches.Count > 0) + { + // point reader to the next batch. + // we'll return the reader below. + NetworkWriterPooled next = batches.Peek(); + StartReadingBatch(next); + } + // otherwise there's nothing more to read + else return false; + } + + // use the current batch's remote timestamp + // AFTER potentially moving to the next batch ABOVE! + remoteTimeStamp = readerRemoteTimeStamp; + + // enough data to read the size prefix? + if (reader.Remaining == 0) + return false; + + // read the size prefix as varint + // see Batcher.AddMessage comments for explanation. + int size = (int)Compression.DecompressVarUInt(reader); + + // validate size prefix, in case attackers send malicious data + if (reader.Remaining < size) + return false; + + // return the message of size + message = reader.ReadBytesSegment(size); + return true; + } + } +} diff --git a/Assets/Mirror/Core/Batching/Unbatcher.cs.meta b/Assets/Mirror/Core/Batching/Unbatcher.cs.meta new file mode 100644 index 0000000..26038b0 --- /dev/null +++ b/Assets/Mirror/Core/Batching/Unbatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 328562d71e1c45c58581b958845aa7a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/ConnectionQuality.cs b/Assets/Mirror/Core/ConnectionQuality.cs new file mode 100644 index 0000000..ee0720a --- /dev/null +++ b/Assets/Mirror/Core/ConnectionQuality.cs @@ -0,0 +1,74 @@ +// standalone, Unity-independent connection-quality algorithm & enum. +// don't need to use this directly, it's built into Mirror's NetworkClient. +using UnityEngine; + +namespace Mirror +{ + public enum ConnectionQuality : byte + { + ESTIMATING, // still estimating + POOR, // unplayable + FAIR, // very noticeable latency, not very enjoyable anymore + GOOD, // very playable for everyone but high level competitors + EXCELLENT // ideal experience for high level competitors + } + + public enum ConnectionQualityMethod : byte + { + Simple, // simple estimation based on rtt and jitter + Pragmatic // based on snapshot interpolation adjustment + } + + // provide different heuristics for users to choose from. + // simple heuristics to get started. + // this will be iterated on over time based on user feedback. + public static class ConnectionQualityHeuristics + { + // convenience extension to color code Connection Quality + public static Color ColorCode(this ConnectionQuality quality) + { + switch (quality) + { + case ConnectionQuality.POOR: return Color.red; + case ConnectionQuality.FAIR: return new Color(1.0f, 0.647f, 0.0f); + case ConnectionQuality.GOOD: return Color.yellow; + case ConnectionQuality.EXCELLENT: return Color.green; + default: return Color.gray; // ESTIMATING + } + } + + // straight forward estimation + // rtt: average round trip time in seconds. + // jitter: average latency variance. + public static ConnectionQuality Simple(double rtt, double jitter) + { + if (rtt <= 0.100 && jitter <= 0.10) return ConnectionQuality.EXCELLENT; + if (rtt <= 0.200 && jitter <= 0.20) return ConnectionQuality.GOOD; + if (rtt <= 0.400 && jitter <= 0.50) return ConnectionQuality.FAIR; + return ConnectionQuality.POOR; + } + + // snapshot interpolation based estimation. + // snap. interp. adjusts buffer time based on connection quality. + // based on this, we can measure how far away we are from the ideal. + // the returned quality will always directly correlate with gameplay. + // => requires SnapshotInterpolation dynamicAdjustment to be enabled! + public static ConnectionQuality Pragmatic(double targetBufferTime, double currentBufferTime) + { + // buffer time is set by the game developer. + // estimating in multiples is a great way to be game independent. + // for example, a fast paced shooter and a slow paced RTS will both + // have poor connection if the multiplier is >10. + double multiplier = currentBufferTime / targetBufferTime; + + // empirically measured with Tanks demo + LatencySimulation. + // it's not obvious to estimate on paper. + if (multiplier <= 1.15) return ConnectionQuality.EXCELLENT; + if (multiplier <= 1.25) return ConnectionQuality.GOOD; + if (multiplier <= 1.50) return ConnectionQuality.FAIR; + + // anything else is poor + return ConnectionQuality.POOR; + } + } +} diff --git a/Assets/Mirror/Core/ConnectionQuality.cs.meta b/Assets/Mirror/Core/ConnectionQuality.cs.meta new file mode 100644 index 0000000..1712ffe --- /dev/null +++ b/Assets/Mirror/Core/ConnectionQuality.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ff663b880e33e4606b545c8b497041c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/HostMode.cs b/Assets/Mirror/Core/HostMode.cs new file mode 100644 index 0000000..3054b3c --- /dev/null +++ b/Assets/Mirror/Core/HostMode.cs @@ -0,0 +1,44 @@ +// host mode related helper functions. +// usually they set up both server & client. +// it's cleaner to keep them in one place, instead of only in server / client. +using System; + +namespace Mirror +{ + public static class HostMode + { + // keep the local connections setup in one function. + // makes host setup easier to follow. + internal static void SetupConnections() + { + // create local connections pair, both are connected + Utils.CreateLocalConnections( + out LocalConnectionToClient connectionToClient, + out LocalConnectionToServer connectionToServer); + + // set client connection + NetworkClient.connection = connectionToServer; + + // set server connection + NetworkServer.SetLocalConnection(connectionToClient); + } + + // call OnConnected on server & client. + // public because NetworkClient.ConnectLocalServer was public before too. + public static void InvokeOnConnected() + { + // call server OnConnected with server's connection to client + NetworkServer.OnConnected(NetworkServer.localConnection); + + // call client OnConnected with client's connection to server + // => previously we used to send a ConnectMessage to + // NetworkServer.localConnection. this would queue the message + // until NetworkClient.Update processes it. + // => invoking the client's OnConnected event directly here makes + // tests fail. so let's do it exactly the same order as before by + // queueing the event for next Update! + //OnConnectedEvent?.Invoke(connection); + ((LocalConnectionToServer)NetworkClient.connection).QueueConnectedEvent(); + } + } +} diff --git a/Assets/Mirror/Core/HostMode.cs.meta b/Assets/Mirror/Core/HostMode.cs.meta new file mode 100644 index 0000000..bf6faed --- /dev/null +++ b/Assets/Mirror/Core/HostMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d27175a08d5341fc97645b49ee533d5a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/InterestManagement.cs b/Assets/Mirror/Core/InterestManagement.cs new file mode 100644 index 0000000..88ead0f --- /dev/null +++ b/Assets/Mirror/Core/InterestManagement.cs @@ -0,0 +1,146 @@ +// interest management component for custom solutions like +// distance based, spatial hashing, raycast based, etc. + +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + [DisallowMultipleComponent] + [HelpURL("https://mirror-networking.gitbook.io/docs/guides/interest-management")] + public abstract class InterestManagement : InterestManagementBase + { + // allocate newObservers helper HashSet + readonly HashSet newObservers = + new HashSet(); + + // rebuild observers for the given NetworkIdentity. + // Server will automatically spawn/despawn added/removed ones. + // newObservers: cached hashset to put the result into + // initialize: true if being rebuilt for the first time + // + // IMPORTANT: + // => global rebuild would be more simple, BUT + // => local rebuild is way faster for spawn/despawn because we can + // simply rebuild a select NetworkIdentity only + // => having both .observers and .observing is necessary for local + // rebuilds + // + // in other words, this is the perfect solution even though it's not + // completely simple (due to .observers & .observing). + // + // Mirror maintains .observing automatically in the background. best of + // both worlds without any worrying now! + public abstract void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers); + + // helper function to trigger a full rebuild. + // most implementations should call this in a certain interval. + // some might call this all the time, or only on team changes or + // scene changes and so on. + // + // IMPORTANT: check if NetworkServer.active when using Update()! + [ServerCallback] + protected void RebuildAll() + { + foreach (NetworkIdentity identity in NetworkServer.spawned.Values) + { + NetworkServer.RebuildObservers(identity, false); + } + } + + public override void Rebuild(NetworkIdentity identity, bool initialize) + { + // clear newObservers hashset before using it + newObservers.Clear(); + + // not force hidden? + if (identity.visibility != Visibility.ForceHidden) + { + OnRebuildObservers(identity, newObservers); + } + + // IMPORTANT: AFTER rebuilding add own player connection in any case + // to ensure player always sees himself no matter what. + // -> OnRebuildObservers might clear observers, so we need to add + // the player's own connection AFTER. 100% fail safe. + // -> fixes https://github.com/vis2k/Mirror/issues/692 where a + // player might teleport out of the ProximityChecker's cast, + // losing the own connection as observer. + if (identity.connectionToClient != null) + { + newObservers.Add(identity.connectionToClient); + } + + bool changed = false; + + // add all newObservers that aren't in .observers yet + foreach (NetworkConnectionToClient conn in newObservers) + { + // only add ready connections. + // otherwise the player might not be in the world yet or anymore + if (conn != null && conn.isReady) + { + if (initialize || !identity.observers.ContainsKey(conn.connectionId)) + { + // new observer + conn.AddToObserving(identity); + // Debug.Log($"New Observer for {gameObject} {conn}"); + changed = true; + } + } + } + + // remove all old .observers that aren't in newObservers anymore + foreach (NetworkConnectionToClient conn in identity.observers.Values) + { + if (!newObservers.Contains(conn)) + { + // removed observer + conn.RemoveFromObserving(identity, false); + // Debug.Log($"Removed Observer for {gameObject} {conn}"); + changed = true; + } + } + + // copy new observers to observers + if (changed) + { + identity.observers.Clear(); + foreach (NetworkConnectionToClient conn in newObservers) + { + if (conn != null && conn.isReady) + identity.observers.Add(conn.connectionId, conn); + } + } + + // special case for host mode: we use SetHostVisibility to hide + // NetworkIdentities that aren't in observer range from host. + // this is what games like Dota/Counter-Strike do too, where a host + // does NOT see all players by default. they are in memory, but + // hidden to the host player. + // + // this code is from UNET, it's a bit strange but it works: + // * it hides newly connected identities in host mode + // => that part was the intended behaviour + // * it hides ALL NetworkIdentities in host mode when the host + // connects but hasn't selected a character yet + // => this only works because we have no .localConnection != null + // check. at this stage, localConnection is null because + // StartHost starts the server first, then calls this code, + // then starts the client and sets .localConnection. so we can + // NOT add a null check without breaking host visibility here. + // * it hides ALL NetworkIdentities in server-only mode because + // observers never contain the 'null' .localConnection + // => that was not intended, but let's keep it as it is so we + // don't break anything in host mode. it's way easier than + // iterating all identities in a special function in StartHost. + if (initialize) + { + if (!newObservers.Contains(NetworkServer.localConnection)) + { + SetHostVisibility(identity, false); + } + } + } + } +} diff --git a/Assets/Mirror/Core/InterestManagement.cs.meta b/Assets/Mirror/Core/InterestManagement.cs.meta new file mode 100644 index 0000000..bfabf6b --- /dev/null +++ b/Assets/Mirror/Core/InterestManagement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41d809934003479f97e992eebb7ed6af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/InterestManagementBase.cs b/Assets/Mirror/Core/InterestManagementBase.cs new file mode 100644 index 0000000..ec60d64 --- /dev/null +++ b/Assets/Mirror/Core/InterestManagementBase.cs @@ -0,0 +1,77 @@ +// interest management component for custom solutions like +// distance based, spatial hashing, raycast based, etc. +// low level base class allows for low level spatial hashing etc., which is 3-5x faster. +using UnityEngine; + +namespace Mirror +{ + [DisallowMultipleComponent] + [HelpURL("https://mirror-networking.gitbook.io/docs/guides/interest-management")] + public abstract class InterestManagementBase : MonoBehaviour + { + // initialize NetworkServer/Client .aoi. + // previously we did this in Awake(), but that's called for disabled + // components too. if we do it OnEnable(), then it's not set for + // disabled components. + protected virtual void OnEnable() + { + // do not check if == null or error if already set. + // users may enabled/disable components randomly, + // causing this to be called multiple times. + NetworkServer.aoi = this; + NetworkClient.aoi = this; + } + + [ServerCallback] + public virtual void ResetState() {} + + // Callback used by the visibility system to determine if an observer + // (player) can see the NetworkIdentity. If this function returns true, + // the network connection will be added as an observer. + // conn: Network connection of a player. + // returns True if the player can see this object. + public abstract bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver); + + + // Callback used by the visibility system for objects on a host. + // Objects on a host (with a local client) cannot be disabled or + // destroyed when they are not visible to the local client. So this + // function is called to allow custom code to hide these objects. A + // typical implementation will disable renderer components on the + // object. This is only called on local clients on a host. + // => need the function in here and virtual so people can overwrite! + // => not everyone wants to hide renderers! + [ServerCallback] + public virtual void SetHostVisibility(NetworkIdentity identity, bool visible) + { + foreach (Renderer rend in identity.GetComponentsInChildren()) + rend.enabled = visible; + } + + /// Called on the server when a new networked object is spawned. + // (useful for 'only rebuild if changed' interest management algorithms) + [ServerCallback] + public virtual void OnSpawned(NetworkIdentity identity) {} + + /// Called on the server when a networked object is destroyed. + // (useful for 'only rebuild if changed' interest management algorithms) + [ServerCallback] + public virtual void OnDestroyed(NetworkIdentity identity) {} + + public abstract void Rebuild(NetworkIdentity identity, bool initialize); + + /// Adds the specified connection to the observers of identity + protected void AddObserver(NetworkConnectionToClient connection, NetworkIdentity identity) + { + connection.AddToObserving(identity); + identity.observers.Add(connection.connectionId, connection); + } + + /// Removes the specified connection from the observers of identity + protected void RemoveObserver(NetworkConnectionToClient connection, NetworkIdentity identity) + { + connection.RemoveFromObserving(identity, false); + identity.observers.Remove(connection.connectionId); + } + } +} diff --git a/Assets/Mirror/Core/InterestManagementBase.cs.meta b/Assets/Mirror/Core/InterestManagementBase.cs.meta new file mode 100644 index 0000000..b2b5ad6 --- /dev/null +++ b/Assets/Mirror/Core/InterestManagementBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18bd2ffe65a444f3b13d59bdac7f2228 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/LagCompensation.meta b/Assets/Mirror/Core/LagCompensation.meta new file mode 100644 index 0000000..b5583ef --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d2656015ded44e83a24f4c4776bafd40 +timeCreated: 1687920405 \ No newline at end of file diff --git a/Assets/Mirror/Core/LagCompensation/Capture.cs b/Assets/Mirror/Core/LagCompensation/Capture.cs new file mode 100644 index 0000000..e4fdabe --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/Capture.cs @@ -0,0 +1,13 @@ +namespace Mirror +{ + public interface Capture + { + // server timestamp at time of capture. + double timestamp { get; set; } + + // optional gizmo drawing for visual debugging. + // history is only known on the server, which usually doesn't render. + // showing Gizmos in the Editor is enough. + void DrawGizmo(); + } +} diff --git a/Assets/Mirror/Core/LagCompensation/Capture.cs.meta b/Assets/Mirror/Core/LagCompensation/Capture.cs.meta new file mode 100644 index 0000000..d78c49f --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/Capture.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 347e831952e943a49095cadd39a5aeb2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs b/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs new file mode 100644 index 0000000..29ebc2e --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs @@ -0,0 +1,139 @@ +// HistoryBounds keeps a bounding box of all the object's bounds in the past N seconds. +// useful to decide which objects to rollback, instead of rolling back all of them. +// https://www.youtube.com/watch?v=zrIY0eIyqmI (37:00) +// standalone C# implementation to be engine (and language) agnostic. + +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + // FakeByte: gather bounds in smaller buckets. + // for example, bucket(t0,t1,t2), bucket(t3,t4,t5), ... + // instead of removing old bounds t0, t1, ... + // we remove a whole bucket every 3 times: bucket(t0,t1,t2) + // and when building total bounds, we encapsulate a few larger buckets + // instead of many smaller bounds. + // + // => a bucket is encapsulate(bounds0, bounds1, bounds2) so we don't + // need a custom struct, simply reuse bounds but remember that each + // entry includes N timestamps. + // + // => note that simply reducing capture interval is _not_ the same. + // we want to capture in detail in case players run in zig-zag. + // but still grow larger buckets internally. + public class HistoryBounds + { + // mischa: use MinMaxBounds to avoid Unity Bounds.Encapsulate conversions. + readonly int boundsPerBucket; + readonly Queue fullBuckets; + + // full bucket limit. older ones will be removed. + readonly int bucketLimit; + + // bucket in progress, contains 0..boundsPerBucket bounds encapsulated. + MinMaxBounds? currentBucket; + int currentBucketSize; + + // amount of total bounds, including bounds in full buckets + current + public int boundsCount { get; private set; } + + // total bounds encapsulating all of the bounds history. + // totalMinMax is used for internal calculations. + // public total is used for Unity representation. + MinMaxBounds totalMinMax; + public Bounds total + { + get + { + Bounds bounds = new Bounds(); + bounds.SetMinMax(totalMinMax.min, totalMinMax.max); + return bounds; + } + } + + public HistoryBounds(int boundsLimit, int boundsPerBucket) + { + // bucketLimit via '/' cuts off remainder. + // that's what we want, since we always have a 'currentBucket'. + this.boundsPerBucket = boundsPerBucket; + this.bucketLimit = (boundsLimit / boundsPerBucket); + + // initialize queue with maximum capacity to avoid runtime resizing + // capacity +1 because it makes the code easier if we insert first, and then remove. + fullBuckets = new Queue(bucketLimit + 1); + } + + // insert new bounds into history. calculates new total bounds. + // Queue.Dequeue() always has the oldest bounds. + public void Insert(Bounds bounds) + { + // convert to MinMax representation for faster .Encapsulate() + MinMaxBounds minmax = new MinMaxBounds + { + min = bounds.min, + max = bounds.max + }; + + // initialize 'total' if not initialized yet. + // we don't want to call (0,0).Encapsulate(bounds). + if (boundsCount == 0) + { + totalMinMax = minmax; + } + + // add to current bucket: + // either initialize new one, or encapsulate into existing one + if (currentBucket == null) + { + currentBucket = minmax; + } + else + { + currentBucket.Value.Encapsulate(minmax); + } + + // current bucket has one more bounds. + // total bounds increased as well. + currentBucketSize += 1; + boundsCount += 1; + + // always encapsulate into total immediately. + // this is free. + totalMinMax.Encapsulate(minmax); + + // current bucket full? + if (currentBucketSize == boundsPerBucket) + { + // move it to full buckets + fullBuckets.Enqueue(currentBucket.Value); + currentBucket = null; + currentBucketSize = 0; + + // full bucket capacity reached? + if (fullBuckets.Count > bucketLimit) + { + // remove oldest bucket + fullBuckets.Dequeue(); + boundsCount -= boundsPerBucket; + + // recompute total bounds + // instead of iterating N buckets, we iterate N / boundsPerBucket buckets. + // TODO technically we could reuse 'currentBucket' before clearing instead of encapsulating again + totalMinMax = minmax; + foreach (MinMaxBounds bucket in fullBuckets) + totalMinMax.Encapsulate(bucket); + } + } + } + + public void Reset() + { + fullBuckets.Clear(); + currentBucket = null; + currentBucketSize = 0; + boundsCount = 0; + totalMinMax = new MinMaxBounds(); + } + } +} diff --git a/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs.meta b/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs.meta new file mode 100644 index 0000000..5f908b0 --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ca9ea58b98a34f73801b162cd5de724e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/LagCompensation/LagCompensation.cs b/Assets/Mirror/Core/LagCompensation/LagCompensation.cs new file mode 100644 index 0000000..ae37a3f --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/LagCompensation.cs @@ -0,0 +1,144 @@ +// standalone lag compensation algorithm +// based on the Valve Networking Model: +// https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking +using System.Collections.Generic; + +namespace Mirror +{ + public static class LagCompensation + { + // history is of . + // Queue allows for fast 'remove first' and 'append last'. + // + // make sure to always insert in order. + // inserting out of order like [1,2,4,3] would cause issues. + // can't safeguard this because Queue doesn't have .Last access. + public static void Insert( + Queue> history, + int historyLimit, + double timestamp, + T capture) + where T : Capture + { + // make space according to history limit. + // do this before inserting, to avoid resizing past capacity. + if (history.Count >= historyLimit) + history.Dequeue(); + + // insert + history.Enqueue(new KeyValuePair(timestamp, capture)); + } + + // get the two snapshots closest to a given timestamp. + // those can be used to interpolate the exact snapshot at that time. + // if timestamp is newer than the newest history entry, then we extrapolate. + // 't' will be between 1 and 2, before is second last, after is last. + // callers should Lerp(before, after, t=1.5) to extrapolate the hit. + // see comments below for extrapolation. + public static bool Sample( + Queue> history, + double timestamp, // current server time + double interval, // capture interval + out T before, + out T after, + out double t) // interpolation factor + where T : Capture + { + before = default; + after = default; + t = 0; + + // can't sample an empty history + // interpolation needs at least one entry. + // extrapolation needs at least two entries. + // can't Lerp(A, A, 1.5). dist(A, A) * 1.5 is always 0. + if(history.Count < 2) { + return false; + } + + // older than oldest + if (timestamp < history.Peek().Key) { + return false; + } + + // iterate through the history + // TODO faster version: guess start index by how many 'intervals' we are behind. + // search around that area. + // should be O(1) most of the time, unless sampling was off. + KeyValuePair prev = new KeyValuePair(); + KeyValuePair prevPrev = new KeyValuePair(); + foreach(KeyValuePair entry in history) { + // exact match? + if (timestamp == entry.Key) { + before = entry.Value; + after = entry.Value; + t = Mathd.InverseLerp(before.timestamp, after.timestamp, timestamp); + return true; + } + + // did we check beyond timestamp? then return the previous two. + if (entry.Key > timestamp) { + before = prev.Value; + after = entry.Value; + t = Mathd.InverseLerp(before.timestamp, after.timestamp, timestamp); + return true; + } + + // remember the last two for extrapolation. + // Queue doesn't have access to .Last. + prevPrev = prev; + prev = entry; + } + + // newer than newest: extrapolate up to one interval. + // let's say we capture every 100 ms: + // 100, 200, 300, 400 + // and the server is at 499 + // if a client sends CmdFire at time 480, then there's no history entry. + // => adding the current entry every time would be too expensive. + // worst case we would capture at 401, 402, 403, 404, ... 100 times + // => not extrapolating isn't great. low latency clients would be + // punished by missing their targets since no entry at 'time' was found. + // => extrapolation is the best solution. make sure this works as + // expected and within limits. + if (prev.Key < timestamp && timestamp <= prev.Key + interval) { + // return the last two valid snapshots. + // can't just return (after, after) because we can't extrapolate + // if their distance is 0. + before = prevPrev.Value; + after = prev.Value; + + // InverseLerp will give [after, after+interval]. + // but we return [before, after, t]. + // so add +1 for the distance from before->after + t = 1 + Mathd.InverseLerp(after.timestamp, after.timestamp + interval, timestamp); + return true; + } + + return false; + } + + // never trust the client. + // we estimate when a message was sent. + // don't trust the client to tell us the time. + // https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking + // Command Execution Time = Current Server Time - Packet Latency - Client View Interpolation + // => lag compensation demo estimation is off by only ~6ms + public static double EstimateTime(double serverTime, double rtt, double bufferTime) + { + // packet latency is one trip from client to server, so rtt / 2 + // client view interpolation is the snapshot interpolation buffer time + double latency = rtt / 2; + return serverTime - latency - bufferTime; + } + + // convenience function to draw all history gizmos. + // this should be called from OnDrawGizmos. + public static void DrawGizmos(Queue> history) + where T : Capture + { + foreach (KeyValuePair entry in history) + entry.Value.DrawGizmo(); + } + } +} diff --git a/Assets/Mirror/Core/LagCompensation/LagCompensation.cs.meta b/Assets/Mirror/Core/LagCompensation/LagCompensation.cs.meta new file mode 100644 index 0000000..452ab21 --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/LagCompensation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ad53cc7d12144d0ba3a8b0a4515e5d17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/LagCompensation/LagCompensationSettings.cs b/Assets/Mirror/Core/LagCompensation/LagCompensationSettings.cs new file mode 100644 index 0000000..a7ec944 --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/LagCompensationSettings.cs @@ -0,0 +1,19 @@ +// snapshot interpolation settings struct. +// can easily be exposed in Unity inspectors. +using System; +using UnityEngine; + +namespace Mirror +{ + // class so we can define defaults easily + [Serializable] + public class LagCompensationSettings + { + [Header("Buffering")] + [Tooltip("Keep this many past snapshots in the buffer. The larger this is, the further we can rewind into the past.\nMaximum rewind time := historyAmount * captureInterval")] + public int historyLimit = 6; + + [Tooltip("Capture state every 'captureInterval' seconds. Larger values will space out the captures more, which gives a longer history but with possible gaps inbetween.\nSmaller values will have fewer gaps, with shorter history.")] + public float captureInterval = 0.100f; // 100 ms + } +} diff --git a/Assets/Mirror/Core/LagCompensation/LagCompensationSettings.cs.meta b/Assets/Mirror/Core/LagCompensation/LagCompensationSettings.cs.meta new file mode 100644 index 0000000..4f43a07 --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/LagCompensationSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa80bec245f94bf8a28ec78777992a1c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/LagCompensation/MinMaxBounds.cs b/Assets/Mirror/Core/LagCompensation/MinMaxBounds.cs new file mode 100644 index 0000000..b1b4874 --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/MinMaxBounds.cs @@ -0,0 +1,73 @@ +// Unity's Bounds struct is represented as (center, extents). +// HistoryBounds make heavy use of .Encapsulate(), which has to convert +// Unity's (center, extents) to (min, max) every time, and then convert back. +// +// It's faster to use a (min, max) representation directly instead. +using System; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Mirror +{ + public struct MinMaxBounds: IEquatable + { + public Vector3 min; + public Vector3 max; + + // encapsulate a single point + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Encapsulate(Vector3 point) + { + min = Vector3.Min(this.min, point); + max = Vector3.Max(this.max, point); + } + + // encapsulate another bounds + public void Encapsulate(MinMaxBounds bounds) + { + Encapsulate(bounds.min); + Encapsulate(bounds.max); + } + + // convenience comparison with Unity's bounds, for unit tests etc. + public static bool operator ==(MinMaxBounds lhs, Bounds rhs) => + lhs.min == rhs.min && + lhs.max == rhs.max; + + public static bool operator !=(MinMaxBounds lhs, Bounds rhs) => + !(lhs == rhs); + + public override bool Equals(object obj) => + obj is MinMaxBounds other && + min == other.min && + max == other.max; + + public bool Equals(MinMaxBounds other) => + min.Equals(other.min) && max.Equals(other.max); + + public bool Equals(Bounds other) => + min.Equals(other.min) && max.Equals(other.max); + +#if UNITY_2021_3_OR_NEWER + // Unity 2019/2020 don't have HashCode.Combine yet. + // this is only to avoid reflection. without defining, it works too. + // default generated by rider + public override int GetHashCode() => HashCode.Combine(min, max); +#else + public override int GetHashCode() + { + // return HashCode.Combine(min, max); without using .Combine for older Unity versions + unchecked + { + int hash = 17; + hash = hash * 23 + min.GetHashCode(); + hash = hash * 23 + max.GetHashCode(); + return hash; + } + } +#endif + + // tostring + public override string ToString() => $"({min}, {max})"; + } +} diff --git a/Assets/Mirror/Core/LagCompensation/MinMaxBounds.cs.meta b/Assets/Mirror/Core/LagCompensation/MinMaxBounds.cs.meta new file mode 100644 index 0000000..3eeb073 --- /dev/null +++ b/Assets/Mirror/Core/LagCompensation/MinMaxBounds.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4372b1e1a1cc4c669cc7bf0925f59d29 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/LocalConnectionToClient.cs b/Assets/Mirror/Core/LocalConnectionToClient.cs new file mode 100644 index 0000000..c41c6ae --- /dev/null +++ b/Assets/Mirror/Core/LocalConnectionToClient.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; + +namespace Mirror +{ + // a server's connection TO a LocalClient. + // sending messages on this connection causes the client's handler function to be invoked directly + public class LocalConnectionToClient : NetworkConnectionToClient + { + internal LocalConnectionToServer connectionToServer; + + // packet queue + internal readonly Queue queue = new Queue(); + + public LocalConnectionToClient() : base(LocalConnectionId) {} + + public override string address => "localhost"; + + internal override void Send(ArraySegment segment, int channelId = Channels.Reliable) + { + // instead of invoking it directly, we enqueue and process next update. + // this way we can simulate a similar call flow as with remote clients. + // the closer we get to simulating host as remote, the better! + // both directions do this, so [Command] and [Rpc] behave the same way. + + //Debug.Log($"Enqueue {BitConverter.ToString(segment.Array, segment.Offset, segment.Count)}"); + NetworkWriterPooled writer = NetworkWriterPool.Get(); + writer.WriteBytes(segment.Array, segment.Offset, segment.Count); + connectionToServer.queue.Enqueue(writer); + } + + // true because local connections never timeout + internal override bool IsAlive(float timeout) => true; + + // don't ping host client in host mode + protected override void UpdatePing() {} + + internal override void Update() + { + base.Update(); + + // process internal messages so they are applied at the correct time + while (queue.Count > 0) + { + // call receive on queued writer's content, return to pool + NetworkWriterPooled writer = queue.Dequeue(); + ArraySegment message = writer.ToArraySegment(); + + // OnTransportData assumes a proper batch with timestamp etc. + // let's make a proper batch and pass it to OnTransportData. + Batcher batcher = GetBatchForChannelId(Channels.Reliable); + batcher.AddMessage(message, NetworkTime.localTime); + + using (NetworkWriterPooled batchWriter = NetworkWriterPool.Get()) + { + // make a batch with our local time (double precision) + if (batcher.GetBatch(batchWriter)) + { + NetworkServer.OnTransportData(connectionId, batchWriter.ToArraySegment(), Channels.Reliable); + } + } + + NetworkWriterPool.Return(writer); + } + } + + internal void DisconnectInternal() + { + // set not ready and handle clientscene disconnect in any case + // (might be client or host mode here) + isReady = false; + RemoveFromObservingsObservers(); + } + + /// Disconnects this connection. + public override void Disconnect() + { + DisconnectInternal(); + connectionToServer.DisconnectInternal(); + } + } +} diff --git a/Assets/Mirror/Core/LocalConnectionToClient.cs.meta b/Assets/Mirror/Core/LocalConnectionToClient.cs.meta new file mode 100644 index 0000000..a4f2d2c --- /dev/null +++ b/Assets/Mirror/Core/LocalConnectionToClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a88758df7db2043d6a9d926e0b6d4191 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/LocalConnectionToServer.cs b/Assets/Mirror/Core/LocalConnectionToServer.cs new file mode 100644 index 0000000..15669c7 --- /dev/null +++ b/Assets/Mirror/Core/LocalConnectionToServer.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + // a localClient's connection TO a server. + // send messages on this connection causes the server's handler function to be invoked directly. + public class LocalConnectionToServer : NetworkConnectionToServer + { + internal LocalConnectionToClient connectionToClient; + + // packet queue + internal readonly Queue queue = new Queue(); + + // see caller for comments on why we need this + bool connectedEventPending; + bool disconnectedEventPending; + internal void QueueConnectedEvent() => connectedEventPending = true; + internal void QueueDisconnectedEvent() => disconnectedEventPending = true; + + // Send stage two: serialized NetworkMessage as ArraySegment + internal override void Send(ArraySegment segment, int channelId = Channels.Reliable) + { + if (segment.Count == 0) + { + Debug.LogError("LocalConnection.SendBytes cannot send zero bytes"); + return; + } + + // instead of invoking it directly, we enqueue and process next update. + // this way we can simulate a similar call flow as with remote clients. + // the closer we get to simulating host as remote, the better! + // both directions do this, so [Command] and [Rpc] behave the same way. + + //Debug.Log($"Enqueue {BitConverter.ToString(segment.Array, segment.Offset, segment.Count)}"); + NetworkWriterPooled writer = NetworkWriterPool.Get(); + writer.WriteBytes(segment.Array, segment.Offset, segment.Count); + connectionToClient.queue.Enqueue(writer); + } + + internal override void Update() + { + base.Update(); + + // should we still process a connected event? + if (connectedEventPending) + { + connectedEventPending = false; + NetworkClient.OnConnectedEvent?.Invoke(); + } + + // process internal messages so they are applied at the correct time + while (queue.Count > 0) + { + // call receive on queued writer's content, return to pool + NetworkWriterPooled writer = queue.Dequeue(); + ArraySegment message = writer.ToArraySegment(); + + // OnTransportData assumes a proper batch with timestamp etc. + // let's make a proper batch and pass it to OnTransportData. + Batcher batcher = GetBatchForChannelId(Channels.Reliable); + batcher.AddMessage(message, NetworkTime.localTime); + + using (NetworkWriterPooled batchWriter = NetworkWriterPool.Get()) + { + // make a batch with our local time (double precision) + if (batcher.GetBatch(batchWriter)) + { + NetworkClient.OnTransportData(batchWriter.ToArraySegment(), Channels.Reliable); + } + } + + NetworkWriterPool.Return(writer); + } + + // should we still process a disconnected event? + if (disconnectedEventPending) + { + disconnectedEventPending = false; + NetworkClient.OnDisconnectedEvent?.Invoke(); + } + } + + /// Disconnects this connection. + internal void DisconnectInternal() + { + // set not ready and handle clientscene disconnect in any case + // (might be client or host mode here) + // TODO remove redundant state. have one source of truth for .ready! + isReady = false; + NetworkClient.ready = false; + } + + /// Disconnects this connection. + public override void Disconnect() + { + connectionToClient.DisconnectInternal(); + DisconnectInternal(); + + // simulate what a true remote connection would do: + // first, the server should remove it: + // TODO should probably be in connectionToClient.DisconnectInternal + // because that's the NetworkServer's connection! + NetworkServer.RemoveLocalConnection(); + + // then call OnTransportDisconnected for proper disconnect handling, + // callbacks & cleanups. + // => otherwise OnClientDisconnected() is never called! + // => see NetworkClientTests.DisconnectCallsOnClientDisconnect_HostMode() + NetworkClient.OnTransportDisconnected(); + } + + // true because local connections never timeout + internal override bool IsAlive(float timeout) => true; + } +} diff --git a/Assets/Mirror/Core/LocalConnectionToServer.cs.meta b/Assets/Mirror/Core/LocalConnectionToServer.cs.meta new file mode 100644 index 0000000..856b255 --- /dev/null +++ b/Assets/Mirror/Core/LocalConnectionToServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cdfff390c3504158a269e8b8662e2a40 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Messages.cs b/Assets/Mirror/Core/Messages.cs new file mode 100644 index 0000000..62888c0 --- /dev/null +++ b/Assets/Mirror/Core/Messages.cs @@ -0,0 +1,140 @@ +using System; +using UnityEngine; + +namespace Mirror +{ + // need to send time every sendInterval. + // batching automatically includes remoteTimestamp. + // all we need to do is ensure that an empty message is sent. + // and react to it. + // => we don't want to insert a snapshot on every batch. + // => do it exactly every sendInterval on every TimeSnapshotMessage. + public struct TimeSnapshotMessage : NetworkMessage {} + + public struct ReadyMessage : NetworkMessage {} + + public struct NotReadyMessage : NetworkMessage {} + + public struct AddPlayerMessage : NetworkMessage {} + + public struct SceneMessage : NetworkMessage + { + public string sceneName; + // Normal = 0, LoadAdditive = 1, UnloadAdditive = 2 + public SceneOperation sceneOperation; + public bool customHandling; + } + + public enum SceneOperation : byte + { + Normal, + LoadAdditive, + UnloadAdditive + } + + public struct CommandMessage : NetworkMessage + { + public uint netId; + public byte componentIndex; + public ushort functionHash; + // the parameters for the Cmd function + // -> ArraySegment to avoid unnecessary allocations + public ArraySegment payload; + } + + public struct RpcMessage : NetworkMessage + { + public uint netId; + public byte componentIndex; + public ushort functionHash; + // the parameters for the Cmd function + // -> ArraySegment to avoid unnecessary allocations + public ArraySegment payload; + } + + public struct SpawnMessage : NetworkMessage + { + // netId of new or existing object + public uint netId; + public bool isLocalPlayer; + // Sets hasAuthority on the spawned object + public bool isOwner; + public ulong sceneId; + // If sceneId != 0 then it is used instead of assetId + public uint assetId; + // Local position + public Vector3 position; + // Local rotation + public Quaternion rotation; + // Local scale + public Vector3 scale; + // serialized component data + // ArraySegment to avoid unnecessary allocations + public ArraySegment payload; + } + + public struct ChangeOwnerMessage : NetworkMessage + { + public uint netId; + public bool isOwner; + public bool isLocalPlayer; + } + + public struct ObjectSpawnStartedMessage : NetworkMessage {} + + public struct ObjectSpawnFinishedMessage : NetworkMessage {} + + public struct ObjectDestroyMessage : NetworkMessage + { + public uint netId; + } + + public struct ObjectHideMessage : NetworkMessage + { + public uint netId; + } + + public struct EntityStateMessage : NetworkMessage + { + public uint netId; + // the serialized component data + // -> ArraySegment to avoid unnecessary allocations + public ArraySegment payload; + } + + // whoever wants to measure rtt, sends this to the other end. + public struct NetworkPingMessage : NetworkMessage + { + // local time is used to calculate round trip time, + // and to calculate the predicted time offset. + public double localTime; + + // predicted time is sent to compare the final error, for debugging only + public double predictedTimeAdjusted; + + public NetworkPingMessage(double localTime, double predictedTimeAdjusted) + { + this.localTime = localTime; + this.predictedTimeAdjusted = predictedTimeAdjusted; + } + } + + // the other end responds with this message. + // we can use this to calculate rtt. + public struct NetworkPongMessage : NetworkMessage + { + // local time is used to calculate round trip time. + public double localTime; + + // predicted error is used to adjust the predicted timeline. + public double predictionErrorUnadjusted; + public double predictionErrorAdjusted; // for debug purposes + + public NetworkPongMessage(double localTime, double predictionErrorUnadjusted, double predictionErrorAdjusted) + { + this.localTime = localTime; + this.predictionErrorUnadjusted = predictionErrorUnadjusted; + this.predictionErrorAdjusted = predictionErrorAdjusted; + } + } +} diff --git a/Assets/Mirror/Core/Messages.cs.meta b/Assets/Mirror/Core/Messages.cs.meta new file mode 100644 index 0000000..5d119e2 --- /dev/null +++ b/Assets/Mirror/Core/Messages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 938f6f28a6c5b48a0bbd7782342d763b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Mirror.asmdef b/Assets/Mirror/Core/Mirror.asmdef new file mode 100644 index 0000000..2fa8d95 --- /dev/null +++ b/Assets/Mirror/Core/Mirror.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Mirror", + "rootNamespace": "", + "references": [ + "GUID:325984b52e4128546bc7558552f8b1d2" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Core/Mirror.asmdef.meta b/Assets/Mirror/Core/Mirror.asmdef.meta new file mode 100644 index 0000000..202009b --- /dev/null +++ b/Assets/Mirror/Core/Mirror.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 30817c1a0e6d646d99c048fc403f5979 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkAuthenticator.cs b/Assets/Mirror/Core/NetworkAuthenticator.cs new file mode 100644 index 0000000..aa1e7f7 --- /dev/null +++ b/Assets/Mirror/Core/NetworkAuthenticator.cs @@ -0,0 +1,84 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +namespace Mirror +{ + [Serializable] public class UnityEventNetworkConnection : UnityEvent {} + + /// Base class for implementing component-based authentication during the Connect phase + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-authenticators")] + public abstract class NetworkAuthenticator : MonoBehaviour + { + /// Notify subscribers on the server when a client is authenticated + [Header("Event Listeners (optional)")] + [Tooltip("Mirror has an internal subscriber to this event. You can add your own here.")] + public UnityEventNetworkConnection OnServerAuthenticated = new UnityEventNetworkConnection(); + + /// Notify subscribers on the client when the client is authenticated + [Tooltip("Mirror has an internal subscriber to this event. You can add your own here.")] + public UnityEvent OnClientAuthenticated = new UnityEvent(); + + /// Called when server starts, used to register message handlers if needed. + public virtual void OnStartServer() {} + + /// Called when server stops, used to unregister message handlers if needed. + public virtual void OnStopServer() {} + + /// Called on server from OnServerConnectInternal when a client needs to authenticate + public virtual void OnServerAuthenticate(NetworkConnectionToClient conn) {} + + protected void ServerAccept(NetworkConnectionToClient conn) + { + OnServerAuthenticated.Invoke(conn); + } + + protected void ServerReject(NetworkConnectionToClient conn) + { + conn.Disconnect(); + } + + /// Called when client starts, used to register message handlers if needed. + public virtual void OnStartClient() {} + + /// Called when client stops, used to unregister message handlers if needed. + public virtual void OnStopClient() {} + + /// Called on client from OnClientConnectInternal when a client needs to authenticate + public virtual void OnClientAuthenticate() {} + + protected void ClientAccept() + { + OnClientAuthenticated.Invoke(); + } + + protected void ClientReject() + { + // Set this on the client for local reference + NetworkClient.connection.isAuthenticated = false; + + // disconnect the client + NetworkClient.connection.Disconnect(); + } + + // Reset() instead of OnValidate(): + // Any NetworkAuthenticator assigns itself to the NetworkManager, this is fine on first adding it, + // but if someone intentionally sets Authenticator to null on the NetworkManager again then the + // Authenticator will reassign itself if a value in the inspector is changed. + // My change switches OnValidate to Reset since Reset is only called when the component is first + // added (or reset is pressed). + void Reset() + { +#if UNITY_EDITOR + // automatically assign authenticator field if we add this to NetworkManager + NetworkManager manager = GetComponent(); + if (manager != null && manager.authenticator == null) + { + // undo has to be called before the change happens + UnityEditor.Undo.RecordObject(manager, "Assigned NetworkManager authenticator"); + manager.authenticator = this; + } +#endif + } + } +} diff --git a/Assets/Mirror/Core/NetworkAuthenticator.cs.meta b/Assets/Mirror/Core/NetworkAuthenticator.cs.meta new file mode 100644 index 0000000..d37db68 --- /dev/null +++ b/Assets/Mirror/Core/NetworkAuthenticator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 407fc95d4a8257f448799f26cdde0c2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkBehaviour.cs b/Assets/Mirror/Core/NetworkBehaviour.cs new file mode 100644 index 0000000..cc81b94 --- /dev/null +++ b/Assets/Mirror/Core/NetworkBehaviour.cs @@ -0,0 +1,1370 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Mirror +{ + // SyncMode decides if a component is synced to all observers, or only owner + public enum SyncMode { Observers, Owner } + + // SyncDirection decides if a component is synced from: + // * server to all clients + // * owner client, to server, to all other clients + // + // naming: 'ClientToServer' etc. instead of 'ClientAuthority', because + // that wouldn't be accurate. server's OnDeserialize can still validate + // client data before applying. it's really about direction, not authority. + public enum SyncDirection { ServerToClient, ClientToServer } + + /// Base class for networked components. + // [RequireComponent(typeof(NetworkIdentity))] disabled to allow child NetworkBehaviours + [AddComponentMenu("")] + [HelpURL("https://mirror-networking.gitbook.io/docs/guides/networkbehaviour")] + public abstract class NetworkBehaviour : MonoBehaviour + { + /// Sync direction for OnSerialize. ServerToClient by default. ClientToServer for client authority. + [Tooltip("Server Authority calls OnSerialize on the server and syncs it to clients.\n\nClient Authority calls OnSerialize on the owning client, syncs it to server, which then broadcasts it to all other clients.\n\nUse server authority for cheat safety.")] + [HideInInspector] public SyncDirection syncDirection = SyncDirection.ServerToClient; + + /// sync mode for OnSerialize + // hidden because NetworkBehaviourInspector shows it only if has OnSerialize. + [Tooltip("By default synced data is sent from the server to all Observers of the object.\nChange this to Owner to only have the server update the client that has ownership authority for this object")] + [HideInInspector] public SyncMode syncMode = SyncMode.Observers; + + /// sync interval for OnSerialize (in seconds) + // hidden because NetworkBehaviourInspector shows it only if has OnSerialize. + // [0,2] should be enough. anything >2s is too laggy anyway. + // + // NetworkServer & NetworkClient broadcast() are behind a sendInterval timer now. + // it makes sense to keep every component's syncInterval setting at '0' by default. + // otherwise, the overlapping timers could introduce unexpected latency. + // careful: default of '0.1' may + [Tooltip("Time in seconds until next change is synchronized to the client. '0' means send immediately if changed. '0.5' means only send changes every 500ms.\n(This is for state synchronization like SyncVars, SyncLists, OnSerialize. Not for Cmds, Rpcs, etc.)")] + [Range(0, 2)] + [HideInInspector] public float syncInterval = 0; + internal double lastSyncTime; + + /// True if this object is on the server and has been spawned. + // This is different from NetworkServer.active, which is true if the + // server itself is active rather than this object being active. + public bool isServer => netIdentity.isServer; + + /// True if this object is on the client and has been spawned by the server. + public bool isClient => netIdentity.isClient; + + /// True if this object is the the client's own local player. + public bool isLocalPlayer => netIdentity.isLocalPlayer; + + /// True if this object is on the server-only, not host. + public bool isServerOnly => netIdentity.isServerOnly; + + /// True if this object is on the client-only, not host. + public bool isClientOnly => netIdentity.isClientOnly; + + /// isOwned is true on the client if this NetworkIdentity is one of the .owned entities of our connection on the server. + // for example: main player & pets are owned. monsters & npcs aren't. + public bool isOwned => netIdentity.isOwned; + + /// authority is true if we are allowed to modify this component's state. On server, it's true if SyncDirection is ServerToClient. On client, it's true if SyncDirection is ClientToServer and(!) if this object is owned by the client. + // on the client: if Client->Server SyncDirection and owned + // on the server: if Server->Client SyncDirection + // on the host: if Server->Client SyncDirection (= server owns it), or if Client->Server and owned (=host client owns it) + // in host mode: always true because either server or client always has authority, and host is both. + // + // for example, NetworkTransform: + // client may modify position if ClientAuthority mode and owned + // server may modify position only if server authority + // + // note that in original Mirror, hasAuthority only meant 'isOwned'. + // there was no syncDirection to check. + // + // also note that this is a per-NetworkBehaviour flag. + // another component may not be client authoritative, etc. + public bool authority + { + get + { + // host mode needs to be checked explicitly + if (isClient && isServer) return syncDirection == SyncDirection.ServerToClient || isOwned; + + // client-only + if (isClient) return syncDirection == SyncDirection.ClientToServer && isOwned; + + // server-only + return syncDirection == SyncDirection.ServerToClient; + } + } + + /// The unique network Id of this object (unique at runtime). + public uint netId => netIdentity.netId; + + /// Client's network connection to the server. This is only valid for player objects on the client. + // TODO change to NetworkConnectionToServer, but might cause some breaking + public NetworkConnection connectionToServer => netIdentity.connectionToServer; + + /// Server's network connection to the client. This is only valid for player objects on the server. + public NetworkConnectionToClient connectionToClient => netIdentity.connectionToClient; + + // SyncLists, SyncSets, etc. + protected readonly List syncObjects = new List(); + + // NetworkBehaviourInspector needs to know if we have SyncObjects + internal bool HasSyncObjects() => syncObjects.Count > 0; + + // NetworkIdentity based values set from NetworkIdentity.Awake(), + // which is way more simple and way faster than trying to figure out + // component index from in here by searching all NetworkComponents. + + /// Returns the NetworkIdentity of this object + public NetworkIdentity netIdentity { get; internal set; } + + /// Returns the index of the component on this object + public byte ComponentIndex { get; internal set; } + + // to avoid fully serializing entities every time, we have two options: + // * run a delta compression algorithm + // -> for fixed size types this is as easy as varint(b-a) for all + // -> for dynamically sized types like strings this is not easy. + // algorithms need to detect inserts/deletions, i.e. Myers Diff. + // those are very cpu intensive and barely fast enough for large + // scale multiplayer games (in Unity) + // * or we use dirty bits as meta data about which fields have changed + // -> spares us from running delta algorithms + // -> still supports dynamically sized types + // + // 64 bit mask, tracking up to 64 SyncVars. + // protected since NB child classes read this field in the weaver generated SerializeSyncVars method + protected ulong syncVarDirtyBits; + // 64 bit mask, tracking up to 64 sync collections. + // internal for tests, field for faster access (instead of property) + // TODO 64 SyncLists are too much. consider smaller mask later. + internal ulong syncObjectDirtyBits; + + // Weaver replaces '[SyncVar] int health' with 'Networkhealth' property. + // setter calls the hook if value changed. + // if we then modify the [SyncVar] from inside the setter, + // the setter would call the hook and we deadlock. + // hook guard prevents that. + ulong syncVarHookGuard; + + // USED BY WEAVER to set syncvars in host mode without deadlocking + protected bool GetSyncVarHookGuard(ulong dirtyBit) => + (syncVarHookGuard & dirtyBit) != 0UL; + + // USED BY WEAVER to set syncvars in host mode without deadlocking + protected void SetSyncVarHookGuard(ulong dirtyBit, bool value) + { + // set the bit + if (value) + syncVarHookGuard |= dirtyBit; + // clear the bit + else + syncVarHookGuard &= ~dirtyBit; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void SetSyncObjectDirtyBit(ulong dirtyBit) + { + syncObjectDirtyBits |= dirtyBit; + } + + /// Set as dirty so that it's synced to clients again. + // these are masks, not bit numbers, ie. 110011b not '2' for 2nd bit. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetSyncVarDirtyBit(ulong dirtyBit) + { + syncVarDirtyBits |= dirtyBit; + } + + /// Set as dirty to trigger OnSerialize & send. Dirty bits are cleared after the send. + // previously one had to use SetSyncVarDirtyBit(1), which is confusing. + // simply reuse SetSyncVarDirtyBit for now. + // instead of adding another field. + // syncVarDirtyBits does trigger OnSerialize as well. + // + // it's important to set _all_ bits as dirty. + // for example, server needs to broadcast ClientToServer components. + // if we only set the first bit, only that SyncVar would be broadcast. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetDirty() => SetSyncVarDirtyBit(ulong.MaxValue); + + // true if syncInterval elapsed and any SyncVar or SyncObject is dirty + // OR both bitmasks. != 0 if either was dirty. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IsDirty() => + // check bits first. this is basically free. + (syncVarDirtyBits | syncObjectDirtyBits) != 0UL && + // only check time if bits were dirty. this is more expensive. + NetworkTime.localTime - lastSyncTime >= syncInterval; + + /// Clears all the dirty bits that were set by SetSyncVarDirtyBit() (formally SetDirtyBits) + // automatically invoked when an update is sent for this object, but can + // be called manually as well. + public void ClearAllDirtyBits() + { + lastSyncTime = NetworkTime.localTime; + syncVarDirtyBits = 0L; + syncObjectDirtyBits = 0L; + + // clear all unsynchronized changes in syncobjects + // (Linq allocates, use for instead) + for (int i = 0; i < syncObjects.Count; ++i) + { + syncObjects[i].ClearChanges(); + } + } + + // this gets called in the constructor by the weaver + // for every SyncObject in the component (e.g. SyncLists). + // We collect all of them and we synchronize them with OnSerialize/OnDeserialize + protected void InitSyncObject(SyncObject syncObject) + { + if (syncObject == null) + { + Debug.LogError("Uninitialized SyncObject. Manually call the constructor on your SyncList, SyncSet, SyncDictionary or SyncField"); + return; + } + + // add it, remember the index in list (if Count=0, index=0 etc.) + int index = syncObjects.Count; + syncObjects.Add(syncObject); + + // OnDirty needs to set nth bit in our dirty mask + ulong nthBit = 1UL << index; + syncObject.OnDirty = () => SetSyncObjectDirtyBit(nthBit); + + // who is allowed to modify SyncList/SyncSet/etc.: + // on client: only if owned ClientToserver + // on server: only if ServerToClient. + // but also for initial state when spawning. + // need to set a lambda because 'isClient' isn't available in + // InitSyncObject yet, which is called from the constructor. + syncObject.IsWritable = () => + { + // carefully check each mode separately to ensure correct results. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3342 + + // normally we would check isServer / isClient here. + // users may add to SyncLists before the object was spawned. + // isServer / isClient would still be false. + // so we need to check NetworkServer/Client.active here instead. + + // host mode: any ServerToClient and any local client owned + if (NetworkServer.active && NetworkClient.active) + return syncDirection == SyncDirection.ServerToClient || isOwned; + + // server only: any ServerToClient + if (NetworkServer.active) + return syncDirection == SyncDirection.ServerToClient; + + // client only: only ClientToServer and owned + if (NetworkClient.active) + { + // spawned: only ClientToServer and owned + if (netId != 0) return syncDirection == SyncDirection.ClientToServer && isOwned; + + // not spawned (character selection previews, etc.): always allow + // fixes https://github.com/MirrorNetworking/Mirror/issues/3343 + return true; + } + + // undefined behaviour should throw to make it very obvious + throw new Exception("InitSyncObject: IsWritable: neither NetworkServer nor NetworkClient are active."); + }; + + // when do we record changes: + // on client: only if owned ClientToServer + // on server: only if we have observers. + // prevents ever growing .changes lists: + // if a monster has no observers but we keep modifing a SyncObject, + // then the changes would never be flushed and keep growing, + // because OnSerialize isn't called without observers. + syncObject.IsRecording = () => + { + // carefully check each mode separately to ensure correct results. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3342 + + // host mode: only if observed + if (isServer && isClient) return netIdentity.observers.Count > 0; + + // server only: only if observed + if (isServer) return netIdentity.observers.Count > 0; + + // client only: only ClientToServer and owned + if (isClient) return syncDirection == SyncDirection.ClientToServer && isOwned; + + // users may add to SyncLists before the object was spawned. + // isServer / isClient would still be false. + // in that case, allow modifying but don't record changes yet. + return false; + }; + } + + protected virtual void OnValidate() + { + // we now allow child NetworkBehaviours. + // we can not [RequireComponent(typeof(NetworkIdentity))] anymore. + // instead, we need to ensure a NetworkIdentity is somewhere in the + // parents. + // only run this in Editor. don't add more runtime overhead. + + // GetComponentInParent(includeInactive) is needed because Prefabs are not + // considered active, so this check requires to scan inactive. +#if UNITY_EDITOR +#if UNITY_2021_3_OR_NEWER // 2021 has GetComponentInParent(bool includeInactive = false) + if (GetComponent() == null && + GetComponentInParent(true) == null) + { + Debug.LogError($"{GetType()} on {name} requires a NetworkIdentity. Please add a NetworkIdentity component to {name} or it's parents.", this); + } +#elif UNITY_2020_3_OR_NEWER // 2020 only has GetComponentsInParent(bool includeInactive = false), we can use this too + NetworkIdentity[] parentsIds = GetComponentsInParent(true); + int parentIdsCount = parentsIds != null ? parentsIds.Length : 0; + if (GetComponent() == null && parentIdsCount == 0) + { + Debug.LogError($"{GetType()} on {name} requires a NetworkIdentity. Please add a NetworkIdentity component to {name} or it's parents.", this); + } +#endif +#endif + } + + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + protected void SendCommandInternal(string functionFullName, int functionHashCode, NetworkWriter writer, int channelId, bool requiresAuthority = true) + { + // this was in Weaver before + // NOTE: we could remove this later to allow calling Cmds on Server + // to avoid Wrapper functions. a lot of people requested this. + if (!NetworkClient.active) + { + Debug.LogError($"Command {functionFullName} called on {name} without an active client.", gameObject); + return; + } + + // previously we used NetworkClient.readyConnection. + // now we check .ready separately. + if (!NetworkClient.ready) + { + // Unreliable Cmds from NetworkTransform may be generated, + // or client may have been set NotReady intentionally, so + // only warn if on the reliable channel. + if (channelId == Channels.Reliable) + Debug.LogWarning($"Command {functionFullName} called on {name} while NetworkClient is not ready.\nThis may be ignored if client intentionally set NotReady.", gameObject); + return; + } + + // local players can always send commands, regardless of authority, + // other objects must have authority. + if (!(!requiresAuthority || isLocalPlayer || isOwned)) + { + Debug.LogWarning($"Command {functionFullName} called on {name} without authority.", gameObject); + return; + } + + // IMPORTANT: can't use .connectionToServer here because calling + // a command on other objects is allowed if requireAuthority is + // false. other objects don't have a .connectionToServer. + // => so we always need to use NetworkClient.connection instead. + // => see also: https://github.com/vis2k/Mirror/issues/2629 + if (NetworkClient.connection == null) + { + Debug.LogError($"Command {functionFullName} called on {name} with no client running.", gameObject); + return; + } + + // construct the message + CommandMessage message = new CommandMessage + { + netId = netId, + componentIndex = ComponentIndex, + // type+func so Inventory.RpcUse != Equipment.RpcUse + functionHash = (ushort)functionHashCode, + // segment to avoid reader allocations + payload = writer.ToArraySegment() + }; + + // IMPORTANT: can't use .connectionToServer here because calling + // a command on other objects is allowed if requireAuthority is + // false. other objects don't have a .connectionToServer. + // => so we always need to use NetworkClient.connection instead. + // => see also: https://github.com/vis2k/Mirror/issues/2629 + // This bypasses the null check in NetworkClient.Send but we have + // a null check above with a detailed error log. + NetworkClient.connection.Send(message, channelId); + } + + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + protected void SendRPCInternal(string functionFullName, int functionHashCode, NetworkWriter writer, int channelId, bool includeOwner) + { + // this was in Weaver before + if (!NetworkServer.active) + { + Debug.LogError($"RPC Function {functionFullName} called without an active server.", gameObject); + return; + } + + // This cannot use NetworkServer.active, as that is not specific to this object. + if (!isServer) + { + Debug.LogWarning($"ClientRpc {functionFullName} called on un-spawned object: {name}", gameObject); + return; + } + + // construct the message + RpcMessage message = new RpcMessage + { + netId = netId, + componentIndex = ComponentIndex, + // type+func so Inventory.RpcUse != Equipment.RpcUse + functionHash = (ushort)functionHashCode, + // segment to avoid reader allocations + payload = writer.ToArraySegment() + }; + + // serialize it to each ready observer's connection's rpc buffer. + // send them all at once, instead of sending one message per rpc. + // NetworkServer.SendToReadyObservers(netIdentity, message, includeOwner, channelId); + + // safety check used to be in SendToReadyObservers. keep it for now. + if (netIdentity.observers == null || netIdentity.observers.Count == 0) + return; + + // serialize the message only once + using (NetworkWriterPooled serialized = NetworkWriterPool.Get()) + { + serialized.Write(message); + + // send to every observer. + // batching buffers this automatically. + foreach (NetworkConnectionToClient conn in netIdentity.observers.Values) + { + bool isOwner = conn == netIdentity.connectionToClient; + if ((!isOwner || includeOwner) && conn.isReady) + { + conn.Send(message, channelId); + } + } + } + } + + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + protected void SendTargetRPCInternal(NetworkConnection conn, string functionFullName, int functionHashCode, NetworkWriter writer, int channelId) + { + if (!NetworkServer.active) + { + Debug.LogError($"TargetRPC {functionFullName} was called on {name} when server not active.", gameObject); + return; + } + + if (!isServer) + { + Debug.LogWarning($"TargetRpc {functionFullName} called on {name} but that object has not been spawned or has been unspawned.", gameObject); + return; + } + + // connection parameter is optional. assign if null. + if (conn is null) + { + conn = connectionToClient; + } + + // if still null + if (conn is null) + { + Debug.LogError($"TargetRPC {functionFullName} can't be sent because it was given a null connection. Make sure {name} is owned by a connection, or if you pass a connection manually then make sure it's not null. For example, TargetRpcs can be called on Player/Pet which are owned by a connection. However, they can not be called on Monsters/Npcs which don't have an owner connection.", gameObject); + return; + } + + // TODO change conn type to NetworkConnectionToClient to begin with. + if (!(conn is NetworkConnectionToClient connToClient)) + { + Debug.LogError($"TargetRPC {functionFullName} called on {name} requires a NetworkConnectionToClient but was given {conn.GetType().Name}", gameObject); + return; + } + + // construct the message + RpcMessage message = new RpcMessage + { + netId = netId, + componentIndex = ComponentIndex, + // type+func so Inventory.RpcUse != Equipment.RpcUse + functionHash = (ushort)functionHashCode, + // segment to avoid reader allocations + payload = writer.ToArraySegment() + }; + + // send it to the connection. + // batching buffers this automatically. + conn.Send(message, channelId); + } + + // move the [SyncVar] generated property's .set into C# to avoid much IL + // + // public int health = 42; + // + // public int Networkhealth + // { + // get + // { + // return health; + // } + // [param: In] + // set + // { + // if (!NetworkBehaviour.SyncVarEqual(value, ref health)) + // { + // int oldValue = health; + // SetSyncVar(value, ref health, 1uL); + // if (NetworkServer.activeHost && !GetSyncVarHookGuard(1uL)) + // { + // SetSyncVarHookGuard(1uL, value: true); + // OnChanged(oldValue, value); + // SetSyncVarHookGuard(1uL, value: false); + // } + // } + // } + // } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void GeneratedSyncVarSetter(T value, ref T field, ulong dirtyBit, Action OnChanged) + { + if (!SyncVarEqual(value, ref field)) + { + T oldValue = field; + SetSyncVar(value, ref field, dirtyBit); + + // call hook (if any) + if (OnChanged != null) + { + // in host mode, setting a SyncVar calls the hook directly. + // in client-only mode, OnDeserialize would call it. + // we use hook guard to protect against deadlock where hook + // changes syncvar, calling hook again. + if (NetworkServer.activeHost && !GetSyncVarHookGuard(dirtyBit)) + { + SetSyncVarHookGuard(dirtyBit, true); + OnChanged(oldValue, value); + SetSyncVarHookGuard(dirtyBit, false); + } + } + } + } + + // GameObject needs custom handling for persistence via netId. + // has one extra parameter. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void GeneratedSyncVarSetter_GameObject(GameObject value, ref GameObject field, ulong dirtyBit, Action OnChanged, ref uint netIdField) + { + if (!SyncVarGameObjectEqual(value, netIdField)) + { + GameObject oldValue = field; + SetSyncVarGameObject(value, ref field, dirtyBit, ref netIdField); + + // call hook (if any) + if (OnChanged != null) + { + // in host mode, setting a SyncVar calls the hook directly. + // in client-only mode, OnDeserialize would call it. + // we use hook guard to protect against deadlock where hook + // changes syncvar, calling hook again. + if (NetworkServer.activeHost && !GetSyncVarHookGuard(dirtyBit)) + { + SetSyncVarHookGuard(dirtyBit, true); + OnChanged(oldValue, value); + SetSyncVarHookGuard(dirtyBit, false); + } + } + } + } + + // NetworkIdentity needs custom handling for persistence via netId. + // has one extra parameter. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void GeneratedSyncVarSetter_NetworkIdentity(NetworkIdentity value, ref NetworkIdentity field, ulong dirtyBit, Action OnChanged, ref uint netIdField) + { + if (!SyncVarNetworkIdentityEqual(value, netIdField)) + { + NetworkIdentity oldValue = field; + SetSyncVarNetworkIdentity(value, ref field, dirtyBit, ref netIdField); + + // call hook (if any) + if (OnChanged != null) + { + // in host mode, setting a SyncVar calls the hook directly. + // in client-only mode, OnDeserialize would call it. + // we use hook guard to protect against deadlock where hook + // changes syncvar, calling hook again. + if (NetworkServer.activeHost && !GetSyncVarHookGuard(dirtyBit)) + { + SetSyncVarHookGuard(dirtyBit, true); + OnChanged(oldValue, value); + SetSyncVarHookGuard(dirtyBit, false); + } + } + } + } + + // NetworkBehaviour needs custom handling for persistence via netId. + // has one extra parameter. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void GeneratedSyncVarSetter_NetworkBehaviour(T value, ref T field, ulong dirtyBit, Action OnChanged, ref NetworkBehaviourSyncVar netIdField) + where T : NetworkBehaviour + { + if (!SyncVarNetworkBehaviourEqual(value, netIdField)) + { + T oldValue = field; + SetSyncVarNetworkBehaviour(value, ref field, dirtyBit, ref netIdField); + + // call hook (if any) + if (OnChanged != null) + { + // in host mode, setting a SyncVar calls the hook directly. + // in client-only mode, OnDeserialize would call it. + // we use hook guard to protect against deadlock where hook + // changes syncvar, calling hook again. + if (NetworkServer.activeHost && !GetSyncVarHookGuard(dirtyBit)) + { + SetSyncVarHookGuard(dirtyBit, true); + OnChanged(oldValue, value); + SetSyncVarHookGuard(dirtyBit, false); + } + } + } + } + + // helper function for [SyncVar] GameObjects. + // needs to be public so that tests & NetworkBehaviours from other + // assemblies both find it + [EditorBrowsable(EditorBrowsableState.Never)] + public static bool SyncVarGameObjectEqual(GameObject newGameObject, uint netIdField) + { + uint newNetId = 0; + if (newGameObject != null) + { + if (newGameObject.TryGetComponent(out NetworkIdentity identity)) + { + newNetId = identity.netId; + if (newNetId == 0) + { + Debug.LogWarning($"SetSyncVarGameObject GameObject {newGameObject} has a zero netId. Maybe it is not spawned yet?"); + } + } + } + + return newNetId == netIdField; + } + + // helper function for [SyncVar] GameObjects. + // dirtyBit is a mask like 00010 + protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gameObjectField, ulong dirtyBit, ref uint netIdField) + { + if (GetSyncVarHookGuard(dirtyBit)) + return; + + uint newNetId = 0; + if (newGameObject != null) + { + if (newGameObject.TryGetComponent(out NetworkIdentity identity)) + { + newNetId = identity.netId; + if (newNetId == 0) + { + Debug.LogWarning($"SetSyncVarGameObject GameObject {newGameObject} has a zero netId. Maybe it is not spawned yet?"); + } + } + } + + //Debug.Log($"SetSyncVar GameObject {GetType().Name} bit:{dirtyBit} netfieldId:{netIdField} -> {newNetId}"); + SetSyncVarDirtyBit(dirtyBit); + // assign new one on the server, and in case we ever need it on client too + gameObjectField = newGameObject; + netIdField = newNetId; + } + + // helper function for [SyncVar] GameObjects. + // -> ref GameObject as second argument makes OnDeserialize processing easier + protected GameObject GetSyncVarGameObject(uint netId, ref GameObject gameObjectField) + { + // server always uses the field + // if neither, fallback to original field + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3447 + if (isServer || !isClient) + { + return gameObjectField; + } + + // client always looks up based on netId because objects might get in and out of range + // over and over again, which shouldn't null them forever + if (NetworkClient.spawned.TryGetValue(netId, out NetworkIdentity identity) && identity != null) + return gameObjectField = identity.gameObject; + return null; + } + + // helper function for [SyncVar] NetworkIdentities. + // needs to be public so that tests & NetworkBehaviours from other + // assemblies both find it + [EditorBrowsable(EditorBrowsableState.Never)] + public static bool SyncVarNetworkIdentityEqual(NetworkIdentity newIdentity, uint netIdField) + { + uint newNetId = 0; + if (newIdentity != null) + { + newNetId = newIdentity.netId; + if (newNetId == 0) + { + Debug.LogWarning($"SetSyncVarNetworkIdentity NetworkIdentity {newIdentity} has a zero netId. Maybe it is not spawned yet?"); + } + } + + // netId changed? + return newNetId == netIdField; + } + + // move the [SyncVar] generated OnDeserialize C# to avoid much IL. + // + // before: + // public override void DeserializeSyncVars(NetworkReader reader, bool initialState) + // { + // base.DeserializeSyncVars(reader, initialState); + // if (initialState) + // { + // int num = health; + // Networkhealth = reader.ReadInt(); + // if (!NetworkBehaviour.SyncVarEqual(num, ref health)) + // { + // OnChanged(num, health); + // } + // return; + // } + // long num2 = (long)reader.ReadULong(); + // if ((num2 & 1L) != 0L) + // { + // int num3 = health; + // Networkhealth = reader.ReadInt(); + // if (!NetworkBehaviour.SyncVarEqual(num3, ref health)) + // { + // OnChanged(num3, health); + // } + // } + // } + // + // after: + // + // public override void DeserializeSyncVars(NetworkReader reader, bool initialState) + // { + // base.DeserializeSyncVars(reader, initialState); + // if (initialState) + // { + // GeneratedSyncVarDeserialize(reader, ref health, null, reader.ReadInt()); + // return; + // } + // long num = (long)reader.ReadULong(); + // if ((num & 1L) != 0L) + // { + // GeneratedSyncVarDeserialize(reader, ref health, null, reader.ReadInt()); + // } + // } + public void GeneratedSyncVarDeserialize(ref T field, Action OnChanged, T value) + { + T previous = field; + field = value; + + // any hook? then call if changed. + if (OnChanged != null && !SyncVarEqual(previous, ref field)) + { + OnChanged(previous, field); + } + } + + // move the [SyncVar] generated OnDeserialize C# to avoid much IL. + // + // before: + // public override void DeserializeSyncVars(NetworkReader reader, bool initialState) + // { + // base.DeserializeSyncVars(reader, initialState); + // if (initialState) + // { + // uint __targetNetId = ___targetNetId; + // GameObject networktarget = Networktarget; + // ___targetNetId = reader.ReadUInt(); + // if (!NetworkBehaviour.SyncVarEqual(__targetNetId, ref ___targetNetId)) + // { + // OnChangedNB(networktarget, Networktarget); + // } + // return; + // } + // long num = (long)reader.ReadULong(); + // if ((num & 1L) != 0L) + // { + // uint __targetNetId2 = ___targetNetId; + // GameObject networktarget2 = Networktarget; + // ___targetNetId = reader.ReadUInt(); + // if (!NetworkBehaviour.SyncVarEqual(__targetNetId2, ref ___targetNetId)) + // { + // OnChangedNB(networktarget2, Networktarget); + // } + // } + // } + // + // after: + // public override void DeserializeSyncVars(NetworkReader reader, bool initialState) + // { + // base.DeserializeSyncVars(reader, initialState); + // if (initialState) + // { + // GeneratedSyncVarDeserialize_GameObject(reader, ref target, OnChangedNB, ref ___targetNetId); + // return; + // } + // long num = (long)reader.ReadULong(); + // if ((num & 1L) != 0L) + // { + // GeneratedSyncVarDeserialize_GameObject(reader, ref target, OnChangedNB, ref ___targetNetId); + // } + // } + public void GeneratedSyncVarDeserialize_GameObject(ref GameObject field, Action OnChanged, NetworkReader reader, ref uint netIdField) + { + uint previousNetId = netIdField; + GameObject previousGameObject = field; + netIdField = reader.ReadUInt(); + + // get the new GameObject now that netId field is set + field = GetSyncVarGameObject(netIdField, ref field); + + // any hook? then call if changed. + if (OnChanged != null && !SyncVarEqual(previousNetId, ref netIdField)) + { + OnChanged(previousGameObject, field); + } + } + + // move the [SyncVar] generated OnDeserialize C# to avoid much IL. + // + // before: + // public override void DeserializeSyncVars(NetworkReader reader, bool initialState) + // { + // base.DeserializeSyncVars(reader, initialState); + // if (initialState) + // { + // uint __targetNetId = ___targetNetId; + // NetworkIdentity networktarget = Networktarget; + // ___targetNetId = reader.ReadUInt(); + // if (!NetworkBehaviour.SyncVarEqual(__targetNetId, ref ___targetNetId)) + // { + // OnChangedNI(networktarget, Networktarget); + // } + // return; + // } + // long num = (long)reader.ReadULong(); + // if ((num & 1L) != 0L) + // { + // uint __targetNetId2 = ___targetNetId; + // NetworkIdentity networktarget2 = Networktarget; + // ___targetNetId = reader.ReadUInt(); + // if (!NetworkBehaviour.SyncVarEqual(__targetNetId2, ref ___targetNetId)) + // { + // OnChangedNI(networktarget2, Networktarget); + // } + // } + // } + // + // after: + // + // public override void DeserializeSyncVars(NetworkReader reader, bool initialState) + // { + // base.DeserializeSyncVars(reader, initialState); + // if (initialState) + // { + // GeneratedSyncVarDeserialize_NetworkIdentity(reader, ref target, OnChangedNI, ref ___targetNetId); + // return; + // } + // long num = (long)reader.ReadULong(); + // if ((num & 1L) != 0L) + // { + // GeneratedSyncVarDeserialize_NetworkIdentity(reader, ref target, OnChangedNI, ref ___targetNetId); + // } + // } + public void GeneratedSyncVarDeserialize_NetworkIdentity(ref NetworkIdentity field, Action OnChanged, NetworkReader reader, ref uint netIdField) + { + uint previousNetId = netIdField; + NetworkIdentity previousIdentity = field; + netIdField = reader.ReadUInt(); + + // get the new NetworkIdentity now that netId field is set + field = GetSyncVarNetworkIdentity(netIdField, ref field); + + // any hook? then call if changed. + if (OnChanged != null && !SyncVarEqual(previousNetId, ref netIdField)) + { + OnChanged(previousIdentity, field); + } + } + + // move the [SyncVar] generated OnDeserialize C# to avoid much IL. + // + // before: + // + // public override void DeserializeSyncVars(NetworkReader reader, bool initialState) + // { + // base.DeserializeSyncVars(reader, initialState); + // if (initialState) + // { + // NetworkBehaviourSyncVar __targetNetId = ___targetNetId; + // Tank networktarget = Networktarget; + // ___targetNetId = reader.ReadNetworkBehaviourSyncVar(); + // if (!NetworkBehaviour.SyncVarEqual(__targetNetId, ref ___targetNetId)) + // { + // OnChangedNB(networktarget, Networktarget); + // } + // return; + // } + // long num = (long)reader.ReadULong(); + // if ((num & 1L) != 0L) + // { + // NetworkBehaviourSyncVar __targetNetId2 = ___targetNetId; + // Tank networktarget2 = Networktarget; + // ___targetNetId = reader.ReadNetworkBehaviourSyncVar(); + // if (!NetworkBehaviour.SyncVarEqual(__targetNetId2, ref ___targetNetId)) + // { + // OnChangedNB(networktarget2, Networktarget); + // } + // } + // } + // + // after: + // + // public override void DeserializeSyncVars(NetworkReader reader, bool initialState) + // { + // base.DeserializeSyncVars(reader, initialState); + // if (initialState) + // { + // GeneratedSyncVarDeserialize_NetworkBehaviour(reader, ref target, OnChangedNB, ref ___targetNetId); + // return; + // } + // long num = (long)reader.ReadULong(); + // if ((num & 1L) != 0L) + // { + // GeneratedSyncVarDeserialize_NetworkBehaviour(reader, ref target, OnChangedNB, ref ___targetNetId); + // } + // } + public void GeneratedSyncVarDeserialize_NetworkBehaviour(ref T field, Action OnChanged, NetworkReader reader, ref NetworkBehaviourSyncVar netIdField) + where T : NetworkBehaviour + { + NetworkBehaviourSyncVar previousNetId = netIdField; + T previousBehaviour = field; + netIdField = reader.ReadNetworkBehaviourSyncVar(); + + // get the new NetworkBehaviour now that netId field is set + field = GetSyncVarNetworkBehaviour(netIdField, ref field); + + // any hook? then call if changed. + if (OnChanged != null && !SyncVarEqual(previousNetId, ref netIdField)) + { + OnChanged(previousBehaviour, field); + } + } + + // helper function for [SyncVar] NetworkIdentities. + // dirtyBit is a mask like 00010 + protected void SetSyncVarNetworkIdentity(NetworkIdentity newIdentity, ref NetworkIdentity identityField, ulong dirtyBit, ref uint netIdField) + { + if (GetSyncVarHookGuard(dirtyBit)) + return; + + uint newNetId = 0; + if (newIdentity != null) + { + newNetId = newIdentity.netId; + if (newNetId == 0) + { + Debug.LogWarning($"SetSyncVarNetworkIdentity NetworkIdentity {newIdentity} has a zero netId. Maybe it is not spawned yet?"); + } + } + + //Debug.Log($"SetSyncVarNetworkIdentity NetworkIdentity {GetType().Name} bit:{dirtyBit} netIdField:{netIdField} -> {newNetId}"); + SetSyncVarDirtyBit(dirtyBit); + netIdField = newNetId; + // assign new one on the server, and in case we ever need it on client too + identityField = newIdentity; + } + + // helper function for [SyncVar] NetworkIdentities. + // -> ref GameObject as second argument makes OnDeserialize processing easier + protected NetworkIdentity GetSyncVarNetworkIdentity(uint netId, ref NetworkIdentity identityField) + { + // server always uses the field + // if neither, fallback to original field + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3447 + if (isServer || !isClient) + { + return identityField; + } + + // client always looks up based on netId because objects might get in and out of range + // over and over again, which shouldn't null them forever + NetworkClient.spawned.TryGetValue(netId, out identityField); + return identityField; + } + + protected static bool SyncVarNetworkBehaviourEqual(T newBehaviour, NetworkBehaviourSyncVar syncField) where T : NetworkBehaviour + { + uint newNetId = 0; + byte newComponentIndex = 0; + if (newBehaviour != null) + { + newNetId = newBehaviour.netId; + newComponentIndex = newBehaviour.ComponentIndex; + if (newNetId == 0) + { + Debug.LogWarning($"SetSyncVarNetworkIdentity NetworkIdentity {newBehaviour} has a zero netId. Maybe it is not spawned yet?"); + } + } + + // netId changed? + return syncField.Equals(newNetId, newComponentIndex); + } + + // helper function for [SyncVar] NetworkIdentities. + // dirtyBit is a mask like 00010 + protected void SetSyncVarNetworkBehaviour(T newBehaviour, ref T behaviourField, ulong dirtyBit, ref NetworkBehaviourSyncVar syncField) where T : NetworkBehaviour + { + if (GetSyncVarHookGuard(dirtyBit)) + return; + + uint newNetId = 0; + byte componentIndex = 0; + if (newBehaviour != null) + { + newNetId = newBehaviour.netId; + componentIndex = newBehaviour.ComponentIndex; + if (newNetId == 0) + { + Debug.LogWarning($"{nameof(SetSyncVarNetworkBehaviour)} NetworkIdentity {newBehaviour} has a zero netId. Maybe it is not spawned yet?"); + } + } + + syncField = new NetworkBehaviourSyncVar(newNetId, componentIndex); + + SetSyncVarDirtyBit(dirtyBit); + + // assign new one on the server, and in case we ever need it on client too + behaviourField = newBehaviour; + + // Debug.Log($"SetSyncVarNetworkBehaviour NetworkIdentity {GetType().Name} bit [{dirtyBit}] netIdField:{oldField}->{syncField}"); + } + + // helper function for [SyncVar] NetworkIdentities. + // -> ref GameObject as second argument makes OnDeserialize processing easier + protected T GetSyncVarNetworkBehaviour(NetworkBehaviourSyncVar syncNetBehaviour, ref T behaviourField) where T : NetworkBehaviour + { + // server always uses the field + // if neither, fallback to original field + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3447 + if (isServer || !isClient) + { + return behaviourField; + } + + // client always looks up based on netId because objects might get in and out of range + // over and over again, which shouldn't null them forever + if (!NetworkClient.spawned.TryGetValue(syncNetBehaviour.netId, out NetworkIdentity identity)) + { + return null; + } + + behaviourField = identity.NetworkBehaviours[syncNetBehaviour.componentIndex] as T; + return behaviourField; + } + + protected static bool SyncVarEqual(T value, ref T fieldValue) + { + // newly initialized or changed value? + // value.Equals(fieldValue) allocates without 'where T : IEquatable' + // seems like we use EqualityComparer to avoid allocations, + // because not all SyncVars are IEquatable + return EqualityComparer.Default.Equals(value, fieldValue); + } + + // dirtyBit is a mask like 00010 + protected void SetSyncVar(T value, ref T fieldValue, ulong dirtyBit) + { + //Debug.Log($"SetSyncVar {GetType().Name} bit:{dirtyBit} fieldValue:{value}"); + SetSyncVarDirtyBit(dirtyBit); + fieldValue = value; + } + + /// Override to do custom serialization (instead of SyncVars/SyncLists). Use OnDeserialize too. + // if a class has syncvars, then OnSerialize/OnDeserialize are added + // automatically. + // + // initialState is true for full spawns, false for delta syncs. + // note: SyncVar hooks are only called when inital=false + public virtual void OnSerialize(NetworkWriter writer, bool initialState) + { + SerializeSyncObjects(writer, initialState); + SerializeSyncVars(writer, initialState); + } + + /// Override to do custom deserialization (instead of SyncVars/SyncLists). Use OnSerialize too. + public virtual void OnDeserialize(NetworkReader reader, bool initialState) + { + DeserializeSyncObjects(reader, initialState); + DeserializeSyncVars(reader, initialState); + } + + void SerializeSyncObjects(NetworkWriter writer, bool initialState) + { + // if initialState: write all SyncVars. + // otherwise write dirtyBits+dirty SyncVars + if (initialState) + SerializeObjectsAll(writer); + else + SerializeObjectsDelta(writer); + } + + void DeserializeSyncObjects(NetworkReader reader, bool initialState) + { + if (initialState) + { + DeserializeObjectsAll(reader); + } + else + { + DeserializeObjectsDelta(reader); + } + } + + // USED BY WEAVER + protected virtual void SerializeSyncVars(NetworkWriter writer, bool initialState) + { + // SyncVar are written here in subclass + + // if initialState + // write all SyncVars + // else + // write syncVarDirtyBits + // write dirty SyncVars + } + + // USED BY WEAVER + protected virtual void DeserializeSyncVars(NetworkReader reader, bool initialState) + { + // SyncVars are read here in subclass + + // if initialState + // read all SyncVars + // else + // read syncVarDirtyBits + // read dirty SyncVars + } + + public void SerializeObjectsAll(NetworkWriter writer) + { + for (int i = 0; i < syncObjects.Count; i++) + { + SyncObject syncObject = syncObjects[i]; + syncObject.OnSerializeAll(writer); + } + } + + public void SerializeObjectsDelta(NetworkWriter writer) + { + // write the mask + writer.WriteULong(syncObjectDirtyBits); + + // serializable objects, such as synclists + for (int i = 0; i < syncObjects.Count; i++) + { + // check dirty mask at nth bit + SyncObject syncObject = syncObjects[i]; + if ((syncObjectDirtyBits & (1UL << i)) != 0) + { + syncObject.OnSerializeDelta(writer); + } + } + } + + internal void DeserializeObjectsAll(NetworkReader reader) + { + for (int i = 0; i < syncObjects.Count; i++) + { + SyncObject syncObject = syncObjects[i]; + syncObject.OnDeserializeAll(reader); + } + } + + internal void DeserializeObjectsDelta(NetworkReader reader) + { + ulong dirty = reader.ReadULong(); + for (int i = 0; i < syncObjects.Count; i++) + { + // check dirty mask at nth bit + SyncObject syncObject = syncObjects[i]; + if ((dirty & (1UL << i)) != 0) + { + syncObject.OnDeserializeDelta(reader); + } + } + } + + // safely serialize each component in a way that one reading too much or + // too few bytes will show obvious, easy to resolve error messages. + // + // prevents the original UNET bug which started Mirror: + // https://github.com/vis2k/Mirror/issues/2617 + // where one component would read too much, and then all following reads + // on other entities would be mismatched, causing the weirdest errors. + // + // reads <> for 100% safety. + internal void Serialize(NetworkWriter writer, bool initialState) + { + // reserve length header to ensure the correct amount will be read. + // originally we used a 4 byte header (too bandwidth heavy). + // instead, let's "& 0xFF" the size. + // + // this is cleaner than barriers at the end of payload, because: + // - ensures the correct safety is read _before_ payload. + // - it's quite hard to break the check. + // a component would need to read/write the intented amount + // multiplied by 255 in order to miss the check. + // with barriers, reading 1 byte too much may still succeed if the + // next component's first byte matches the expected barrier. + // - we can still attempt to correct the invalid position via the + // safety length byte (we know that one is correct). + // + // it's just overall cleaner, and still low on bandwidth. + + // write placeholder length byte + // (jumping back later is WAY faster than allocating a temporary + // writer for the payload, then writing payload.size, payload) + int headerPosition = writer.Position; + writer.WriteByte(0); + int contentPosition = writer.Position; + + // write payload + try + { + // note this may not write anything if no syncIntervals elapsed + OnSerialize(writer, initialState); + } + catch (Exception e) + { + // show a detailed error and let the user know what went wrong + Debug.LogError($"OnSerialize failed for: object={name} component={GetType()} sceneId={netIdentity.sceneId:X}\n\n{e}"); + } + int endPosition = writer.Position; + + // fill in length hash as the last byte of the 4 byte length + writer.Position = headerPosition; + int size = endPosition - contentPosition; + byte safety = (byte)(size & 0xFF); + writer.WriteByte(safety); + writer.Position = endPosition; + + //Debug.Log($"OnSerializeSafely written for object {name} component:{GetType()} sceneId:{sceneId:X} header:{headerPosition} content:{contentPosition} end:{endPosition} contentSize:{endPosition - contentPosition}"); + } + + // correct the read size with the 1 byte length hash (by mischa). + // -> the component most likely read a few too many/few bytes. + // -> we know the correct last byte of the expected size (=the safety). + // -> attempt to reconstruct the size via safety byte. + // it will be correct unless someone wrote way way too much, + // as in > 255 bytes worth too much. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int ErrorCorrection(int size, byte safety) + { + // clear the last byte which most likely contains the error + uint cleared = (uint)size & 0xFFFFFF00; + + // insert the safety which we know to be correct + return (int)(cleared | safety); + } + + // returns false in case of errors. + // server needs to know in order to disconnect on error. + internal bool Deserialize(NetworkReader reader, bool initialState) + { + // detect errors, but attempt to correct before returning + bool result = true; + + // read 1 byte length hash safety & capture beginning for size check + byte safety = reader.ReadByte(); + int chunkStart = reader.Position; + + // call OnDeserialize and wrap it in a try-catch block so there's no + // way to mess up another component's deserialization + try + { + //Debug.Log($"OnDeserializeSafely: {name} component:{GetType()} sceneId:{sceneId:X} length:{contentSize}"); + OnDeserialize(reader, initialState); + } + catch (Exception e) + { + // show a detailed error and let the user know what went wrong + Debug.LogError($"OnDeserialize failed Exception={e.GetType()} (see below) object={name} component={GetType()} netId={netId}. Possible Reasons:\n" + + $" * Do {GetType()}'s OnSerialize and OnDeserialize calls write the same amount of data? \n" + + $" * Was there an exception in {GetType()}'s OnSerialize/OnDeserialize code?\n" + + $" * Are the server and client the exact same project?\n" + + $" * Maybe this OnDeserialize call was meant for another GameObject? The sceneIds can easily get out of sync if the Hierarchy was modified only in the client OR the server. Try rebuilding both.\n\n" + + $"Exception {e}"); + result = false; + } + + // compare bytes read with length hash + int size = reader.Position - chunkStart; + byte sizeHash = (byte)(size & 0xFF); + if (sizeHash != safety) + { + // warn the user. + Debug.LogWarning($"{name} (netId={netId}): {GetType()} OnDeserialize size mismatch. It read {size} bytes, which caused a size hash mismatch of {sizeHash:X2} vs. {safety:X2}. Make sure that OnSerialize and OnDeserialize write/read the same amount of data in all cases."); + + // attempt to fix the position, so the following components + // don't all fail. this is very likely to work, unless the user + // read more than 255 bytes too many / too few. + // + // see test: SerializationSizeMismatch. + int correctedSize = ErrorCorrection(size, safety); + reader.Position = chunkStart + correctedSize; + result = false; + } + + return result; + } + + internal void ResetSyncObjects() + { + foreach (SyncObject syncObject in syncObjects) + { + syncObject.Reset(); + } + } + + /// Like Start(), but only called on server and host. + public virtual void OnStartServer() {} + + /// Stop event, only called on server and host. + public virtual void OnStopServer() {} + + /// Like Start(), but only called on client and host. + public virtual void OnStartClient() {} + + /// Stop event, only called on client and host. + public virtual void OnStopClient() {} + + /// Like Start(), but only called on client and host for the local player object. + public virtual void OnStartLocalPlayer() {} + + /// Stop event, but only called on client and host for the local player object. + public virtual void OnStopLocalPlayer() {} + + /// Like Start(), but only called for objects the client has authority over. + public virtual void OnStartAuthority() {} + + /// Stop event, only called for objects the client has authority over. + public virtual void OnStopAuthority() {} + + // Weaver injects this into inheriting classes to return true. + // allows runtime & tests to check if a type was weaved. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual bool Weaved() => false; + } +} diff --git a/Assets/Mirror/Core/NetworkBehaviour.cs.meta b/Assets/Mirror/Core/NetworkBehaviour.cs.meta new file mode 100644 index 0000000..f0bc195 --- /dev/null +++ b/Assets/Mirror/Core/NetworkBehaviour.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 655ee8cba98594f70880da5cc4dc442d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkBehaviourSyncVar.cs b/Assets/Mirror/Core/NetworkBehaviourSyncVar.cs new file mode 100644 index 0000000..e9ed726 --- /dev/null +++ b/Assets/Mirror/Core/NetworkBehaviourSyncVar.cs @@ -0,0 +1,33 @@ +using System; + +namespace Mirror +{ + // backing field for sync NetworkBehaviour + public struct NetworkBehaviourSyncVar : IEquatable + { + public uint netId; + // limited to 255 behaviours per identity + public byte componentIndex; + + public NetworkBehaviourSyncVar(uint netId, int componentIndex) : this() + { + this.netId = netId; + this.componentIndex = (byte)componentIndex; + } + + public bool Equals(NetworkBehaviourSyncVar other) + { + return other.netId == netId && other.componentIndex == componentIndex; + } + + public bool Equals(uint netId, int componentIndex) + { + return this.netId == netId && this.componentIndex == componentIndex; + } + + public override string ToString() + { + return $"[netId:{netId} compIndex:{componentIndex}]"; + } + } +} diff --git a/Assets/Mirror/Core/NetworkBehaviourSyncVar.cs.meta b/Assets/Mirror/Core/NetworkBehaviourSyncVar.cs.meta new file mode 100644 index 0000000..47e3893 --- /dev/null +++ b/Assets/Mirror/Core/NetworkBehaviourSyncVar.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b04fe7518657486089dfaf811db0b3ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkClient.cs b/Assets/Mirror/Core/NetworkClient.cs new file mode 100644 index 0000000..097dd3e --- /dev/null +++ b/Assets/Mirror/Core/NetworkClient.cs @@ -0,0 +1,1842 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Mirror.RemoteCalls; +using UnityEngine; + +namespace Mirror +{ + public enum ConnectState + { + None, + // connecting between Connect() and OnTransportConnected() + Connecting, + Connected, + // disconnecting between Disconnect() and OnTransportDisconnected() + Disconnecting, + Disconnected + } + + /// NetworkClient with connection to server. + public static partial class NetworkClient + { + // time & value snapshot interpolation are separate. + // -> time is interpolated globally on NetworkClient / NetworkConnection + // -> value is interpolated per-component, i.e. NetworkTransform. + // however, both need to be on the same send interval. + // + // additionally, server & client need to use the same send interval. + // otherwise it's too easy to accidentally cause interpolation issues if + // a component sends with client.interval but interpolates with + // server.interval, etc. + public static int sendRate => NetworkServer.sendRate; + public static float sendInterval => sendRate < int.MaxValue ? 1f / sendRate : 0; // for 30 Hz, that's 33ms + static double lastSendTime; + + // For security, it is recommended to disconnect a player if a networked + // action triggers an exception\nThis could prevent components being + // accessed in an undefined state, which may be an attack vector for + // exploits. + // + // However, some games may want to allow exceptions in order to not + // interrupt the player's experience. + public static bool exceptionsDisconnect = true; // security by default + + // message handlers by messageId + internal static readonly Dictionary handlers = + new Dictionary(); + + /// All spawned NetworkIdentities by netId. + // client sees OBSERVED spawned ones. + public static readonly Dictionary spawned = + new Dictionary(); + + /// Client's NetworkConnection to server. + public static NetworkConnection connection { get; internal set; } + + /// True if client is ready (= joined world). + // TODO redundant state. point it to .connection.isReady instead (& test) + // TODO OR remove NetworkConnection.isReady? unless it's used on server + // + // TODO maybe ClientState.Connected/Ready/AddedPlayer/etc.? + // way better for security if we can check states in callbacks + public static bool ready; + + /// NetworkIdentity of the localPlayer + public static NetworkIdentity localPlayer { get; internal set; } + + // NetworkClient state + internal static ConnectState connectState = ConnectState.None; + + /// active is true while a client is connecting/connected either as standalone or as host client. + // (= while the network is active) + public static bool active => connectState == ConnectState.Connecting || + connectState == ConnectState.Connected; + + /// active is true while the client is connected in host mode. + // naming consistent with NetworkServer.activeHost. + public static bool activeHost => connection is LocalConnectionToServer; + + /// Check if client is connecting (before connected). + public static bool isConnecting => connectState == ConnectState.Connecting; + + /// Check if client is connected (after connecting). + public static bool isConnected => connectState == ConnectState.Connected; + + // OnConnected / OnDisconnected used to be NetworkMessages that were + // invoked. this introduced a bug where external clients could send + // Connected/Disconnected messages over the network causing undefined + // behaviour. + // => public so that custom NetworkManagers can hook into it + public static Action OnConnectedEvent; + public static Action OnDisconnectedEvent; + public static Action OnErrorEvent; + + /// Registered spawnable prefabs by assetId. + public static readonly Dictionary prefabs = + new Dictionary(); + + // custom spawn / unspawn handlers by assetId. + // useful to support prefab pooling etc.: + // https://mirror-networking.gitbook.io/docs/guides/gameobjects/custom-spawnfunctions + internal static readonly Dictionary spawnHandlers = + new Dictionary(); + internal static readonly Dictionary unspawnHandlers = + new Dictionary(); + + // spawning + // internal for tests + internal static bool isSpawnFinished; + + // Disabled scene objects that can be spawned again, by sceneId. + internal static readonly Dictionary spawnableObjects = + new Dictionary(); + + internal static Unbatcher unbatcher = new Unbatcher(); + + // interest management component (optional) + // only needed for SetHostVisibility + public static InterestManagementBase aoi; + + // scene loading + public static bool isLoadingScene; + + // connection quality + // this is set by a virtual function in NetworkManager, + // which allows users to overwrite it with their own estimations. + public static ConnectionQuality connectionQuality = ConnectionQuality.ESTIMATING; + public static ConnectionQuality lastConnectionQuality = ConnectionQuality.ESTIMATING; + public static ConnectionQualityMethod connectionQualityMethod = ConnectionQualityMethod.Simple; + public static float connectionQualityInterval = 3; + static double lastConnectionQualityUpdate; + + /// + /// Invoked when connection quality changes. + /// First argument is the old quality, second argument is the new quality. + /// + public static event Action onConnectionQualityChanged; + + // initialization ////////////////////////////////////////////////////// + static void AddTransportHandlers() + { + // community Transports may forget to call OnDisconnected. + // which could cause handlers to be added twice with +=. + // ensure we always clear the old ones first. + // fixes: https://github.com/vis2k/Mirror/issues/3152 + RemoveTransportHandlers(); + + // += so that other systems can also hook into it (i.e. statistics) + Transport.active.OnClientConnected += OnTransportConnected; + Transport.active.OnClientDataReceived += OnTransportData; + Transport.active.OnClientDisconnected += OnTransportDisconnected; + Transport.active.OnClientError += OnTransportError; + } + + static void RemoveTransportHandlers() + { + // -= so that other systems can also hook into it (i.e. statistics) + Transport.active.OnClientConnected -= OnTransportConnected; + Transport.active.OnClientDataReceived -= OnTransportData; + Transport.active.OnClientDisconnected -= OnTransportDisconnected; + Transport.active.OnClientError -= OnTransportError; + } + + // connect ///////////////////////////////////////////////////////////// + // initialize is called before every connect + static void Initialize(bool hostMode) + { + // safety: ensure Weaving succeded. + // if it silently failed, we would get lots of 'writer not found' + // and other random errors at runtime instead. this is cleaner. + if (!WeaverFuse.Weaved()) + { + // if it failed, throw an exception to early exit all Connect calls. + throw new Exception("NetworkClient won't start because Weaving failed or didn't run."); + } + + // Debug.Log($"Client Connect: {address}"); + Debug.Assert(Transport.active != null, "There was no active transport when calling NetworkClient.Connect, If you are calling Connect manually then make sure to set 'Transport.active' first"); + + // reset unbatcher in case any batches from last session remain. + // need to do this in Initialize() so it runs for the host as well. + // fixes host mode scene transition receiving data from previous scene. + // credits: BigBoxVR + unbatcher = new Unbatcher(); + + // reset time interpolation on every new connect. + // ensures last sessions' state is cleared before starting again. + InitTimeInterpolation(); + + RegisterMessageHandlers(hostMode); + Transport.active.enabled = true; + } + + /// Connect client to a NetworkServer by address. + public static void Connect(string address) + { + Initialize(false); + + AddTransportHandlers(); + connectState = ConnectState.Connecting; + Transport.active.ClientConnect(address); + connection = new NetworkConnectionToServer(); + } + + /// Connect client to a NetworkServer by Uri. + public static void Connect(Uri uri) + { + Initialize(false); + + AddTransportHandlers(); + connectState = ConnectState.Connecting; + Transport.active.ClientConnect(uri); + connection = new NetworkConnectionToServer(); + } + + // TODO why are there two connect host methods? + // called from NetworkManager.FinishStartHost() + public static void ConnectHost() + { + Initialize(true); + connectState = ConnectState.Connected; + HostMode.SetupConnections(); + } + + // disconnect ////////////////////////////////////////////////////////// + /// Disconnect from server. + public static void Disconnect() + { + // only if connected or connecting. + // don't disconnect() again if already in the process of + // disconnecting or fully disconnected. + if (connectState != ConnectState.Connecting && + connectState != ConnectState.Connected) + return; + + // we are disconnecting until OnTransportDisconnected is called. + // setting state to Disconnected would stop OnTransportDisconnected + // from calling cleanup code because it would think we are already + // disconnected fully. + // TODO move to 'cleanup' code below if safe + connectState = ConnectState.Disconnecting; + ready = false; + + // call Disconnect on the NetworkConnection + connection?.Disconnect(); + + // IMPORTANT: do NOT clear connection here yet. + // we still need it in OnTransportDisconnected for callbacks. + // connection = null; + } + + // transport events //////////////////////////////////////////////////// + // called by Transport + static void OnTransportConnected() + { + if (connection != null) + { + // reset network time stats + NetworkTime.ResetStatics(); + + // the handler may want to send messages to the client + // thus we should set the connected state before calling the handler + connectState = ConnectState.Connected; + // ping right away after connecting so client gets new time asap + NetworkTime.SendPing(); + OnConnectedEvent?.Invoke(); + } + else Debug.LogError("Skipped Connect message handling because connection is null."); + } + + // helper function + static bool UnpackAndInvoke(NetworkReader reader, int channelId) + { + if (NetworkMessages.UnpackId(reader, out ushort msgType)) + { + // try to invoke the handler for that message + if (handlers.TryGetValue(msgType, out NetworkMessageDelegate handler)) + { + handler.Invoke(connection, reader, channelId); + + // message handler may disconnect client, making connection = null + // therefore must check for null to avoid NRE. + if (connection != null) + connection.lastMessageTime = Time.time; + + return true; + } + else + { + // message in a batch are NOT length prefixed to save bandwidth. + // every message needs to be handled and read until the end. + // otherwise it would overlap into the next message. + // => need to warn and disconnect to avoid undefined behaviour. + // => WARNING, not error. can happen if attacker sends random data. + Debug.LogWarning($"Unknown message id: {msgType}. This can happen if no handler was registered for this message."); + // simply return false. caller is responsible for disconnecting. + //connection.Disconnect(); + return false; + } + } + else + { + // => WARNING, not error. can happen if attacker sends random data. + Debug.LogWarning("Invalid message header."); + // simply return false. caller is responsible for disconnecting. + //connection.Disconnect(); + return false; + } + } + + // called by Transport + internal static void OnTransportData(ArraySegment data, int channelId) + { + if (connection != null) + { + // server might batch multiple messages into one packet. + // feed it to the Unbatcher. + // NOTE: we don't need to associate a channelId because we + // always process all messages in the batch. + if (!unbatcher.AddBatch(data)) + { + if (exceptionsDisconnect) + { + Debug.LogError($"NetworkClient: failed to add batch, disconnecting."); + connection.Disconnect(); + } + else + Debug.LogWarning($"NetworkClient: failed to add batch."); + + return; + } + + // process all messages in the batch. + // only while NOT loading a scene. + // if we get a scene change message, then we need to stop + // processing. otherwise we might apply them to the old scene. + // => fixes https://github.com/vis2k/Mirror/issues/2651 + // + // NOTE: is scene starts loading, then the rest of the batch + // would only be processed when OnTransportData is called + // the next time. + // => consider moving processing to NetworkEarlyUpdate. + while (!isLoadingScene && + unbatcher.GetNextMessage(out ArraySegment message, out double remoteTimestamp)) + { + using (NetworkReaderPooled reader = NetworkReaderPool.Get(message)) + { + // enough to read at least header size? + if (reader.Remaining >= NetworkMessages.IdSize) + { + // make remoteTimeStamp available to the user + connection.remoteTimeStamp = remoteTimestamp; + + // handle message + if (!UnpackAndInvoke(reader, channelId)) + { + // warn, disconnect and return if failed + // -> warning because attackers might send random data + // -> messages in a batch aren't length prefixed. + // failing to read one would cause undefined + // behaviour for every message afterwards. + // so we need to disconnect. + // -> return to avoid the below unbatches.count error. + // we already disconnected and handled it. + if (exceptionsDisconnect) + { + Debug.LogError($"NetworkClient: failed to unpack and invoke message. Disconnecting."); + connection.Disconnect(); + } + else + Debug.LogWarning($"NetworkClient: failed to unpack and invoke message."); + + return; + } + } + // otherwise disconnect + else + { + if (exceptionsDisconnect) + { + Debug.LogError($"NetworkClient: received Message was too short (messages should start with message id). Disconnecting."); + connection.Disconnect(); + } + else + Debug.LogWarning("NetworkClient: received Message was too short (messages should start with message id)"); + return; + } + } + } + + // if we weren't interrupted by a scene change, + // then all batched messages should have been processed now. + // if not, we need to log an error to avoid debugging hell. + // otherwise batches would silently grow. + // we need to log an error to avoid debugging hell. + // + // EXAMPLE: https://github.com/vis2k/Mirror/issues/2882 + // -> UnpackAndInvoke silently returned because no handler for id + // -> Reader would never be read past the end + // -> Batch would never be retired because end is never reached + // + // NOTE: prefixing every message in a batch with a length would + // avoid ever not reading to the end. for extra bandwidth. + // + // IMPORTANT: always keep this check to detect memory leaks. + // this took half a day to debug last time. + if (!isLoadingScene && unbatcher.BatchesCount > 0) + { + Debug.LogError($"Still had {unbatcher.BatchesCount} batches remaining after processing, even though processing was not interrupted by a scene change. This should never happen, as it would cause ever growing batches.\nPossible reasons:\n* A message didn't deserialize as much as it serialized\n*There was no message handler for a message id, so the reader wasn't read until the end."); + } + } + else Debug.LogError("Skipped Data message handling because connection is null."); + } + + // called by Transport + // IMPORTANT: often times when disconnecting, we call this from Mirror + // too because we want to remove the connection and handle + // the disconnect immediately. + // => which is fine as long as we guarantee it only runs once + // => which we do by setting the state to Disconnected! + internal static void OnTransportDisconnected() + { + // StopClient called from user code triggers Disconnected event + // from transport which calls StopClient again, so check here + // and short circuit running the Shutdown process twice. + if (connectState == ConnectState.Disconnected) return; + + // Raise the event before changing ConnectState + // because 'active' depends on this during shutdown + // + // previously OnDisconnected was only invoked if connection != null. + // however, if DNS resolve fails in Transport.Connect(), + // OnDisconnected would never be called because 'connection' is only + // created after the Transport.Connect() call. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3365 + OnDisconnectedEvent?.Invoke(); + + connectState = ConnectState.Disconnected; + ready = false; + snapshots.Clear(); + localTimeline = 0; + + // now that everything was handled, clear the connection. + // previously this was done in Disconnect() already, but we still + // need it for the above OnDisconnectedEvent. + connection = null; + + // transport handlers are only added when connecting. + // so only remove when actually disconnecting. + RemoveTransportHandlers(); + } + + // transport errors are forwarded to high level + static void OnTransportError(TransportError error, string reason) + { + // transport errors will happen. logging a warning is enough. + // make sure the user does not panic. + Debug.LogWarning($"Client Transport Error: {error}: {reason}. This is fine."); + OnErrorEvent?.Invoke(error, reason); + } + + // send //////////////////////////////////////////////////////////////// + /// Send a NetworkMessage to the server over the given channel. + public static void Send(T message, int channelId = Channels.Reliable) + where T : struct, NetworkMessage + { + if (connection != null) + { + if (connectState == ConnectState.Connected) + { + connection.Send(message, channelId); + } + else Debug.LogError("NetworkClient Send when not connected to a server"); + } + else Debug.LogError("NetworkClient Send with no connection"); + } + + // message handlers //////////////////////////////////////////////////// + internal static void RegisterMessageHandlers(bool hostMode) + { + // host mode client / remote client react to some messages differently. + // but we still need to add handlers for all of them to avoid + // 'message id not found' errors. + if (hostMode) + { + RegisterHandler(OnHostClientObjectDestroy); + RegisterHandler(OnHostClientObjectHide); + RegisterHandler(_ => { }, false); + RegisterHandler(OnHostClientSpawn); + // host mode doesn't need spawning + RegisterHandler(_ => { }); + // host mode doesn't need spawning + RegisterHandler(_ => { }); + // host mode doesn't need state updates + RegisterHandler(_ => { }); + } + else + { + RegisterHandler(OnObjectDestroy); + RegisterHandler(OnObjectHide); + RegisterHandler(NetworkTime.OnClientPong, false); + RegisterHandler(NetworkTime.OnClientPing, false); + RegisterHandler(OnSpawn); + RegisterHandler(OnObjectSpawnStarted); + RegisterHandler(OnObjectSpawnFinished); + RegisterHandler(OnEntityStateMessage); + } + + // These handlers are the same for host and remote clients + RegisterHandler(OnTimeSnapshotMessage); + RegisterHandler(OnChangeOwner); + RegisterHandler(OnRPCMessage); + } + + /// Register a handler for a message type T. Most should require authentication. + public static void RegisterHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + ushort msgType = NetworkMessageId.Id; + if (handlers.ContainsKey(msgType)) + { + Debug.LogWarning($"NetworkClient.RegisterHandler replacing handler for {typeof(T).FullName}, id={msgType}. If replacement is intentional, use ReplaceHandler instead to avoid this warning."); + } + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + // we use the same WrapHandler function for server and client. + // so let's wrap it to ignore the NetworkConnection parameter. + // it's not needed on client. it's always NetworkClient.connection. + void HandlerWrapped(NetworkConnection _, T value) => handler(value); + handlers[msgType] = NetworkMessages.WrapHandler((Action)HandlerWrapped, requireAuthentication, exceptionsDisconnect); + } + + /// Register a handler for a message type T. Most should require authentication. + // This version passes channelId to the handler. + public static void RegisterHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + ushort msgType = NetworkMessageId.Id; + if (handlers.ContainsKey(msgType)) + { + Debug.LogWarning($"NetworkClient.RegisterHandler replacing handler for {typeof(T).FullName}, id={msgType}. If replacement is intentional, use ReplaceHandler instead to avoid this warning."); + } + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + // we use the same WrapHandler function for server and client. + // so let's wrap it to ignore the NetworkConnection parameter. + // it's not needed on client. it's always NetworkClient.connection. + void HandlerWrapped(NetworkConnection _, T value, int channelId) => handler(value, channelId); + handlers[msgType] = NetworkMessages.WrapHandler((Action)HandlerWrapped, requireAuthentication, exceptionsDisconnect); + } + + // Deprecated 2024-01-21 + [Obsolete("Use ReplaceHandler without the NetworkConnection parameter instead. This version is obsolete and will be removed soon.")] + public static void ReplaceHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + // we use the same WrapHandler function for server and client. + // so let's wrap it to ignore the NetworkConnection parameter. + // it's not needed on client. it's always NetworkClient.connection. + ushort msgType = NetworkMessageId.Id; + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + void HandlerWrapped(NetworkConnection _, T value) => handler(_, value); + handlers[msgType] = NetworkMessages.WrapHandler((Action)HandlerWrapped, requireAuthentication, exceptionsDisconnect); + } + + /// Replace a handler for a particular message type. Should require authentication by default. + // RegisterHandler throws a warning (as it should) if a handler is assigned twice + // Use of ReplaceHandler makes it clear the user intended to replace the handler + public static void ReplaceHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + // we use the same WrapHandler function for server and client. + // so let's wrap it to ignore the NetworkConnection parameter. + // it's not needed on client. it's always NetworkClient.connection. + ushort msgType = NetworkMessageId.Id; + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + void HandlerWrapped(NetworkConnection _, T value) => handler(value); + handlers[msgType] = NetworkMessages.WrapHandler((Action)HandlerWrapped, requireAuthentication, exceptionsDisconnect); + } + + /// Replace a handler for a particular message type. Should require authentication by default. This version passes channelId to the handler. + // RegisterHandler throws a warning (as it should) if a handler is assigned twice + // Use of ReplaceHandler makes it clear the user intended to replace the handler + public static void ReplaceHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + // we use the same WrapHandler function for server and client. + // so let's wrap it to ignore the NetworkConnection parameter. + // it's not needed on client. it's always NetworkClient.connection. + ushort msgType = NetworkMessageId.Id; + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + void HandlerWrapped(NetworkConnection _, T value, int channelId) => handler(value, channelId); + handlers[msgType] = NetworkMessages.WrapHandler((Action)HandlerWrapped, requireAuthentication, exceptionsDisconnect); + } + + /// Unregister a message handler of type T. + public static bool UnregisterHandler() + where T : struct, NetworkMessage + { + // use int to minimize collisions + ushort msgType = NetworkMessageId.Id; + return handlers.Remove(msgType); + } + + // spawnable prefabs /////////////////////////////////////////////////// + /// Find the registered prefab for this asset id. + // Useful for debuggers + public static bool GetPrefab(uint assetId, out GameObject prefab) + { + prefab = null; + return assetId != 0 && + prefabs.TryGetValue(assetId, out prefab) && + prefab != null; + } + + /// Validates Prefab then adds it to prefabs dictionary. + static void RegisterPrefabIdentity(NetworkIdentity prefab) + { + if (prefab.assetId == 0) + { + Debug.LogError($"Can not Register '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead"); + return; + } + + if (prefab.sceneId != 0) + { + Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene."); + return; + } + + // disallow child NetworkIdentities. + // TODO likely not necessary anymore due to the new check in + // NetworkIdentity.OnValidate. + NetworkIdentity[] identities = prefab.GetComponentsInChildren(); + if (identities.Length > 1) + { + Debug.LogError($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object."); + } + + if (prefabs.ContainsKey(prefab.assetId)) + { + GameObject existingPrefab = prefabs[prefab.assetId]; + Debug.LogWarning($"Replacing existing prefab with assetId '{prefab.assetId}'. Old prefab '{existingPrefab.name}', New prefab '{prefab.name}'"); + } + + if (spawnHandlers.ContainsKey(prefab.assetId) || unspawnHandlers.ContainsKey(prefab.assetId)) + { + Debug.LogWarning($"Adding prefab '{prefab.name}' with assetId '{prefab.assetId}' when spawnHandlers with same assetId already exists. If you want to use custom spawn handling, then remove the prefab from NetworkManager's registered prefabs first."); + } + + // Debug.Log($"Registering prefab '{prefab.name}' as asset:{prefab.assetId}"); + + prefabs[prefab.assetId] = prefab.gameObject; + } + + /// Register spawnable prefab with custom assetId. + // Note: newAssetId can not be set on GameObjects that already have an assetId + // Note: registering with assetId is useful for assetbundles etc. a lot + // of people use this. + public static void RegisterPrefab(GameObject prefab, uint newAssetId) + { + if (prefab == null) + { + Debug.LogError("Could not register prefab because it was null"); + return; + } + + if (newAssetId == 0) + { + Debug.LogError($"Could not register '{prefab.name}' with new assetId because the new assetId was empty"); + return; + } + + if (!prefab.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component"); + return; + } + + if (identity.assetId != 0 && identity.assetId != newAssetId) + { + Debug.LogError($"Could not register '{prefab.name}' to {newAssetId} because it already had an AssetId, Existing assetId {identity.assetId}"); + return; + } + + identity.assetId = newAssetId; + + RegisterPrefabIdentity(identity); + } + + /// Register spawnable prefab. + public static void RegisterPrefab(GameObject prefab) + { + if (prefab == null) + { + Debug.LogError("Could not register prefab because it was null"); + return; + } + + if (!prefab.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component"); + return; + } + + RegisterPrefabIdentity(identity); + } + + /// Register a spawnable prefab with custom assetId and custom spawn/unspawn handlers. + // Note: newAssetId can not be set on GameObjects that already have an assetId + // Note: registering with assetId is useful for assetbundles etc. a lot + // of people use this. + // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate? + public static void RegisterPrefab(GameObject prefab, uint newAssetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler) + { + // We need this check here because we don't want a null handler in the lambda expression below + if (spawnHandler == null) + { + Debug.LogError($"Can not Register null SpawnHandler for {newAssetId}"); + return; + } + + RegisterPrefab(prefab, newAssetId, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler); + } + + /// Register a spawnable prefab with custom spawn/unspawn handlers. + // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate? + public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler) + { + if (prefab == null) + { + Debug.LogError("Could not register handler for prefab because the prefab was null"); + return; + } + + if (!prefab.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component"); + return; + } + + if (identity.sceneId != 0) + { + Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene."); + return; + } + + if (identity.assetId == 0) + { + Debug.LogError($"Can not Register handler for '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead"); + return; + } + + // We need this check here because we don't want a null handler in the lambda expression below + if (spawnHandler == null) + { + Debug.LogError($"Can not Register null SpawnHandler for {identity.assetId}"); + return; + } + + RegisterPrefab(prefab, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler); + } + + /// Register a spawnable prefab with custom assetId and custom spawn/unspawn handlers. + // Note: newAssetId can not be set on GameObjects that already have an assetId + // Note: registering with assetId is useful for assetbundles etc. a lot + // of people use this. + // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate? + public static void RegisterPrefab(GameObject prefab, uint newAssetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler) + { + if (newAssetId == 0) + { + Debug.LogError($"Could not register handler for '{prefab.name}' with new assetId because the new assetId was empty"); + return; + } + + if (prefab == null) + { + Debug.LogError("Could not register handler for prefab because the prefab was null"); + return; + } + + if (!prefab.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component"); + return; + } + + if (identity.assetId != 0 && identity.assetId != newAssetId) + { + Debug.LogError($"Could not register Handler for '{prefab.name}' to {newAssetId} because it already had an AssetId, Existing assetId {identity.assetId}"); + return; + } + + if (identity.sceneId != 0) + { + Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene."); + return; + } + + identity.assetId = newAssetId; + uint assetId = identity.assetId; + + if (spawnHandler == null) + { + Debug.LogError($"Can not Register null SpawnHandler for {assetId}"); + return; + } + + if (unspawnHandler == null) + { + Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}"); + return; + } + + if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId)) + { + Debug.LogWarning($"Replacing existing spawnHandlers for prefab '{prefab.name}' with assetId '{assetId}'"); + } + + if (prefabs.ContainsKey(assetId)) + { + // this is error because SpawnPrefab checks prefabs before handler + Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}', unregister the prefab first before trying to add handler"); + } + + NetworkIdentity[] identities = prefab.GetComponentsInChildren(); + if (identities.Length > 1) + { + Debug.LogError($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object."); + } + + //Debug.Log($"Registering custom prefab {prefab.name} as asset:{assetId} {spawnHandler.GetMethodName()}/{unspawnHandler.GetMethodName()}"); + + spawnHandlers[assetId] = spawnHandler; + unspawnHandlers[assetId] = unspawnHandler; + } + + /// Register a spawnable prefab with custom spawn/unspawn handlers. + // TODO why do we have one with SpawnDelegate and one with SpawnHandlerDelegate? + public static void RegisterPrefab(GameObject prefab, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler) + { + if (prefab == null) + { + Debug.LogError("Could not register handler for prefab because the prefab was null"); + return; + } + + if (!prefab.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component"); + return; + } + + if (identity.sceneId != 0) + { + Debug.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene."); + return; + } + + uint assetId = identity.assetId; + + if (assetId == 0) + { + Debug.LogError($"Can not Register handler for '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead"); + return; + } + + if (spawnHandler == null) + { + Debug.LogError($"Can not Register null SpawnHandler for {assetId}"); + return; + } + + if (unspawnHandler == null) + { + Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}"); + return; + } + + if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId)) + { + Debug.LogWarning($"Replacing existing spawnHandlers for prefab '{prefab.name}' with assetId '{assetId}'"); + } + + if (prefabs.ContainsKey(assetId)) + { + // this is error because SpawnPrefab checks prefabs before handler + Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}', unregister the prefab first before trying to add handler"); + } + + NetworkIdentity[] identities = prefab.GetComponentsInChildren(); + if (identities.Length > 1) + { + Debug.LogError($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object."); + } + + //Debug.Log($"Registering custom prefab {prefab.name} as asset:{assetId} {spawnHandler.GetMethodName()}/{unspawnHandler.GetMethodName()}"); + + spawnHandlers[assetId] = spawnHandler; + unspawnHandlers[assetId] = unspawnHandler; + } + + /// Removes a registered spawn prefab that was setup with NetworkClient.RegisterPrefab. + public static void UnregisterPrefab(GameObject prefab) + { + if (prefab == null) + { + Debug.LogError("Could not unregister prefab because it was null"); + return; + } + + if (!prefab.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"Could not unregister '{prefab.name}' since it contains no NetworkIdentity component"); + return; + } + + uint assetId = identity.assetId; + + prefabs.Remove(assetId); + spawnHandlers.Remove(assetId); + unspawnHandlers.Remove(assetId); + } + + // spawn handlers ////////////////////////////////////////////////////// + /// This is an advanced spawning function that registers a custom assetId with the spawning system. + // This can be used to register custom spawning methods for an assetId - + // instead of the usual method of registering spawning methods for a + // prefab. This should be used when no prefab exists for the spawned + // objects - such as when they are constructed dynamically at runtime + // from configuration data. + public static void RegisterSpawnHandler(uint assetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler) + { + // We need this check here because we don't want a null handler in the lambda expression below + if (spawnHandler == null) + { + Debug.LogError($"Can not Register null SpawnHandler for {assetId}"); + return; + } + + RegisterSpawnHandler(assetId, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler); + } + + /// This is an advanced spawning function that registers a custom assetId with the spawning system. + // This can be used to register custom spawning methods for an assetId - + // instead of the usual method of registering spawning methods for a + // prefab. This should be used when no prefab exists for the spawned + // objects - such as when they are constructed dynamically at runtime + // from configuration data. + public static void RegisterSpawnHandler(uint assetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler) + { + if (spawnHandler == null) + { + Debug.LogError($"Can not Register null SpawnHandler for {assetId}"); + return; + } + + if (unspawnHandler == null) + { + Debug.LogError($"Can not Register null UnSpawnHandler for {assetId}"); + return; + } + + if (assetId == 0) + { + Debug.LogError("Can not Register SpawnHandler for empty assetId"); + return; + } + + if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId)) + { + Debug.LogWarning($"Replacing existing spawnHandlers for {assetId}"); + } + + if (prefabs.ContainsKey(assetId)) + { + // this is error because SpawnPrefab checks prefabs before handler + Debug.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}'"); + } + + // Debug.Log("RegisterSpawnHandler asset {assetId} {spawnHandler.GetMethodName()}/{unspawnHandler.GetMethodName()}"); + + spawnHandlers[assetId] = spawnHandler; + unspawnHandlers[assetId] = unspawnHandler; + } + + /// Removes a registered spawn handler function that was registered with NetworkClient.RegisterHandler(). + public static void UnregisterSpawnHandler(uint assetId) + { + spawnHandlers.Remove(assetId); + unspawnHandlers.Remove(assetId); + } + + /// This clears the registered spawn prefabs and spawn handler functions for this client. + public static void ClearSpawners() + { + prefabs.Clear(); + spawnHandlers.Clear(); + unspawnHandlers.Clear(); + } + + internal static bool InvokeUnSpawnHandler(uint assetId, GameObject obj) + { + if (unspawnHandlers.TryGetValue(assetId, out UnSpawnDelegate handler) && handler != null) + { + handler(obj); + return true; + } + return false; + } + + // ready /////////////////////////////////////////////////////////////// + /// Sends Ready message to server, indicating that we loaded the scene, ready to enter the game. + // This could be for example when a client enters an ongoing game and + // has finished loading the current scene. The server should respond to + // the SYSTEM_READY event with an appropriate handler which instantiates + // the players object for example. + public static bool Ready() + { + // Debug.Log($"NetworkClient.Ready() called with connection {conn}"); + if (ready) + { + Debug.LogError("NetworkClient is already ready. It shouldn't be called twice."); + return false; + } + + // need a valid connection to become ready + if (connection == null) + { + Debug.LogError("Ready() called with invalid connection object: conn=null"); + return false; + } + + // Set these before sending the ReadyMessage, otherwise host client + // will fail in InternalAddPlayer with null readyConnection. + // TODO this is redundant. have one source of truth for .ready + ready = true; + connection.isReady = true; + + // Tell server we're ready to have a player object spawned + connection.Send(new ReadyMessage()); + return true; + } + + // add player ////////////////////////////////////////////////////////// + // called from message handler for Owner message + internal static void InternalAddPlayer(NetworkIdentity identity) + { + //Debug.Log("NetworkClient.InternalAddPlayer"); + + // NOTE: It can be "normal" when changing scenes for the player to be destroyed and recreated. + // But, the player structures are not cleaned up, we'll just replace the old player + localPlayer = identity; + + // NOTE: we DONT need to set isClient=true here, because OnStartClient + // is called before OnStartLocalPlayer, hence it's already set. + // localPlayer.isClient = true; + + // TODO this check might not be necessary + //if (readyConnection != null) + if (ready && connection != null) + { + connection.identity = identity; + } + else Debug.LogWarning("NetworkClient can't AddPlayer before being ready. Please call NetworkClient.Ready() first. Clients are considered ready after joining the game world."); + } + + /// Sends AddPlayer message to the server, indicating that we want to join the world. + public static bool AddPlayer() + { + // ensure valid ready connection + if (connection == null) + { + Debug.LogError("AddPlayer requires a valid NetworkClient.connection."); + return false; + } + + // UNET checked 'if readyConnection != null'. + // in other words, we need a connection and we need to be ready. + if (!ready) + { + Debug.LogError("AddPlayer requires a ready NetworkClient."); + return false; + } + + if (connection.identity != null) + { + Debug.LogError("NetworkClient.AddPlayer: a PlayerController was already added. Did you call AddPlayer twice?"); + return false; + } + + // Debug.Log($"NetworkClient.AddPlayer() called with connection {readyConnection}"); + connection.Send(new AddPlayerMessage()); + return true; + } + + // spawning //////////////////////////////////////////////////////////// + internal static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage message) + { + if (message.assetId != 0) + identity.assetId = message.assetId; + + if (!identity.gameObject.activeSelf) + { + identity.gameObject.SetActive(true); + } + + // apply local values for VR support + identity.transform.localPosition = message.position; + identity.transform.localRotation = message.rotation; + identity.transform.localScale = message.scale; + + // configure flags + // the below DeserializeClient call invokes SyncVarHooks. + // flags always need to be initialized before that. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3259 + identity.isOwned = message.isOwner; + identity.netId = message.netId; + + if (message.isLocalPlayer) + InternalAddPlayer(identity); + + // configure isClient/isLocalPlayer flags. + // => after InternalAddPlayer. can't initialize .isLocalPlayer + // before InternalAddPlayer sets .localPlayer + // => before DeserializeClient, otherwise SyncVar hooks wouldn't + // have isClient/isLocalPlayer set yet. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3259 + InitializeIdentityFlags(identity); + + // deserialize components if any payload + // (Count is 0 if there were no components) + if (message.payload.Count > 0) + { + using (NetworkReaderPooled payloadReader = NetworkReaderPool.Get(message.payload)) + { + identity.DeserializeClient(payloadReader, true); + } + } + + spawned[message.netId] = identity; + if (identity.isOwned) connection?.owned.Add(identity); + + // the initial spawn with OnObjectSpawnStarted/Finished calls all + // object's OnStartClient/OnStartLocalPlayer after they were all + // spawned. + // this only happens once though. + // for all future spawns, we need to call OnStartClient/LocalPlayer + // here immediately since there won't be another OnObjectSpawnFinished. + if (isSpawnFinished) + { + InvokeIdentityCallbacks(identity); + } + } + + // Finds Existing Object with NetId or spawns a new one using AssetId or sceneId + internal static bool FindOrSpawnObject(SpawnMessage message, out NetworkIdentity identity) + { + // was the object already spawned? + identity = GetExistingObject(message.netId); + + // if found, return early + if (identity != null) + { + return true; + } + + if (message.assetId == 0 && message.sceneId == 0) + { + Debug.LogError($"OnSpawn message with netId '{message.netId}' has no AssetId or sceneId"); + return false; + } + + identity = message.sceneId == 0 ? SpawnPrefab(message) : SpawnSceneObject(message.sceneId); + + if (identity == null) + { + Debug.LogError($"Could not spawn assetId={message.assetId} scene={message.sceneId:X} netId={message.netId}"); + return false; + } + + return true; + } + + static NetworkIdentity GetExistingObject(uint netid) + { + spawned.TryGetValue(netid, out NetworkIdentity identity); + return identity; + } + + static NetworkIdentity SpawnPrefab(SpawnMessage message) + { + // custom spawn handler for this prefab? (for prefab pools etc.) + // + // IMPORTANT: look for spawn handlers BEFORE looking for registered + // prefabs. Unspawning also looks for unspawn handlers + // before falling back to regular Destroy. this needs to + // be consistent. + // https://github.com/vis2k/Mirror/issues/2705 + if (spawnHandlers.TryGetValue(message.assetId, out SpawnHandlerDelegate handler)) + { + GameObject obj = handler(message); + if (obj == null) + { + Debug.LogError($"Spawn Handler returned null, Handler assetId '{message.assetId}'"); + return null; + } + + if (!obj.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"Object Spawned by handler did not have a NetworkIdentity, Handler assetId '{message.assetId}'"); + return null; + } + + return identity; + } + + // otherwise look in NetworkManager registered prefabs + if (GetPrefab(message.assetId, out GameObject prefab)) + { + GameObject obj = GameObject.Instantiate(prefab, message.position, message.rotation); + //Debug.Log($"Client spawn handler instantiating [netId{message.netId} asset ID:{message.assetId} pos:{message.position} rotation:{message.rotation}]"); + return obj.GetComponent(); + } + + Debug.LogError($"Failed to spawn server object, did you forget to add it to the NetworkManager? assetId={message.assetId} netId={message.netId}"); + return null; + } + + static NetworkIdentity SpawnSceneObject(ulong sceneId) + { + NetworkIdentity identity = GetAndRemoveSceneObject(sceneId); + if (identity == null) + { + Debug.LogError($"Spawn scene object not found for {sceneId:X}. Make sure that client and server use exactly the same project. This only happens if the hierarchy gets out of sync."); + + // dump the whole spawnable objects dict for easier debugging + //foreach (KeyValuePair kvp in spawnableObjects) + // Debug.Log($"Spawnable: SceneId={kvp.Key:X} name={kvp.Value.name}"); + } + //else Debug.Log($"Client spawn for [netId:{msg.netId}] [sceneId:{msg.sceneId:X}] obj:{identity}"); + return identity; + } + + static NetworkIdentity GetAndRemoveSceneObject(ulong sceneId) + { + if (spawnableObjects.TryGetValue(sceneId, out NetworkIdentity identity)) + { + spawnableObjects.Remove(sceneId); + return identity; + } + return null; + } + + /// Call this after loading/unloading a scene in the client after connection to register the spawnable objects + public static void PrepareToSpawnSceneObjects() + { + // remove existing items, they will be re-added below + spawnableObjects.Clear(); + + // finds all NetworkIdentity currently loaded by unity (includes disabled objects) + NetworkIdentity[] allIdentities = Resources.FindObjectsOfTypeAll(); + foreach (NetworkIdentity identity in allIdentities) + { + // add all unspawned NetworkIdentities to spawnable objects + // need to check netId to make sure object is not spawned + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3541 + // PrepareToSpawnSceneObjects may be called multiple times in case + // the ObjectSpawnStarted message is received multiple times. + if (Utils.IsSceneObject(identity) && + identity.netId == 0) + { + if (spawnableObjects.TryGetValue(identity.sceneId, out NetworkIdentity existingIdentity)) + { + string msg = $"NetworkClient: Duplicate sceneId {identity.sceneId} detected on {identity.gameObject.name} and {existingIdentity.gameObject.name}\n" + + $"This can happen if a networked object is persisted in DontDestroyOnLoad through loading / changing to the scene where it originated,\n" + + $"otherwise you may need to open and re-save the {identity.gameObject.scene} to reset scene id's."; + Debug.LogWarning(msg, identity.gameObject); + } + else + { + spawnableObjects.Add(identity.sceneId, identity); + } + } + } + } + + internal static void OnObjectSpawnStarted(ObjectSpawnStartedMessage _) + { + // Debug.Log("SpawnStarted"); + PrepareToSpawnSceneObjects(); + isSpawnFinished = false; + } + + internal static void OnObjectSpawnFinished(ObjectSpawnFinishedMessage _) + { + // paul: Initialize the objects in the same order as they were + // initialized in the server. This is important if spawned objects + // use data from scene objects + foreach (NetworkIdentity identity in spawned.Values.OrderBy(uv => uv.netId)) + { + // NetworkIdentities should always be removed from .spawned when + // they are destroyed. for safety, let's double check here. + if (identity != null) + { + BootstrapIdentity(identity); + } + else Debug.LogWarning("Found null entry in NetworkClient.spawned. This is unexpected. Was the NetworkIdentity not destroyed properly?"); + } + isSpawnFinished = true; + } + + // host mode callbacks ///////////////////////////////////////////////// + static void OnHostClientObjectDestroy(ObjectDestroyMessage message) + { + //Debug.Log($"NetworkClient.OnLocalObjectObjDestroy netId:{message.netId}"); + + // remove from owned (if any) + if (spawned.TryGetValue(message.netId, out NetworkIdentity identity)) + connection.owned.Remove(identity); + + spawned.Remove(message.netId); + } + + static void OnHostClientObjectHide(ObjectHideMessage message) + { + //Debug.Log($"ClientScene::OnLocalObjectObjHide netId:{message.netId}"); + if (spawned.TryGetValue(message.netId, out NetworkIdentity identity) && + identity != null) + { + if (aoi != null) + aoi.SetHostVisibility(identity, false); + } + } + + internal static void OnHostClientSpawn(SpawnMessage message) + { + // on host mode, the object already exist in NetworkServer.spawned. + // simply add it to NetworkClient.spawned too. + if (NetworkServer.spawned.TryGetValue(message.netId, out NetworkIdentity identity) && identity != null) + { + spawned[message.netId] = identity; + if (message.isOwner) connection.owned.Add(identity); + + // now do the actual 'spawning' on host mode + if (message.isLocalPlayer) + InternalAddPlayer(identity); + + // set visibility before invoking OnStartClient etc. callbacks + if (aoi != null) + aoi.SetHostVisibility(identity, true); + + identity.isOwned = message.isOwner; + BootstrapIdentity(identity); + } + } + + // client-only mode callbacks ////////////////////////////////////////// + static void OnEntityStateMessage(EntityStateMessage message) + { + // Debug.Log($"NetworkClient.OnUpdateVarsMessage {msg.netId}"); + if (spawned.TryGetValue(message.netId, out NetworkIdentity identity) && identity != null) + { + using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload)) + identity.DeserializeClient(reader, false); + } + else Debug.LogWarning($"Did not find target for sync message for {message.netId}. Were all prefabs added to the NetworkManager's spawnable list?\nNote: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message."); + } + + static void OnRPCMessage(RpcMessage message) + { + // Debug.Log($"NetworkClient.OnRPCMessage hash:{message.functionHash} netId:{message.netId}"); + if (spawned.TryGetValue(message.netId, out NetworkIdentity identity)) + { + using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload)) + identity.HandleRemoteCall(message.componentIndex, message.functionHash, RemoteCallType.ClientRpc, reader); + } + // Rpcs often can't be applied if interest management unspawned them + } + + static void OnObjectHide(ObjectHideMessage message) => DestroyObject(message.netId); + + internal static void OnObjectDestroy(ObjectDestroyMessage message) => DestroyObject(message.netId); + + internal static void OnSpawn(SpawnMessage message) + { + // Debug.Log($"Client spawn handler instantiating netId={msg.netId} assetID={msg.assetId} sceneId={msg.sceneId:X} pos={msg.position}"); + if (FindOrSpawnObject(message, out NetworkIdentity identity)) + { + ApplySpawnPayload(identity, message); + } + } + + internal static void OnChangeOwner(ChangeOwnerMessage message) + { + NetworkIdentity identity = GetExistingObject(message.netId); + + if (identity != null) + ChangeOwner(identity, message); + else + Debug.LogError($"OnChangeOwner: Could not find object with netId {message.netId}"); + } + + // ChangeOwnerMessage contains new 'owned' and new 'localPlayer' + // that we need to apply to the identity. + internal static void ChangeOwner(NetworkIdentity identity, ChangeOwnerMessage message) + { + // local player before, but not anymore? + // call OnStopLocalPlayer before setting new values. + if (identity.isLocalPlayer && !message.isLocalPlayer) + { + identity.OnStopLocalPlayer(); + } + + // set ownership flag (aka authority) + identity.isOwned = message.isOwner; + + // Add / Remove to client's connectionToServer.owned hashset. + if (identity.isOwned) + connection?.owned.Add(identity); + else + connection?.owned.Remove(identity); + + // Call OnStartAuthority / OnStopAuthority + identity.NotifyAuthority(); + + // set localPlayer flag + identity.isLocalPlayer = message.isLocalPlayer; + + // identity is now local player. set our static helper field to it. + if (identity.isLocalPlayer) + { + localPlayer = identity; + identity.connectionToServer = connection; + identity.OnStartLocalPlayer(); + } + // identity's isLocalPlayer was set to false. + // clear our static localPlayer IF (and only IF) it was that one before. + else if (localPlayer == identity) + { + localPlayer = null; + // TODO set .connectionToServer to null for old local player? + // since we set it in the above 'if' case too. + } + } + + // set up NetworkIdentity flags on the client. + // needs to be separate from invoking callbacks. + // cleaner, and some places need to set flags first. + static void InitializeIdentityFlags(NetworkIdentity identity) + { + // initialize flags before invoking callbacks. + // this way isClient/isLocalPlayer is correct during callbacks. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3362 + identity.isClient = true; + identity.isLocalPlayer = localPlayer == identity; + + // .connectionToServer is only available for local players. + // set it here, before invoking any callbacks. + // this way it's available in _all_ callbacks. + if (identity.isLocalPlayer) + identity.connectionToServer = connection; + } + + // invoke NetworkIdentity callbacks on the client. + // needs to be separate from configuring flags. + // cleaner, and some places need to set flags first. + static void InvokeIdentityCallbacks(NetworkIdentity identity) + { + // invoke OnStartAuthority + identity.NotifyAuthority(); + + // invoke OnStartClient + identity.OnStartClient(); + + // invoke OnStartLocalPlayer + if (identity.isLocalPlayer) + identity.OnStartLocalPlayer(); + } + + // configure flags & invoke callbacks + static void BootstrapIdentity(NetworkIdentity identity) + { + InitializeIdentityFlags(identity); + InvokeIdentityCallbacks(identity); + } + + // broadcast /////////////////////////////////////////////////////////// + static void BroadcastTimeSnapshot() + { + Send(new TimeSnapshotMessage(), Channels.Unreliable); + } + + // make sure Broadcast() is only called every sendInterval. + // calling it every update() would require too much bandwidth. + static void Broadcast() + { + // joined the world yet? + if (!connection.isReady) return; + + // nothing to do in host mode. server already knows the state. + if (NetworkServer.active) return; + + // send time snapshot every sendInterval. + BroadcastTimeSnapshot(); + + // for each entity that the client owns + foreach (NetworkIdentity identity in connection.owned) + { + // make sure it's not null or destroyed. + // (which can happen if someone uses + // GameObject.Destroy instead of + // NetworkServer.Destroy) + if (identity != null) + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + // get serialization for this entity viewed by this connection + // (if anything was serialized this time) + identity.SerializeClient(writer); + if (writer.Position > 0) + { + // send state update message + EntityStateMessage message = new EntityStateMessage + { + netId = identity.netId, + payload = writer.ToArraySegment() + }; + Send(message); + } + } + } + // spawned list should have no null entries because we + // always call Remove in OnObjectDestroy everywhere. + // if it does have null then we missed something. + else Debug.LogWarning($"Found 'null' entry in owned list for client. This is unexpected behaviour."); + } + } + + // update ////////////////////////////////////////////////////////////// + // NetworkEarlyUpdate called before any Update/FixedUpdate + // (we add this to the UnityEngine in NetworkLoop) + internal static void NetworkEarlyUpdate() + { + // process all incoming messages first before updating the world + if (Transport.active != null) + Transport.active.ClientEarlyUpdate(); + + // time snapshot interpolation + UpdateTimeInterpolation(); + } + + // NetworkLateUpdate called after any Update/FixedUpdate/LateUpdate + // (we add this to the UnityEngine in NetworkLoop) + internal static void NetworkLateUpdate() + { + // broadcast ClientToServer components while active + if (active) + { + // broadcast every sendInterval. + // AccurateInterval to avoid update frequency inaccuracy issues: + // https://github.com/vis2k/Mirror/pull/3153 + // + // for example, host mode server doesn't set .targetFrameRate. + // Broadcast() would be called every tick. + // snapshots might be sent way too often, etc. + // + // during tests, we always call Broadcast() though. + // + // also important for syncInterval=0 components like + // NetworkTransform, so they can sync on same interval as time + // snapshots _but_ not every single tick. + // + // Unity 2019 doesn't have Time.timeAsDouble yet + if (!Application.isPlaying || + AccurateInterval.Elapsed(NetworkTime.localTime, sendInterval, ref lastSendTime)) + { + Broadcast(); + } + + UpdateConnectionQuality(); + } + + // Connection Quality ////////////////////////////////////////////////// + // uses 'pragmatic' version based on snapshot interpolation by default. + void UpdateConnectionQuality() + { + // only recalculate every few seconds + // we don't want to fire Good->Bad->Good->Bad dozens of times per second. + if (connectionQualityInterval > 0 && NetworkTime.time > lastConnectionQualityUpdate + connectionQualityInterval) + { + lastConnectionQualityUpdate = NetworkTime.time; + + switch (connectionQualityMethod) + { + case ConnectionQualityMethod.Simple: + connectionQuality = ConnectionQualityHeuristics.Simple(NetworkTime.rtt, NetworkTime.rttVariance); + break; + case ConnectionQualityMethod.Pragmatic: + connectionQuality = ConnectionQualityHeuristics.Pragmatic(initialBufferTime, bufferTime); + break; + } + + if (lastConnectionQuality != connectionQuality) + { + // Invoke the event before assigning the new value so + // the event handler can compare old and new values. + onConnectionQualityChanged?.Invoke(lastConnectionQuality, connectionQuality); + lastConnectionQuality = connectionQuality; + } + } + } + + // update connections to flush out messages _after_ broadcast + // local connection? + if (connection is LocalConnectionToServer localConnection) + { + localConnection.Update(); + } + // remote connection? + else if (connection is NetworkConnectionToServer remoteConnection) + { + // only update things while connected + if (active && connectState == ConnectState.Connected) + { + // update NetworkTime + NetworkTime.UpdateClient(); + + // update connection to flush out batched messages + remoteConnection.Update(); + } + } + + // process all outgoing messages after updating the world + if (Transport.active != null) + Transport.active.ClientLateUpdate(); + } + + // destroy ///////////////////////////////////////////////////////////// + /// Destroys all networked objects on the client. + // Note: NetworkServer.CleanupNetworkIdentities does the same on server. + public static void DestroyAllClientObjects() + { + // user can modify spawned lists which causes InvalidOperationException + // list can modified either in UnSpawnHandler or in OnDisable/OnDestroy + // we need the Try/Catch so that the rest of the shutdown does not get stopped + try + { + foreach (NetworkIdentity identity in spawned.Values) + { + if (identity != null && identity.gameObject != null) + { + if (identity.isLocalPlayer) + identity.OnStopLocalPlayer(); + + identity.OnStopClient(); + + // NetworkClient.Shutdown calls DestroyAllClientObjects. + // which destroys all objects in NetworkClient.spawned. + // => NC.spawned contains owned & observed objects + // => in host mode, we CAN NOT destroy observed objects. + // => that would destroy them other connection's objects + // on the host server, making them disconnect. + // https://github.com/vis2k/Mirror/issues/2954 + bool hostOwned = identity.connectionToServer is LocalConnectionToServer; + bool shouldDestroy = !identity.isServer || hostOwned; + if (shouldDestroy) + { + bool wasUnspawned = InvokeUnSpawnHandler(identity.assetId, identity.gameObject); + + // unspawned objects should be reset for reuse later. + if (wasUnspawned) + { + identity.ResetState(); + } + // without unspawn handler, we need to disable/destroy. + else + { + // scene objects are reset and disabled. + // they always stay in the scene, we don't destroy them. + if (identity.sceneId != 0) + { + identity.ResetState(); + identity.gameObject.SetActive(false); + } + // spawned objects are destroyed + else + { + GameObject.Destroy(identity.gameObject); + } + } + } + } + } + spawned.Clear(); + connection?.owned.Clear(); + } + catch (InvalidOperationException e) + { + Debug.LogException(e); + Debug.LogError("Could not DestroyAllClientObjects because spawned list was modified during loop, make sure you are not modifying NetworkIdentity.spawned by calling NetworkServer.Destroy or NetworkServer.Spawn in OnDestroy or OnDisable."); + } + } + + static void DestroyObject(uint netId) + { + // Debug.Log($"NetworkClient.OnObjDestroy netId: {netId}"); + if (spawned.TryGetValue(netId, out NetworkIdentity identity) && identity != null) + { + if (identity.isLocalPlayer) + identity.OnStopLocalPlayer(); + + identity.OnStopClient(); + + // custom unspawn handler for this prefab? (for prefab pools etc.) + if (InvokeUnSpawnHandler(identity.assetId, identity.gameObject)) + { + // reset object after user's handler + identity.ResetState(); + } + // otherwise fall back to default Destroy + else if (identity.sceneId == 0) + { + // don't call reset before destroy so that values are still set in OnDestroy + GameObject.Destroy(identity.gameObject); + } + // scene object.. disable it in scene instead of destroying + else + { + identity.gameObject.SetActive(false); + spawnableObjects[identity.sceneId] = identity; + // reset for scene objects + identity.ResetState(); + } + + // remove from dictionary no matter how it is unspawned + connection.owned.Remove(identity); // if any + spawned.Remove(netId); + } + //else Debug.LogWarning($"Did not find target for destroy message for {netId}"); + } + + // shutdown //////////////////////////////////////////////////////////// + /// Shutdown the client. + // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + public static void Shutdown() + { + //Debug.Log("Shutting down client."); + + // objects need to be destroyed before spawners are cleared + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3334 + DestroyAllClientObjects(); + + // calls prefabs.Clear(); + // calls spawnHandlers.Clear(); + // calls unspawnHandlers.Clear(); + ClearSpawners(); + + spawned.Clear(); + connection?.owned.Clear(); + handlers.Clear(); + spawnableObjects.Clear(); + + // IMPORTANT: do NOT call NetworkIdentity.ResetStatics() here! + // calling StopClient() in host mode would reset nextNetId to 1, + // causing next connection to have a duplicate netId accidentally. + // => see also: https://github.com/vis2k/Mirror/issues/2954 + //NetworkIdentity.ResetStatics(); + // => instead, reset only the client sided statics. + NetworkIdentity.ResetClientStatics(); + + // disconnect the client connection. + // we do NOT call Transport.Shutdown, because someone only called + // NetworkClient.Shutdown. we can't assume that the server is + // supposed to be shut down too! + if (Transport.active != null) + Transport.active.ClientDisconnect(); + + // reset statics + connectState = ConnectState.None; + connection = null; + localPlayer = null; + ready = false; + isSpawnFinished = false; + isLoadingScene = false; + lastSendTime = 0; + + unbatcher = new Unbatcher(); + + // clear events. someone might have hooked into them before, but + // we don't want to use those hooks after Shutdown anymore. + OnConnectedEvent = null; + OnDisconnectedEvent = null; + OnErrorEvent = null; + } + + // GUI ///////////////////////////////////////////////////////////////// + // called from NetworkManager to display timeline interpolation status. + // useful to indicate catchup / slowdown / dynamic adjustment etc. + public static void OnGUI() + { + // only if in world + if (!ready) return; + + GUILayout.BeginArea(new Rect(10, 5, 1020, 50)); + + GUILayout.BeginHorizontal("Box"); + GUILayout.Label("Snapshot Interp.:"); + // color while catching up / slowing down + if (localTimescale > 1) GUI.color = Color.green; // green traffic light = go fast + else if (localTimescale < 1) GUI.color = Color.red; // red traffic light = go slow + else GUI.color = Color.white; + GUILayout.Box($"timeline: {localTimeline:F2}"); + GUILayout.Box($"buffer: {snapshots.Count}"); + GUILayout.Box($"DriftEMA: {NetworkClient.driftEma.Value:F2}"); + GUILayout.Box($"DelTimeEMA: {NetworkClient.deliveryTimeEma.Value:F2}"); + GUILayout.Box($"timescale: {localTimescale:F2}"); + GUILayout.Box($"BTM: {NetworkClient.bufferTimeMultiplier:F2}"); // current dynamically adjusted multiplier + GUILayout.Box($"RTT: {NetworkTime.rtt * 1000:F0}ms"); + GUILayout.Box($"PredErrUNADJ: {NetworkTime.predictionErrorUnadjusted * 1000:F0}ms"); + GUILayout.Box($"PredErrADJ: {NetworkTime.predictionErrorAdjusted * 1000:F0}ms"); + GUILayout.EndHorizontal(); + + GUILayout.EndArea(); + } + } +} diff --git a/Assets/Mirror/Core/NetworkClient.cs.meta b/Assets/Mirror/Core/NetworkClient.cs.meta new file mode 100644 index 0000000..20cb211 --- /dev/null +++ b/Assets/Mirror/Core/NetworkClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: abe6be14204d94224a3e7cd99dd2ea73 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs b/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs new file mode 100644 index 0000000..8d28859 --- /dev/null +++ b/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + public static partial class NetworkClient + { + // snapshot interpolation settings ///////////////////////////////////// + // TODO expose the settings to the user later. + // via NetMan or NetworkClientConfig or NetworkClient as component etc. + public static SnapshotInterpolationSettings snapshotSettings = new SnapshotInterpolationSettings(); + + // snapshot interpolation runtime data ///////////////////////////////// + // buffer time is dynamically adjusted. + // store the current multiplier here, without touching the original in settings. + // this way we can easily reset to or compare with original where needed. + public static double bufferTimeMultiplier; + + // original buffer time based on the settings + // dynamically adjusted buffer time based on dynamically adjusted multiplier + public static double initialBufferTime => NetworkServer.sendInterval * snapshotSettings.bufferTimeMultiplier; + public static double bufferTime => NetworkServer.sendInterval * bufferTimeMultiplier; + + // + public static SortedList snapshots = new SortedList(); + + // for smooth interpolation, we need to interpolate along server time. + // any other time (arrival on client, client local time, etc.) is not + // going to give smooth results. + // in other words, this is the remote server's time, but adjusted. + // + // internal for use from NetworkTime. + // double for long running servers, see NetworkTime comments. + internal static double localTimeline; + + // catchup / slowdown adjustments are applied to timescale, + // to be adjusted in every update instead of when receiving messages. + internal static double localTimescale = 1; + + // catchup ///////////////////////////////////////////////////////////// + + + // we use EMA to average the last second worth of snapshot time diffs. + // manually averaging the last second worth of values with a for loop + // would be the same, but a moving average is faster because we only + // ever add one value. + static ExponentialMovingAverage driftEma; + + // dynamic buffer time adjustment ////////////////////////////////////// + // dynamically adjusts bufferTimeMultiplier for smooth results. + // to understand how this works, try this manually: + // + // - disable dynamic adjustment + // - set jitter = 0.2 (20% is a lot!) + // - notice some stuttering + // - disable interpolation to see just how much jitter this really is(!) + // - enable interpolation again + // - manually increase bufferTimeMultiplier to 3-4 + // ... the cube slows down (blue) until it's smooth + // - with dynamic adjustment enabled, it will set 4 automatically + // ... the cube slows down (blue) until it's smooth as well + // + // note that 20% jitter is extreme. + // for this to be perfectly smooth, set the safety tolerance to '2'. + // but realistically this is not necessary, and '1' is enough. + [Header("Snapshot Interpolation: Dynamic Adjustment")] + [Tooltip("Automatically adjust bufferTimeMultiplier for smooth results.\nSets a low multiplier on stable connections, and a high multiplier on jittery connections.")] + public static bool dynamicAdjustment = true; + + [Tooltip("Safety buffer that is always added to the dynamic bufferTimeMultiplier adjustment.")] + public static float dynamicAdjustmentTolerance = 1; // 1 is realistically just fine, 2 is very very safe even for 20% jitter. can be half a frame too. (see above comments) + + [Tooltip("Dynamic adjustment is computed over n-second exponential moving average standard deviation.")] + public static int deliveryTimeEmaDuration = 2; // 1-2s recommended to capture average delivery time + static ExponentialMovingAverage deliveryTimeEma; // average delivery time (standard deviation gives average jitter) + + // OnValidate: see NetworkClient.cs + // add snapshot & initialize client interpolation time if needed + + // initialization called from Awake + static void InitTimeInterpolation() + { + // reset timeline, localTimescale & snapshots from last session (if any) + bufferTimeMultiplier = snapshotSettings.bufferTimeMultiplier; + localTimeline = 0; + localTimescale = 1; + snapshots.Clear(); + + // initialize EMA with 'emaDuration' seconds worth of history. + // 1 second holds 'sendRate' worth of values. + // multiplied by emaDuration gives n-seconds. + driftEma = new ExponentialMovingAverage(NetworkServer.sendRate * snapshotSettings.driftEmaDuration); + deliveryTimeEma = new ExponentialMovingAverage(NetworkServer.sendRate * snapshotSettings.deliveryTimeEmaDuration); + } + + // server sends TimeSnapshotMessage every sendInterval. + // batching already includes the remoteTimestamp. + // we simply insert it on-message here. + // => only for reliable channel. unreliable would always arrive earlier. + static void OnTimeSnapshotMessage(TimeSnapshotMessage _) + { + // insert another snapshot for snapshot interpolation. + // before calling OnDeserialize so components can use + // NetworkTime.time and NetworkTime.timeStamp. + + // Unity 2019 doesn't have Time.timeAsDouble yet + OnTimeSnapshot(new TimeSnapshot(connection.remoteTimeStamp, NetworkTime.localTime)); + } + + // see comments at the top of this file + public static void OnTimeSnapshot(TimeSnapshot snap) + { + // Debug.Log($"NetworkClient: OnTimeSnapshot @ {snap.remoteTime:F3}"); + + // (optional) dynamic adjustment + if (snapshotSettings.dynamicAdjustment) + { + // set bufferTime on the fly. + // shows in inspector for easier debugging :) + bufferTimeMultiplier = SnapshotInterpolation.DynamicAdjustment( + NetworkServer.sendInterval, + deliveryTimeEma.StandardDeviation, + snapshotSettings.dynamicAdjustmentTolerance + ); + } + + // insert into the buffer & initialize / adjust / catchup + SnapshotInterpolation.InsertAndAdjust( + snapshots, + snapshotSettings.bufferLimit, + snap, + ref localTimeline, + ref localTimescale, + NetworkServer.sendInterval, + bufferTime, + snapshotSettings.catchupSpeed, + snapshotSettings.slowdownSpeed, + ref driftEma, + snapshotSettings.catchupNegativeThreshold, + snapshotSettings.catchupPositiveThreshold, + ref deliveryTimeEma); + + // Debug.Log($"inserted TimeSnapshot remote={snap.remoteTime:F2} local={snap.localTime:F2} total={snapshots.Count}"); + } + + // call this from early update, so the timeline is safe to use in update + static void UpdateTimeInterpolation() + { + // only while we have snapshots. + // timeline starts when the first snapshot arrives. + if (snapshots.Count > 0) + { + // progress local timeline. + // NetworkTime uses unscaled time and ignores Time.timeScale. + // fixes Time.timeScale getting server & client time out of sync: + // https://github.com/MirrorNetworking/Mirror/issues/3409 + SnapshotInterpolation.StepTime(Time.unscaledDeltaTime, ref localTimeline, localTimescale); + + // progress local interpolation. + // TimeSnapshot doesn't interpolate anything. + // this is merely to keep removing older snapshots. + SnapshotInterpolation.StepInterpolation(snapshots, localTimeline, out _, out _, out double t); + // Debug.Log($"NetworkClient SnapshotInterpolation @ {localTimeline:F2} t={t:F2}"); + } + } + } +} diff --git a/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs.meta b/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs.meta new file mode 100644 index 0000000..3c52ae1 --- /dev/null +++ b/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ad039071a9cc487b9f7831d28bbe8e83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkConnection.cs b/Assets/Mirror/Core/NetworkConnection.cs new file mode 100644 index 0000000..6317eca --- /dev/null +++ b/Assets/Mirror/Core/NetworkConnection.cs @@ -0,0 +1,207 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Mirror +{ + /// Base NetworkConnection class for server-to-client and client-to-server connection. + public abstract class NetworkConnection + { + public const int LocalConnectionId = 0; + + /// Unique identifier for this connection that is assigned by the transport layer. + // assigned by transport, this id is unique for every connection on server. + // clients don't know their own id and they don't know other client's ids. + public readonly int connectionId; + + /// Flag that indicates the client has been authenticated. + public bool isAuthenticated; + + /// General purpose object to hold authentication data, character selection, tokens, etc. + public object authenticationData; + + /// A server connection is ready after joining the game world. + // TODO move this to ConnectionToClient so the flag only lives on server + // connections? clients could use NetworkClient.ready to avoid redundant + // state. + public bool isReady; + + /// Last time a message was received for this connection. Includes system and user messages. + public float lastMessageTime; + + /// This connection's main object (usually the player object). + public NetworkIdentity identity { get; internal set; } + + /// All NetworkIdentities owned by this connection. Can be main player, pets, etc. + // .owned is now valid both on server and on client. + // IMPORTANT: this needs to be , not . + // fixes a bug where DestroyOwnedObjects wouldn't find the + // netId anymore: https://github.com/vis2k/Mirror/issues/1380 + // Works fine with NetworkIdentity pointers though. + public readonly HashSet owned = new HashSet(); + + // batching from server to client & client to server. + // fewer transport calls give us significantly better performance/scale. + // + // for a 64KB max message transport and 64 bytes/message on average, we + // reduce transport calls by a factor of 1000. + // + // depending on the transport, this can give 10x performance. + // + // Dictionary because we have multiple channels. + protected Dictionary batches = new Dictionary(); + + /// last batch's remote timestamp. not interpolated. useful for NetworkTransform etc. + // for any given NetworkMessage/Rpc/Cmd/OnSerialize, this was the time + // on the REMOTE END when it was sent. + // + // NOTE: this is NOT in NetworkTime, it needs to be per-connection + // because the server receives different batch timestamps from + // different connections. + public double remoteTimeStamp { get; internal set; } + + internal NetworkConnection() + { + // set lastTime to current time when creating connection to make + // sure it isn't instantly kicked for inactivity + lastMessageTime = Time.time; + } + + internal NetworkConnection(int networkConnectionId) : this() + { + connectionId = networkConnectionId; + } + + // TODO if we only have Reliable/Unreliable, then we could initialize + // two batches and avoid this code + protected Batcher GetBatchForChannelId(int channelId) + { + // get existing or create new writer for the channelId + Batcher batch; + if (!batches.TryGetValue(channelId, out batch)) + { + // get max batch size for this channel + int threshold = Transport.active.GetBatchThreshold(channelId); + + // create batcher + batch = new Batcher(threshold); + batches[channelId] = batch; + } + return batch; + } + + // Send stage one: NetworkMessage + /// Send a NetworkMessage to this connection over the given channel. + public void Send(T message, int channelId = Channels.Reliable) + where T : struct, NetworkMessage + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + // pack message + NetworkMessages.Pack(message, writer); + + // validate packet size immediately. + // we know how much can fit into one batch at max. + // if it's larger, log an error immediately with the type . + // previously we only logged in Update() when processing batches, + // but there we don't have type information anymore. + int max = NetworkMessages.MaxMessageSize(channelId); + if (writer.Position > max) + { + Debug.LogError($"NetworkConnection.Send: message of type {typeof(T)} with a size of {writer.Position} bytes is larger than the max allowed message size in one batch: {max}.\nThe message was dropped, please make it smaller."); + return; + } + + // send allocation free + NetworkDiagnostics.OnSend(message, channelId, writer.Position, 1); + Send(writer.ToArraySegment(), channelId); + } + } + + // Send stage two: serialized NetworkMessage as ArraySegment + // internal because no one except Mirror should send bytes directly to + // the client. they would be detected as a message. send messages instead. + // => make sure to validate message size before calling Send! + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal virtual void Send(ArraySegment segment, int channelId = Channels.Reliable) + { + //Debug.Log($"ConnectionSend {this} bytes:{BitConverter.ToString(segment.Array, segment.Offset, segment.Count)}"); + + // add to batch no matter what. + // batching will try to fit as many as possible into MTU. + // but we still allow > MTU, e.g. kcp max packet size 144kb. + // those are simply sent as single batches. + // + // IMPORTANT: do NOT send > batch sized messages directly: + // - data race: large messages would be sent directly. small + // messages would be sent in the batch at the end of frame + // - timestamps: if batching assumes a timestamp, then large + // messages need that too. + // + // NOTE: we ALWAYS batch. it's not optional, because the + // receiver needs timestamps for NT etc. + // + // NOTE: we do NOT ValidatePacketSize here yet. the final packet + // will be the full batch, including timestamp. + GetBatchForChannelId(channelId).AddMessage(segment, NetworkTime.localTime); + } + + // Send stage three: hand off to transport + protected abstract void SendToTransport(ArraySegment segment, int channelId = Channels.Reliable); + + // flush batched messages at the end of every Update. + internal virtual void Update() + { + // go through batches for all channels + // foreach ((int key, Batcher batcher) in batches) // Unity 2020 doesn't support deconstruct yet + foreach (KeyValuePair kvp in batches) + { + // make and send as many batches as necessary from the stored + // messages. + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + // make a batch with our local time (double precision) + while (kvp.Value.GetBatch(writer)) + { + // message size is validated in Send, with test coverage. + // we can send directly without checking again. + ArraySegment segment = writer.ToArraySegment(); + + // send to transport + SendToTransport(segment, kvp.Key); + //UnityEngine.Debug.Log($"sending batch of {writer.Position} bytes for channel={kvp.Key} connId={connectionId}"); + + // reset writer for each new batch + writer.Position = 0; + } + } + } + } + + /// Check if we received a message within the last 'timeout' seconds. + internal virtual bool IsAlive(float timeout) => Time.time - lastMessageTime < timeout; + + /// Disconnects this connection. + // for future reference, here is how Disconnects work in Mirror. + // + // first, there are two types of disconnects: + // * voluntary: the other end simply disconnected + // * involuntary: server disconnects a client by itself + // + // UNET had special (complex) code to handle both cases differently. + // + // Mirror handles both cases the same way: + // * Disconnect is called from TOP to BOTTOM + // NetworkServer/Client -> NetworkConnection -> Transport.Disconnect() + // * Disconnect is handled from BOTTOM to TOP + // Transport.OnDisconnected -> ... + // + // in other words, calling Disconnect() does no cleanup whatsoever. + // it simply asks the transport to disconnect. + // then later the transport events will do the clean up. + public abstract void Disconnect(); + + public override string ToString() => $"connection({connectionId})"; + } +} diff --git a/Assets/Mirror/Core/NetworkConnection.cs.meta b/Assets/Mirror/Core/NetworkConnection.cs.meta new file mode 100644 index 0000000..32c4ba2 --- /dev/null +++ b/Assets/Mirror/Core/NetworkConnection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11ea41db366624109af1f0834bcdde2f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkConnectionToClient.cs b/Assets/Mirror/Core/NetworkConnectionToClient.cs new file mode 100644 index 0000000..361b00c --- /dev/null +++ b/Assets/Mirror/Core/NetworkConnectionToClient.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Mirror +{ + public class NetworkConnectionToClient : NetworkConnection + { + // rpcs are collected in a buffer, and then flushed out together. + // this way we don't need one NetworkMessage per rpc. + // => prepares for LocalWorldState as well. + // ensure max size when adding! + readonly NetworkWriter reliableRpcs = new NetworkWriter(); + readonly NetworkWriter unreliableRpcs = new NetworkWriter(); + + public virtual string address => Transport.active.ServerGetClientAddress(connectionId); + + /// NetworkIdentities that this connection can see + // TODO move to server's NetworkConnectionToClient? + public readonly HashSet observing = new HashSet(); + + // unbatcher + public Unbatcher unbatcher = new Unbatcher(); + + // server runs a time snapshot interpolation for each client's local time. + // this is necessary for client auth movement to still be smooth on the + // server for host mode. + // TODO move them along server's timeline in the future. + // perhaps with an offset. + // for now, keep compatibility by manually constructing a timeline. + ExponentialMovingAverage driftEma; + ExponentialMovingAverage deliveryTimeEma; // average delivery time (standard deviation gives average jitter) + public double remoteTimeline; + public double remoteTimescale; + double bufferTimeMultiplier = 2; + double bufferTime => NetworkServer.sendInterval * bufferTimeMultiplier; + + // + readonly SortedList snapshots = new SortedList(); + + // Snapshot Buffer size limit to avoid ever growing list memory consumption attacks from clients. + public int snapshotBufferSizeLimit = 64; + + // ping for rtt (round trip time) + // useful for statistics, lag compensation, etc. + double lastPingTime = 0; + internal ExponentialMovingAverage _rtt = new ExponentialMovingAverage(NetworkTime.PingWindowSize); + + /// Round trip time (in seconds) that it takes a message to go server->client->server. + public double rtt => _rtt.Value; + + public NetworkConnectionToClient(int networkConnectionId) + : base(networkConnectionId) + { + // initialize EMA with 'emaDuration' seconds worth of history. + // 1 second holds 'sendRate' worth of values. + // multiplied by emaDuration gives n-seconds. + driftEma = new ExponentialMovingAverage(NetworkServer.sendRate * NetworkClient.snapshotSettings.driftEmaDuration); + deliveryTimeEma = new ExponentialMovingAverage(NetworkServer.sendRate * NetworkClient.snapshotSettings.deliveryTimeEmaDuration); + + // buffer limit should be at least multiplier to have enough in there + snapshotBufferSizeLimit = Mathf.Max((int)NetworkClient.snapshotSettings.bufferTimeMultiplier, snapshotBufferSizeLimit); + } + + public void OnTimeSnapshot(TimeSnapshot snapshot) + { + // protect against ever growing buffer size attacks + if (snapshots.Count >= snapshotBufferSizeLimit) return; + + // (optional) dynamic adjustment + if (NetworkClient.snapshotSettings.dynamicAdjustment) + { + // set bufferTime on the fly. + // shows in inspector for easier debugging :) + bufferTimeMultiplier = SnapshotInterpolation.DynamicAdjustment( + NetworkServer.sendInterval, + deliveryTimeEma.StandardDeviation, + NetworkClient.snapshotSettings.dynamicAdjustmentTolerance + ); + // Debug.Log($"[Server]: {name} delivery std={serverDeliveryTimeEma.StandardDeviation} bufferTimeMult := {bufferTimeMultiplier} "); + } + + // insert into the server buffer & initialize / adjust / catchup + SnapshotInterpolation.InsertAndAdjust( + snapshots, + NetworkClient.snapshotSettings.bufferLimit, + snapshot, + ref remoteTimeline, + ref remoteTimescale, + NetworkServer.sendInterval, + bufferTime, + NetworkClient.snapshotSettings.catchupSpeed, + NetworkClient.snapshotSettings.slowdownSpeed, + ref driftEma, + NetworkClient.snapshotSettings.catchupNegativeThreshold, + NetworkClient.snapshotSettings.catchupPositiveThreshold, + ref deliveryTimeEma + ); + } + + public void UpdateTimeInterpolation() + { + // timeline starts when the first snapshot arrives. + if (snapshots.Count > 0) + { + // progress local timeline. + SnapshotInterpolation.StepTime(Time.unscaledDeltaTime, ref remoteTimeline, remoteTimescale); + + // progress local interpolation. + // TimeSnapshot doesn't interpolate anything. + // this is merely to keep removing older snapshots. + SnapshotInterpolation.StepInterpolation(snapshots, remoteTimeline, out _, out _, out _); + // Debug.Log($"NetworkClient SnapshotInterpolation @ {localTimeline:F2} t={t:F2}"); + } + } + + // Send stage three: hand off to transport + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override void SendToTransport(ArraySegment segment, int channelId = Channels.Reliable) => + Transport.active.ServerSend(connectionId, segment, channelId); + + protected virtual void UpdatePing() + { + // localTime (double) instead of Time.time for accuracy over days + if (NetworkTime.localTime >= lastPingTime + NetworkTime.PingInterval) + { + // TODO it would be safer for the server to store the last N + // messages' timestamp and only send a message number. + // This way client's can't just modify the timestamp. + // predictedTime parameter is 0 because the server doesn't predict. + NetworkPingMessage pingMessage = new NetworkPingMessage(NetworkTime.localTime, 0); + Send(pingMessage, Channels.Unreliable); + lastPingTime = NetworkTime.localTime; + } + } + + internal override void Update() + { + UpdatePing(); + base.Update(); + } + + /// Disconnects this connection. + public override void Disconnect() + { + // set not ready and handle clientscene disconnect in any case + // (might be client or host mode here) + isReady = false; + reliableRpcs.Position = 0; + unreliableRpcs.Position = 0; + Transport.active.ServerDisconnect(connectionId); + + // IMPORTANT: NetworkConnection.Disconnect() is NOT called for + // voluntary disconnects from the other end. + // -> so all 'on disconnect' cleanup code needs to be in + // OnTransportDisconnect, where it's called for both voluntary + // and involuntary disconnects! + } + + internal void AddToObserving(NetworkIdentity netIdentity) + { + observing.Add(netIdentity); + + // spawn identity for this conn + NetworkServer.ShowForConnection(netIdentity, this); + } + + internal void RemoveFromObserving(NetworkIdentity netIdentity, bool isDestroyed) + { + observing.Remove(netIdentity); + + if (!isDestroyed) + { + // hide identity for this conn + NetworkServer.HideForConnection(netIdentity, this); + } + } + + internal void RemoveFromObservingsObservers() + { + foreach (NetworkIdentity netIdentity in observing) + { + netIdentity.RemoveObserver(this); + } + observing.Clear(); + } + + internal void AddOwnedObject(NetworkIdentity obj) + { + owned.Add(obj); + } + + internal void RemoveOwnedObject(NetworkIdentity obj) + { + owned.Remove(obj); + } + + internal void DestroyOwnedObjects() + { + // create a copy because the list might be modified when destroying + HashSet tmp = new HashSet(owned); + foreach (NetworkIdentity netIdentity in tmp) + { + if (netIdentity != null) + { + // unspawn scene objects, destroy instantiated objects. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3538 + if (netIdentity.sceneId != 0) + NetworkServer.UnSpawn(netIdentity.gameObject); + else + NetworkServer.Destroy(netIdentity.gameObject); + } + } + + // clear the hashset because we destroyed them all + owned.Clear(); + } + } +} diff --git a/Assets/Mirror/Core/NetworkConnectionToClient.cs.meta b/Assets/Mirror/Core/NetworkConnectionToClient.cs.meta new file mode 100644 index 0000000..6001a71 --- /dev/null +++ b/Assets/Mirror/Core/NetworkConnectionToClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb2195f8b29d24f0680a57fde2e9fd09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkConnectionToServer.cs b/Assets/Mirror/Core/NetworkConnectionToServer.cs new file mode 100644 index 0000000..496813d --- /dev/null +++ b/Assets/Mirror/Core/NetworkConnectionToServer.cs @@ -0,0 +1,24 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public class NetworkConnectionToServer : NetworkConnection + { + // Send stage three: hand off to transport + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override void SendToTransport(ArraySegment segment, int channelId = Channels.Reliable) => + Transport.active.ClientSend(segment, channelId); + + /// Disconnects this connection. + public override void Disconnect() + { + // set not ready and handle clientscene disconnect in any case + // (might be client or host mode here) + // TODO remove redundant state. have one source of truth for .ready! + isReady = false; + NetworkClient.ready = false; + Transport.active.ClientDisconnect(); + } + } +} diff --git a/Assets/Mirror/Core/NetworkConnectionToServer.cs.meta b/Assets/Mirror/Core/NetworkConnectionToServer.cs.meta new file mode 100644 index 0000000..3424b58 --- /dev/null +++ b/Assets/Mirror/Core/NetworkConnectionToServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 761977cbf38a34ded9dd89de45445675 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkDiagnostics.cs b/Assets/Mirror/Core/NetworkDiagnostics.cs new file mode 100644 index 0000000..1cdc96f --- /dev/null +++ b/Assets/Mirror/Core/NetworkDiagnostics.cs @@ -0,0 +1,63 @@ +using System; + +namespace Mirror +{ + /// Profiling statistics for tool to subscribe to (profiler etc.) + public static class NetworkDiagnostics + { + /// Describes an outgoing message + public readonly struct MessageInfo + { + /// The message being sent + public readonly NetworkMessage message; + /// channel through which the message was sent + public readonly int channel; + /// how big was the message (does not include transport headers) + public readonly int bytes; + /// How many connections was the message sent to. + public readonly int count; + + internal MessageInfo(NetworkMessage message, int channel, int bytes, int count) + { + this.message = message; + this.channel = channel; + this.bytes = bytes; + this.count = count; + } + } + + /// Event for when Mirror sends a message. Can be subscribed to. + public static event Action OutMessageEvent; + + /// Event for when Mirror receives a message. Can be subscribed to. + public static event Action InMessageEvent; + + // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload + [UnityEngine.RuntimeInitializeOnLoadMethod] + static void ResetStatics() + { + InMessageEvent = null; + OutMessageEvent = null; + } + + internal static void OnSend(T message, int channel, int bytes, int count) + where T : struct, NetworkMessage + { + if (count > 0 && OutMessageEvent != null) + { + MessageInfo outMessage = new MessageInfo(message, channel, bytes, count); + OutMessageEvent?.Invoke(outMessage); + } + } + + internal static void OnReceive(T message, int channel, int bytes) + where T : struct, NetworkMessage + { + if (InMessageEvent != null) + { + MessageInfo inMessage = new MessageInfo(message, channel, bytes, 1); + InMessageEvent?.Invoke(inMessage); + } + } + } +} diff --git a/Assets/Mirror/Core/NetworkDiagnostics.cs.meta b/Assets/Mirror/Core/NetworkDiagnostics.cs.meta new file mode 100644 index 0000000..fe37316 --- /dev/null +++ b/Assets/Mirror/Core/NetworkDiagnostics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c3754b39e5f8740fd93f3337b2c4274e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkIdentity.cs b/Assets/Mirror/Core/NetworkIdentity.cs new file mode 100644 index 0000000..aed8251 --- /dev/null +++ b/Assets/Mirror/Core/NetworkIdentity.cs @@ -0,0 +1,1390 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using Mirror.RemoteCalls; +using UnityEngine; +using UnityEngine.Serialization; + +#if UNITY_EDITOR +using UnityEditor; + +#if UNITY_2021_2_OR_NEWER +using UnityEditor.SceneManagement; +#else +using UnityEditor.Experimental.SceneManagement; +#endif +#endif + +namespace Mirror +{ + // Default = use interest management + // ForceHidden = useful to hide monsters while they respawn etc. + // ForceShown = useful to have score NetworkIdentities that always broadcast + // to everyone etc. + public enum Visibility { Default, ForceHidden, ForceShown } + + public struct NetworkIdentitySerialization + { + // IMPORTANT: int tick avoids floating point inaccuracy over days/weeks + public int tick; + public NetworkWriter ownerWriter; + public NetworkWriter observersWriter; + } + + /// NetworkIdentity identifies objects across the network. + [DisallowMultipleComponent] + // NetworkIdentity.Awake initializes all NetworkComponents. + // let's make sure it's always called before their Awake's. + [DefaultExecutionOrder(-1)] + [AddComponentMenu("Network/Network Identity")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-identity")] + public sealed class NetworkIdentity : MonoBehaviour + { + /// Returns true if running as a client and this object was spawned by a server. + // + // IMPORTANT: + // OnStartClient sets it to true. we NEVER set it to false after. + // otherwise components like Skillbars couldn't use OnDestroy() + // for saving, etc. since isClient may have been reset before + // OnDestroy was called. + // + // we also DO NOT make it dependent on NetworkClient.active or similar. + // we set it, then never change it. that's the user's expectation too. + // + // => fixes https://github.com/vis2k/Mirror/issues/1475 + public bool isClient { get; internal set; } + + /// Returns true if NetworkServer.active and server is not stopped. + // + // IMPORTANT: + // OnStartServer sets it to true. we NEVER set it to false after. + // otherwise components like Skillbars couldn't use OnDestroy() + // for saving, etc. since isServer may have been reset before + // OnDestroy was called. + // + // we also DO NOT make it dependent on NetworkServer.active or similar. + // we set it, then never change it. that's the user's expectation too. + // + // => fixes https://github.com/vis2k/Mirror/issues/1484 + // => fixes https://github.com/vis2k/Mirror/issues/2533 + public bool isServer { get; internal set; } + + /// Return true if this object represents the player on the local machine. + // + // IMPORTANT: + // OnStartLocalPlayer sets it to true. we NEVER set it to false after. + // otherwise components like Skillbars couldn't use OnDestroy() + // for saving, etc. since isLocalPlayer may have been reset before + // OnDestroy was called. + // + // we also DO NOT make it dependent on NetworkClient.localPlayer or similar. + // we set it, then never change it. that's the user's expectation too. + // + // => fixes https://github.com/vis2k/Mirror/issues/2615 + public bool isLocalPlayer { get; internal set; } + + /// True if this object only exists on the server + public bool isServerOnly => isServer && !isClient; + + /// True if this object exists on a client that is not also acting as a server. + public bool isClientOnly => isClient && !isServer; + + /// isOwned is true on the client if this NetworkIdentity is one of the .owned entities of our connection on the server. + // for example: main player & pets are owned. monsters & npcs aren't. + public bool isOwned { get; internal set; } + + // internal so NetworkManager can reset it from StopClient. + internal bool clientStarted; + + /// The set of network connections (players) that can see this object. + public readonly Dictionary observers = + new Dictionary(); + + /// The unique network Id of this object (unique at runtime). + public uint netId { get; internal set; } + + /// Unique identifier for NetworkIdentity objects within a scene, used for spawning scene objects. + // persistent scene id (see AssignSceneID comments) + [FormerlySerializedAs("m_SceneId"), HideInInspector] + public ulong sceneId; + + // assetId used to spawn prefabs across the network. + // originally a Guid, but a 4 byte uint is sufficient + // (as suggested by james) + // + // it's also easier to work with for serialization etc. + // serialized and visible in inspector for easier debugging + [SerializeField, HideInInspector] uint _assetId; + + // The AssetId trick: + // Ideally we would have a serialized 'Guid m_AssetId' but Unity can't + // serialize it because Guid's internal bytes are private + // + // Using just the Guid string would work, but it's 32 chars long and + // would then be sent over the network as 64 instead of 16 bytes + // + // => The solution is to serialize the string internally here and then + // use the real 'Guid' type for everything else via .assetId + public uint assetId + { + get + { +#if UNITY_EDITOR + // old UNET comment: + // This is important because sometimes OnValidate does not run + // (like when adding NetworkIdentity to prefab with no child links) + if (_assetId == 0) + SetupIDs(); +#endif + return _assetId; + } + // assetId is set internally when creating or duplicating a prefab + internal set + { + // should never be empty + if (value == 0) + { + Debug.LogError($"Can not set AssetId to empty guid on NetworkIdentity '{name}', old assetId '{_assetId}'"); + return; + } + + // always set it otherwise. + // for new prefabs, it will set from 0 to N. + // for duplicated prefabs, it will set from N to M. + // either way, it's always set to a valid GUID. + _assetId = value; + // Debug.Log($"Setting AssetId on NetworkIdentity '{name}', new assetId '{value:X4}'"); + } + } + + /// Make this object only exist when the game is running as a server (or host). + [FormerlySerializedAs("m_ServerOnly")] + [Tooltip("Prevents this object from being spawned / enabled on clients")] + public bool serverOnly; + + // Set before Destroy is called so that OnDestroy doesn't try to destroy + // the object again + internal bool destroyCalled; + + /// Client's network connection to the server. This is only valid for player objects on the client. + // TODO change to NetworkConnectionToServer, but might cause some breaking + public NetworkConnection connectionToServer { get; internal set; } + + /// Server's network connection to the client. This is only valid for client-owned objects (including the Player object) on the server. + public NetworkConnectionToClient connectionToClient + { + get => _connectionToClient; + internal set + { + _connectionToClient?.RemoveOwnedObject(this); + _connectionToClient = value; + _connectionToClient?.AddOwnedObject(this); + } + } + NetworkConnectionToClient _connectionToClient; + + // get all NetworkBehaviour components + public NetworkBehaviour[] NetworkBehaviours { get; private set; } + + // to save bandwidth, we send one 64 bit dirty mask + // instead of 1 byte index per dirty component. + // which means we can't allow > 64 components (it's enough). + const int MaxNetworkBehaviours = 64; + + // current visibility + // + // Default = use interest management + // ForceHidden = useful to hide monsters while they respawn etc. + // ForceShown = useful to have score NetworkIdentities that always broadcast + // to everyone etc. + [Tooltip("Visibility can overwrite interest management. ForceHidden can be useful to hide monsters while they respawn. ForceShown can be useful for score NetworkIdentities that should always broadcast to everyone in the world.")] + [FormerlySerializedAs("visible")] + public Visibility visibility = Visibility.Default; + + // Deprecated 2024-01-21 + [HideInInspector] + [Obsolete("Deprecated - Use .visibility instead. This will be removed soon.")] + public Visibility visible + { + get => visibility; + set => visibility = value; + } + + // broadcasting serializes all entities around a player for each player. + // we don't want to serialize one entity twice in the same tick. + // so we cache the last serialization and remember the timestamp so we + // know which Update it was serialized. + // (timestamp is the same while inside Update) + // => this way we don't need to pool thousands of writers either. + // => way easier to store them per object + NetworkIdentitySerialization lastSerialization = new NetworkIdentitySerialization + { + ownerWriter = new NetworkWriter(), + observersWriter = new NetworkWriter() + }; + + // Keep track of all sceneIds to detect scene duplicates + static readonly Dictionary sceneIds = + new Dictionary(); + + // Helper function to handle Command/Rpc + internal void HandleRemoteCall(byte componentIndex, ushort functionHash, RemoteCallType remoteCallType, NetworkReader reader, NetworkConnectionToClient senderConnection = null) + { + // check if unity object has been destroyed + if (this == null) + { + Debug.LogWarning($"{remoteCallType} [{functionHash}] received for deleted object [netId={netId}]"); + return; + } + + // find the right component to invoke the function on + if (componentIndex >= NetworkBehaviours.Length) + { + Debug.LogWarning($"Component [{componentIndex}] not found for [netId={netId}]"); + return; + } + + NetworkBehaviour invokeComponent = NetworkBehaviours[componentIndex]; + if (!RemoteProcedureCalls.Invoke(functionHash, remoteCallType, reader, invokeComponent, senderConnection)) + { + Debug.LogError($"Found no receiver for incoming {remoteCallType} [{functionHash}] on {gameObject.name}, the server and client should have the same NetworkBehaviour instances [netId={netId}]."); + } + } + + // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload + // internal so it can be called from NetworkServer & NetworkClient + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + internal static void ResetStatics() + { + // reset ALL statics + ResetClientStatics(); + ResetServerStatics(); + } + + // reset only client sided statics. + // don't touch server statics when calling StopClient in host mode. + // https://github.com/vis2k/Mirror/issues/2954 + internal static void ResetClientStatics() + { + previousLocalPlayer = null; + clientAuthorityCallback = null; + } + + internal static void ResetServerStatics() + { + nextNetworkId = 1; + } + + /// Gets the NetworkIdentity from the sceneIds dictionary with the corresponding id + public static NetworkIdentity GetSceneIdentity(ulong id) => sceneIds[id]; + + static uint nextNetworkId = 1; + internal static uint GetNextNetworkId() => nextNetworkId++; + + /// Resets nextNetworkId = 1 + public static void ResetNextNetworkId() => nextNetworkId = 1; + + /// The delegate type for the clientAuthorityCallback. + public delegate void ClientAuthorityCallback(NetworkConnectionToClient conn, NetworkIdentity identity, bool authorityState); + + /// A callback that can be populated to be notified when the client-authority state of objects changes. + public static event ClientAuthorityCallback clientAuthorityCallback; + + // hasSpawned should always be false before runtime + [SerializeField, HideInInspector] bool hasSpawned; + public bool SpawnedFromInstantiate { get; private set; } + + // NetworkBehaviour components are initialized in Awake once. + // Changing them at runtime would get client & server out of sync. + // BUT internal so tests can add them after creating the NetworkIdentity + internal void InitializeNetworkBehaviours() + { + // Get all NetworkBehaviour components, including children. + // Some users need NetworkTransform on child bones, etc. + // => Deterministic: https://forum.unity.com/threads/getcomponentsinchildren.4582/#post-33983 + // => Never null. GetComponents returns [] if none found. + // => Include inactive. We need all child components. + NetworkBehaviours = GetComponentsInChildren(true); + ValidateComponents(); + + // initialize each one + for (int i = 0; i < NetworkBehaviours.Length; ++i) + { + NetworkBehaviour component = NetworkBehaviours[i]; + component.netIdentity = this; + component.ComponentIndex = (byte)i; + } + } + + void ValidateComponents() + { + if (NetworkBehaviours == null) + { + Debug.LogError($"NetworkBehaviours array is null on {gameObject.name}!\n" + + $"Typically this can happen when a networked object is a child of a " + + $"non-networked parent that's disabled, preventing Awake on the networked object " + + $"from being invoked, where the NetworkBehaviours array is initialized.", gameObject); + } + else if (NetworkBehaviours.Length > MaxNetworkBehaviours) + { + Debug.LogError($"NetworkIdentity {name} has too many NetworkBehaviour components: only {MaxNetworkBehaviours} NetworkBehaviour components are allowed in order to save bandwidth.", this); + } + } + + // Awake is only called in Play mode. + // internal so we can call it during unit tests too. + internal void Awake() + { + // initialize NetworkBehaviour components. + // Awake() is called immediately after initialization. + // no one can overwrite it because NetworkIdentity is sealed. + // => doing it here is the fastest and easiest solution. + InitializeNetworkBehaviours(); + + if (hasSpawned) + { + Debug.LogError($"{name} has already spawned. Don't call Instantiate for NetworkIdentities that were in the scene since the beginning (aka scene objects). Otherwise the client won't know which object to use for a SpawnSceneObject message."); + SpawnedFromInstantiate = true; + Destroy(gameObject); + } + hasSpawned = true; + } + + void OnValidate() + { + // OnValidate is not called when using Instantiate, so we can use + // it to make sure that hasSpawned is false + hasSpawned = false; + +#if UNITY_EDITOR + DisallowChildNetworkIdentities(); + SetupIDs(); +#endif + } + + // expose our AssetId Guid to uint mapping code in case projects need to map Guids to uint as well. + // this way their projects won't break if we change our mapping algorithm. + // needs to be available at runtime / builds, don't wrap in #if UNITY_EDITOR + public static uint AssetGuidToUint(Guid guid) => (uint)guid.GetHashCode(); // deterministic + +#if UNITY_EDITOR + // child NetworkIdentities are not supported. + // Disallow them and show an error for the user to fix. + // This needs to work for Prefabs & Scene objects, so the previous check + // in NetworkClient.RegisterPrefab is not enough. + void DisallowChildNetworkIdentities() + { +#if UNITY_2020_3_OR_NEWER + NetworkIdentity[] identities = GetComponentsInChildren(true); +#else + NetworkIdentity[] identities = GetComponentsInChildren(); +#endif + if (identities.Length > 1) + { + // always log the next child component so it's easy to fix. + // if there are multiple, then after removing it'll log the next. + Debug.LogError($"'{name}' has another NetworkIdentity component on '{identities[1].name}'. There should only be one NetworkIdentity, and it must be on the root object. Please remove the other one.", this); + } + } + + void AssignAssetID(string path) + { + // only set if not empty. fixes https://github.com/vis2k/Mirror/issues/2765 + if (!string.IsNullOrWhiteSpace(path)) + { + // if we generate the assetId then we MUST be sure to set dirty + // in order to save the prefab object properly. otherwise it + // would be regenerated every time we reopen the prefab. + // -> Undo.RecordObject is the new EditorUtility.SetDirty! + // -> we need to call it before changing. + // + // to verify this, duplicate a prefab and double click to open it. + // add a log message if "_assetId != before_". + // without RecordObject, it'll log every time because it's not saved. + Undo.RecordObject(this, "Assigned AssetId"); + + // uint before = _assetId; + Guid guid = new Guid(AssetDatabase.AssetPathToGUID(path)); + assetId = AssetGuidToUint(guid); + // if (_assetId != before) Debug.Log($"Assigned assetId={assetId} to {name}"); + } + } + + void AssignAssetID(GameObject prefab) => AssignAssetID(AssetDatabase.GetAssetPath(prefab)); + + // persistent sceneId assignment + // (because scene objects have no persistent unique ID in Unity) + // + // original UNET used OnPostProcessScene to assign an index based on + // FindObjectOfType order. + // -> this didn't work because FindObjectOfType order isn't deterministic. + // -> one workaround is to sort them by sibling paths, but it can still + // get out of sync when we open scene2 in editor and we have + // DontDestroyOnLoad objects that messed with the sibling index. + // + // we absolutely need a persistent id. challenges: + // * it needs to be 0 for prefabs + // => we set it to 0 in SetupIDs() if prefab! + // * it needs to be only assigned in edit time, not at runtime because + // only the objects that were in the scene since beginning should have + // a scene id. + // => Application.isPlaying check solves that + // * it needs to detect duplicated sceneIds after duplicating scene + // objects + // => sceneIds dict takes care of that + // * duplicating the whole scene file shouldn't result in duplicate + // scene objects + // => buildIndex is shifted into sceneId for that. + // => if we have no scenes in build index then it doesn't matter + // because by definition a build can't switch to other scenes + // => if we do have scenes in build index then it will be != -1 + // note: the duplicated scene still needs to be opened once for it to + // be set properly + // * scene objects need the correct scene index byte even if the scene's + // build index was changed or a duplicated scene wasn't opened yet. + // => OnPostProcessScene is the only function that gets called for + // each scene before runtime, so this is where we set the scene + // byte. + // * disabled scenes in build settings should result in same scene index + // in editor and in build + // => .gameObject.scene.buildIndex filters out disabled scenes by + // default + // * generated sceneIds absolutely need to set scene dirty and force the + // user to resave. + // => Undo.RecordObject does that perfectly. + // * sceneIds should never be generated temporarily for unopened scenes + // when building, otherwise editor and build get out of sync + // => BuildPipeline.isBuildingPlayer check solves that + void AssignSceneID() + { + // we only ever assign sceneIds at edit time, never at runtime. + // by definition, only the original scene objects should get one. + // -> if we assign at runtime then server and client would generate + // different random numbers! + if (Application.isPlaying) + return; + + // no valid sceneId yet, or duplicate? + bool duplicate = sceneIds.TryGetValue(sceneId, out NetworkIdentity existing) && existing != null && existing != this; + if (sceneId == 0 || duplicate) + { + // clear in any case, because it might have been a duplicate + sceneId = 0; + + // if a scene was never opened and we are building it, then a + // sceneId would be assigned to build but not saved in editor, + // resulting in them getting out of sync. + // => don't ever assign temporary ids. they always need to be + // permanent + // => throw an exception to cancel the build and let the user + // know how to fix it! + if (BuildPipeline.isBuildingPlayer) + throw new InvalidOperationException($"Scene {gameObject.scene.path} needs to be opened and resaved before building, because the scene object {name} has no valid sceneId yet."); + + // if we generate the sceneId then we MUST be sure to set dirty + // in order to save the scene object properly. otherwise it + // would be regenerated every time we reopen the scene, and + // upgrading would be very difficult. + // -> Undo.RecordObject is the new EditorUtility.SetDirty! + // -> we need to call it before changing. + Undo.RecordObject(this, "Generated SceneId"); + + // generate random sceneId part (0x00000000FFFFFFFF) + uint randomId = Utils.GetTrueRandomUInt(); + + // only assign if not a duplicate of an existing scene id + // (small chance, but possible) + duplicate = sceneIds.TryGetValue(randomId, out existing) && existing != null && existing != this; + if (!duplicate) + { + sceneId = randomId; + //Debug.Log($"{name} in scene {gameObject.scene.name} sceneId assigned to:{sceneId:X}"); + } + } + + // add to sceneIds dict no matter what + // -> even if we didn't generate anything new, because we still need + // existing sceneIds in there to check duplicates + sceneIds[sceneId] = this; + } + + // copy scene path hash into sceneId for scene objects. + // this is the only way for scene file duplication to not contain + // duplicate sceneIds as it seems. + // -> sceneId before: 0x00000000AABBCCDD + // -> then we clear the left 4 bytes, so that our 'OR' uses 0x00000000 + // -> then we OR the hash into the 0x00000000 part + // -> buildIndex is not enough, because Editor and Build have different + // build indices if there are disabled scenes in build settings, and + // if no scene is in build settings then Editor and Build have + // different indices too (Editor=0, Build=-1) + // => ONLY USE THIS FROM POSTPROCESSSCENE! + public void SetSceneIdSceneHashPartInternal() + { + // Use `ToLower` to that because BuildPipeline.BuildPlayer is case insensitive but hash is case sensitive + // If the scene in the project is `forest.unity` but `Forest.unity` is given to BuildPipeline then the + // BuildPipeline will use `Forest.unity` for the build and create a different hash than the editor will. + // Using ToLower will mean the hash will be the same for these 2 paths + // Assets/Scenes/Forest.unity + // Assets/Scenes/forest.unity + string scenePath = gameObject.scene.path.ToLower(); + + // get deterministic scene hash + uint pathHash = (uint)scenePath.GetStableHashCode(); + + // shift hash from 0x000000FFFFFFFF to 0xFFFFFFFF00000000 + ulong shiftedHash = (ulong)pathHash << 32; + + // OR into scene id + sceneId = (sceneId & 0xFFFFFFFF) | shiftedHash; + + // log it. this is incredibly useful to debug sceneId issues. + //Debug.Log($"{name} in scene {gameObject.scene.name} scene index hash {pathHash:X} copied into sceneId {sceneId:X}"); + } + + void SetupIDs() + { + // is this a prefab? + if (Utils.IsPrefab(gameObject)) + { + // force 0 for prefabs + sceneId = 0; + AssignAssetID(gameObject); + } + // are we currently in prefab editing mode? aka prefab stage + // => check prefabstage BEFORE SceneObjectWithPrefabParent + // (fixes https://github.com/vis2k/Mirror/issues/976) + // => if we don't check GetCurrentPrefabStage and only check + // GetPrefabStage(gameObject), then the 'else' case where we + // assign a sceneId and clear the assetId would still be + // triggered for prefabs. in other words: if we are in prefab + // stage, do not bother with anything else ever! + else if (PrefabStageUtility.GetCurrentPrefabStage() != null) + { + // when modifying a prefab in prefab stage, Unity calls + // OnValidate for that prefab and for all scene objects based on + // that prefab. + // + // is this GameObject the prefab that we modify, and not just a + // scene object based on the prefab? + // * GetCurrentPrefabStage = 'are we editing ANY prefab?' + // * GetPrefabStage(go) = 'are we editing THIS prefab?' + if (PrefabStageUtility.GetPrefabStage(gameObject) != null) + { + // force 0 for prefabs + sceneId = 0; + //Debug.Log($"{name} scene:{gameObject.scene.name} sceneid reset to 0 because CurrentPrefabStage={PrefabStageUtility.GetCurrentPrefabStage()} PrefabStage={PrefabStageUtility.GetPrefabStage(gameObject)}"); + + // get path from PrefabStage for this prefab +#if UNITY_2020_1_OR_NEWER + string path = PrefabStageUtility.GetPrefabStage(gameObject).assetPath; +#else + string path = PrefabStageUtility.GetPrefabStage(gameObject).prefabAssetPath; +#endif + + AssignAssetID(path); + } + } + // is this a scene object with prefab parent? + else if (Utils.IsSceneObjectWithPrefabParent(gameObject, out GameObject prefab)) + { + AssignSceneID(); + AssignAssetID(prefab); + } + else + { + AssignSceneID(); + + // IMPORTANT: DO NOT clear assetId at runtime! + // => fixes a bug where clicking any of the NetworkIdentity + // properties (like ServerOnly/ForceHidden) at runtime would + // call OnValidate + // => OnValidate gets into this else case here because prefab + // connection isn't known at runtime + // => then we would clear the previously assigned assetId + // => and NetworkIdentity couldn't be spawned on other clients + // anymore because assetId was cleared + if (!EditorApplication.isPlaying) + { + _assetId = 0; + } + // don't log. would show a lot when pressing play in uMMORPG/uSurvival/etc. + //else Debug.Log($"Avoided clearing assetId at runtime for {name} after (probably) clicking any of the NetworkIdentity properties."); + } + } +#endif + + // OnDestroy is called for all SPAWNED NetworkIdentities + // => scene objects aren't destroyed. it's not called for them. + // + // Note: Unity will Destroy all networked objects on Scene Change, so we + // have to handle that here silently. That means we cannot have any + // warning or logging in this method. + void OnDestroy() + { + // Objects spawned from Instantiate are not allowed so are destroyed right away + // we don't want to call NetworkServer.Destroy if this is the case + if (SpawnedFromInstantiate) + return; + + // If false the object has already been unspawned + // if it is still true, then we need to unspawn it + // if destroy is already called don't call it again + if (isServer && !destroyCalled) + { + // Do not add logging to this (see above) + NetworkServer.Destroy(gameObject); + } + + if (isLocalPlayer) + { + // previously there was a bug where isLocalPlayer was + // false in OnDestroy because it was dynamically defined as: + // isLocalPlayer => NetworkClient.localPlayer == this + // we fixed it by setting isLocalPlayer manually and never + // resetting it. + // + // BUT now we need to be aware of a possible data race like in + // our rooms example: + // => GamePlayer is in world + // => player returns to room + // => GamePlayer is destroyed + // => NetworkClient.localPlayer is set to RoomPlayer + // => GamePlayer.OnDestroy is called 1 frame later + // => GamePlayer.OnDestroy 'isLocalPlayer' is true, so here we + // are trying to clear NetworkClient.localPlayer + // => which would overwrite the new RoomPlayer local player + // + // FIXED by simply only clearing if NetworkClient.localPlayer + // still points to US! + // => see also: https://github.com/vis2k/Mirror/issues/2635 + if (NetworkClient.localPlayer == this) + NetworkClient.localPlayer = null; + } + + if (isClient) + { + // ServerChangeScene doesn't send destroy messages. + // some identities may persist in DDOL. + // some are destroyed by scene change. + // if an identity is still in .owned remove it. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3308 + if (NetworkClient.connection != null) + NetworkClient.connection.owned.Remove(this); + + // if an identity is still in .spawned, remove it too. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3324 + NetworkClient.spawned.Remove(netId); + } + } + + internal void OnStartServer() + { + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + // an exception in OnStartServer should be caught, so that one + // component's exception doesn't stop all other components from + // being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + comp.OnStartServer(); + } + catch (Exception e) + { + Debug.LogException(e, comp); + } + } + } + + internal void OnStopServer() + { + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + // an exception in OnStartServer should be caught, so that one + // component's exception doesn't stop all other components from + // being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + comp.OnStopServer(); + } + catch (Exception e) + { + Debug.LogException(e, comp); + } + } + } + + internal void OnStartClient() + { + if (clientStarted) return; + + clientStarted = true; + + // Debug.Log($"OnStartClient {gameObject} netId:{netId}"); + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + // an exception in OnStartClient should be caught, so that one + // component's exception doesn't stop all other components from + // being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + // user implemented startup + comp.OnStartClient(); + } + catch (Exception e) + { + Debug.LogException(e, comp); + } + } + } + + internal void OnStopClient() + { + // In case this object was destroyed already don't call + // OnStopClient if OnStartClient hasn't been called. + if (!clientStarted) return; + + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + // an exception in OnStopClient should be caught, so that + // one component's exception doesn't stop all other components + // from being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + comp.OnStopClient(); + } + catch (Exception e) + { + Debug.LogException(e, comp); + } + } + } + + internal static NetworkIdentity previousLocalPlayer = null; + internal void OnStartLocalPlayer() + { + // ensure OnStartLocalPlayer is only called once. + // Room demo would call it multiple times: + // - once from ApplySpawnPayload + // - once from OnObjectSpawnFinished + // + // to reproduce: + // - open room demo, add the 3 scenes to build settings + // - add OnStartLocalPlayer log to RoomPlayer prefab + // - build, run server-only + // - in editor, connect, press ready + // - in server, start game + // - notice multiple OnStartLocalPlayer logs in editor client + // + // explanation: + // we send the spawn message multiple times. Whenever an object changes + // authority, we send the spawn message again for the object. This is + // necessary because we need to reinitialize all variables when + // ownership change due to sync to owner feature. + // Without this static, the second time we get the spawn message we + // would call OnStartLocalPlayer again on the same object + if (previousLocalPlayer == this) + return; + previousLocalPlayer = this; + + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + // an exception in OnStartLocalPlayer should be caught, so that + // one component's exception doesn't stop all other components + // from being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + comp.OnStartLocalPlayer(); + } + catch (Exception e) + { + Debug.LogException(e, comp); + } + } + } + + internal void OnStopLocalPlayer() + { + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + // an exception in OnStopLocalPlayer should be caught, so that + // one component's exception doesn't stop all other components + // from being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + comp.OnStopLocalPlayer(); + } + catch (Exception e) + { + Debug.LogException(e, comp); + } + } + } + + // build dirty mask for server owner & observers (= all dirty components). + // faster to do it in one iteration instead of iterating separately. + (ulong, ulong) ServerDirtyMasks(bool initialState) + { + ulong ownerMask = 0; + ulong observerMask = 0; + + NetworkBehaviour[] components = NetworkBehaviours; + for (int i = 0; i < components.Length; ++i) + { + NetworkBehaviour component = components[i]; + + bool dirty = component.IsDirty(); + ulong nthBit = (1u << i); + + // owner needs to be considered for both SyncModes, because + // Observers mode always includes the Owner. + // + // for initial, it should always sync owner. + // for delta, only for ServerToClient and only if dirty. + // ClientToServer comes from the owner client. + if (initialState || (component.syncDirection == SyncDirection.ServerToClient && dirty)) + ownerMask |= nthBit; + + // observers need to be considered only in Observers mode + // + // for initial, it should always sync to observers. + // for delta, only if dirty. + // SyncDirection is irrelevant, as both are broadcast to + // observers which aren't the owner. + if (component.syncMode == SyncMode.Observers && (initialState || dirty)) + observerMask |= nthBit; + } + + return (ownerMask, observerMask); + } + + // build dirty mask for client. + // server always knows initialState, so we don't need it here. + ulong ClientDirtyMask() + { + ulong mask = 0; + + NetworkBehaviour[] components = NetworkBehaviours; + for (int i = 0; i < components.Length; ++i) + { + // on the client, we need to consider different sync scenarios: + // + // ServerToClient SyncDirection: + // do nothing. + // ClientToServer SyncDirection: + // serialize only if owned. + + // on client, only consider owned components with SyncDirection to server + NetworkBehaviour component = components[i]; + if (isOwned && component.syncDirection == SyncDirection.ClientToServer) + { + // set the n-th bit if dirty + // shifting from small to large numbers is varint-efficient. + if (component.IsDirty()) mask |= (1u << i); + } + } + + return mask; + } + + // check if n-th component is dirty. + // in other words, if it has the n-th bit set in the dirty mask. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool IsDirty(ulong mask, int index) + { + ulong nthBit = (ulong)(1 << index); + return (mask & nthBit) != 0; + } + + // serialize components into writer on the server. + // check ownerWritten/observersWritten to know if anything was written + // We pass dirtyComponentsMask into this function so that we can check + // if any Components are dirty before creating writers + internal void SerializeServer(bool initialState, NetworkWriter ownerWriter, NetworkWriter observersWriter) + { + // ensure NetworkBehaviours are valid before usage + ValidateComponents(); + NetworkBehaviour[] components = NetworkBehaviours; + + // check which components are dirty for owner / observers. + // this is quite complicated with SyncMode + SyncDirection. + // see the function for explanation. + // + // instead of writing a 1 byte index per component, + // we limit components to 64 bits and write one ulong instead. + // the ulong is also varint compressed for minimum bandwidth. + (ulong ownerMask, ulong observerMask) = ServerDirtyMasks(initialState); + + // if nothing dirty, then don't even write the mask. + // otherwise, every unchanged object would send a 1 byte dirty mask! + if (ownerMask != 0) Compression.CompressVarUInt(ownerWriter, ownerMask); + if (observerMask != 0) Compression.CompressVarUInt(observersWriter, observerMask); + + // serialize all components + // perf: only iterate if either dirty mask has dirty bits. + if ((ownerMask | observerMask) != 0) + { + for (int i = 0; i < components.Length; ++i) + { + NetworkBehaviour comp = components[i]; + + // is the component dirty for anyone (owner or observers)? + // may be serialized to owner, observer, both, or neither. + // + // OnSerialize should only be called once. + // this is faster, and it cleaner because it may set + // internal state, counters, logs, etc. + // + // previously we always serialized to owner and then copied + // the serialization to observers. however, since + // SyncDirection it's not guaranteed to be in owner anymore. + // so we need to serialize to temporary writer first. + // and then copy as needed. + bool ownerDirty = IsDirty(ownerMask, i); + bool observersDirty = IsDirty(observerMask, i); + if (ownerDirty || observersDirty) + { + // serialize into helper writer + using (NetworkWriterPooled temp = NetworkWriterPool.Get()) + { + comp.Serialize(temp, initialState); + ArraySegment segment = temp.ToArraySegment(); + + // copy to owner / observers as needed + if (ownerDirty) ownerWriter.WriteBytes(segment.Array, segment.Offset, segment.Count); + if (observersDirty) observersWriter.WriteBytes(segment.Array, segment.Offset, segment.Count); + } + + // clear dirty bits for the components that we serialized. + // do not clear for _all_ components, only the ones that + // were dirty and had their syncInterval elapsed. + // + // we don't want to clear bits before the syncInterval + // was elapsed, as then they wouldn't be synced. + // + // only clear for delta, not for full (spawn messages). + // otherwise if a player joins, we serialize monster, + // and shouldn't clear dirty bits not yet synced to + // other players. + if (!initialState) comp.ClearAllDirtyBits(); + } + } + } + } + + // serialize components into writer on the client. + internal void SerializeClient(NetworkWriter writer) + { + // ensure NetworkBehaviours are valid before usage + ValidateComponents(); + NetworkBehaviour[] components = NetworkBehaviours; + + // check which components are dirty. + // this is quite complicated with SyncMode + SyncDirection. + // see the function for explanation. + // + // instead of writing a 1 byte index per component, + // we limit components to 64 bits and write one ulong instead. + // the ulong is also varint compressed for minimum bandwidth. + ulong dirtyMask = ClientDirtyMask(); + + // varint compresses the mask to 1 byte in most cases. + // instead of writing an 8 byte ulong. + // 7 components fit into 1 byte. (previously 7 bytes) + // 11 components fit into 2 bytes. (previously 11 bytes) + // 16 components fit into 3 bytes. (previously 16 bytes) + // TODO imer: server knows amount of comps, write N bytes instead + + // if nothing dirty, then don't even write the mask. + // otherwise, every unchanged object would send a 1 byte dirty mask! + if (dirtyMask != 0) Compression.CompressVarUInt(writer, dirtyMask); + + // serialize all components + // perf: only iterate if dirty mask has dirty bits. + if (dirtyMask != 0) + { + // serialize all components + for (int i = 0; i < components.Length; ++i) + { + NetworkBehaviour comp = components[i]; + + // is this component dirty? + // reuse the mask instead of calling comp.IsDirty() again here. + if (IsDirty(dirtyMask, i)) + // if (isOwned && component.syncDirection == SyncDirection.ClientToServer) + { + // serialize into writer. + // server always knows initialState, we never need to send it + comp.Serialize(writer, false); + + // clear dirty bits for the components that we serialized. + // do not clear for _all_ components, only the ones that + // were dirty and had their syncInterval elapsed. + // + // we don't want to clear bits before the syncInterval + // was elapsed, as then they wouldn't be synced. + comp.ClearAllDirtyBits(); + } + } + } + } + + // deserialize components from the client on the server. + // there's no 'initialState'. server always knows the initial state. + internal bool DeserializeServer(NetworkReader reader) + { + // ensure NetworkBehaviours are valid before usage + ValidateComponents(); + NetworkBehaviour[] components = NetworkBehaviours; + + // first we deserialize the varinted dirty mask + ulong mask = Compression.DecompressVarUInt(reader); + + // now deserialize every dirty component + for (int i = 0; i < components.Length; ++i) + { + // was this one dirty? + if (IsDirty(mask, i)) + { + NetworkBehaviour comp = components[i]; + + // safety check to ensure clients can only modify their own + // ClientToServer components, nothing else. + if (comp.syncDirection == SyncDirection.ClientToServer) + { + // deserialize this component + // server always knows the initial state (initial=false) + // disconnect if failed, to prevent exploits etc. + if (!comp.Deserialize(reader, false)) return false; + + // server received state from the owner client. + // set dirty so it's broadcast to other clients too. + // + // note that we set the _whole_ component as dirty. + // everything will be broadcast to others. + // SetSyncVarDirtyBits() would be nicer, but not all + // components use [SyncVar]s. + comp.SetDirty(); + } + } + } + + // successfully deserialized everything + return true; + } + + // deserialize components from server on the client. + internal void DeserializeClient(NetworkReader reader, bool initialState) + { + // ensure NetworkBehaviours are valid before usage + ValidateComponents(); + NetworkBehaviour[] components = NetworkBehaviours; + + // first we deserialize the varinted dirty mask + ulong mask = Compression.DecompressVarUInt(reader); + + // now deserialize every dirty component + for (int i = 0; i < components.Length; ++i) + { + // was this one dirty? + if (IsDirty(mask, i)) + { + // deserialize this component + NetworkBehaviour comp = components[i]; + comp.Deserialize(reader, initialState); + } + } + } + + // get cached serialization for this tick (or serialize if none yet). + // IMPORTANT: int tick avoids floating point inaccuracy over days/weeks. + // calls SerializeServer, so this function is to be called on server. + internal NetworkIdentitySerialization GetServerSerializationAtTick(int tick) + { + // only rebuild serialization once per tick. reuse otherwise. + // except for tests, where Time.frameCount never increases. + // so during tests, we always rebuild. + // (otherwise [SyncVar] changes would never be serialized in tests) + // + // NOTE: != instead of < because int.max+1 overflows at some point. + if (lastSerialization.tick != tick +#if UNITY_EDITOR + || !Application.isPlaying +#endif + ) + { + // reset + lastSerialization.ownerWriter.Position = 0; + lastSerialization.observersWriter.Position = 0; + + // serialize + SerializeServer(false, + lastSerialization.ownerWriter, + lastSerialization.observersWriter); + + // set tick + lastSerialization.tick = tick; + //Debug.Log($"{name} (netId={netId}) serialized for tick={tickTimeStamp}"); + } + + // return it + return lastSerialization; + } + + internal void AddObserver(NetworkConnectionToClient conn) + { + if (observers.ContainsKey(conn.connectionId)) + { + // if we try to add a connectionId that was already added, then + // we may have generated one that was already in use. + return; + } + + // Debug.Log($"Added observer: {conn.address} added for {gameObject}"); + + // if we previously had no observers, then clear all dirty bits once. + // a monster's health may have changed while it had no observers. + // but that change (= the dirty bits) don't matter as soon as the + // first observer comes. + // -> first observer gets full spawn packet + // -> afterwards it gets delta packet + // => if we don't clear previous dirty bits, observer would get + // the health change because the bit was still set. + // => ultimately this happens because spawn doesn't reset dirty + // bits + // => which happens because spawn happens separately, instead of + // in Broadcast() (which will be changed in the future) + // + // NOTE that NetworkServer.Broadcast previously cleared dirty bits + // for ALL SPAWNED that don't have observers. that was super + // expensive. doing it when adding the first observer has the + // same result, without the O(N) iteration in Broadcast(). + // + // TODO remove this after moving spawning into Broadcast()! + if (observers.Count == 0) + { + ClearAllComponentsDirtyBits(); + } + + observers[conn.connectionId] = conn; + conn.AddToObserving(this); + } + + // clear all component's dirty bits no matter what + internal void ClearAllComponentsDirtyBits() + { + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + comp.ClearAllDirtyBits(); + } + } + + // this is used when a connection is destroyed, since the "observers" property is read-only + internal void RemoveObserver(NetworkConnection conn) + { + observers.Remove(conn.connectionId); + } + + /// Assign control of an object to a client via the client's NetworkConnection. + // This causes hasAuthority to be set on the client that owns the object, + // and NetworkBehaviour.OnStartAuthority will be called on that client. + // This object then will be in the NetworkConnection.clientOwnedObjects + // list for the connection. + // + // Authority can be removed with RemoveClientAuthority. Only one client + // can own an object at any time. This does not need to be called for + // player objects, as their authority is setup automatically. + public bool AssignClientAuthority(NetworkConnectionToClient conn) + { + if (!isServer) + { + Debug.LogError("AssignClientAuthority can only be called on the server for spawned objects."); + return false; + } + + if (conn == null) + { + Debug.LogError($"AssignClientAuthority for {gameObject} owner cannot be null. Use RemoveClientAuthority() instead."); + return false; + } + + if (connectionToClient != null && conn != connectionToClient) + { + Debug.LogError($"AssignClientAuthority for {gameObject} already has an owner. Use RemoveClientAuthority() first."); + return false; + } + + SetClientOwner(conn); + + // The client will match to the existing object + NetworkServer.SendChangeOwnerMessage(this, conn); + + clientAuthorityCallback?.Invoke(conn, this, true); + + return true; + } + + // used when adding players + internal void SetClientOwner(NetworkConnectionToClient conn) + { + // do nothing if it already has an owner + if (connectionToClient != null && conn != connectionToClient) + { + Debug.LogError($"Object {this} netId={netId} already has an owner. Use RemoveClientAuthority() first", this); + return; + } + + // otherwise set the owner connection + connectionToClient = conn; + } + + /// Removes ownership for an object. + // Applies to objects that had authority set by AssignClientAuthority, + // or NetworkServer.Spawn with a NetworkConnection parameter included. + // Authority cannot be removed for player objects. + public void RemoveClientAuthority() + { + if (!isServer) + { + Debug.LogError("RemoveClientAuthority can only be called on the server for spawned objects."); + return; + } + + if (connectionToClient?.identity == this) + { + Debug.LogError("RemoveClientAuthority cannot remove authority for a player object"); + return; + } + + if (connectionToClient != null) + { + clientAuthorityCallback?.Invoke(connectionToClient, this, false); + NetworkConnectionToClient previousOwner = connectionToClient; + connectionToClient = null; + NetworkServer.SendChangeOwnerMessage(this, previousOwner); + } + } + + // Reset is called when the user hits the Reset button in the + // Inspector's context menu or when adding the component the first time. + // This function is only called in editor mode. + // + // Reset() seems to be called only for Scene objects. + // we can't destroy them (they are always in the scene). + // instead we disable them and call Reset(). + // + // Do not reset SyncObjects from Reset + // - Unspawned objects need to retain their list contents + // - They may be respawned, especially players, but others as well. + // + // OLD COMMENT: + // Marks the identity for future reset, this is because we cant reset + // the identity during destroy as people might want to be able to read + // the members inside OnDestroy(), and we have no way of invoking reset + // after OnDestroy is called. + internal void ResetState() + { + hasSpawned = false; + clientStarted = false; + isClient = false; + isServer = false; + //isLocalPlayer = false; <- cleared AFTER ClearLocalPlayer below! + + // remove authority flag. This object may be unspawned, not destroyed, on client. + isOwned = false; + NotifyAuthority(); + + netId = 0; + connectionToServer = null; + connectionToClient = null; + + ClearObservers(); + + // clear local player if it was the local player, + // THEN reset isLocalPlayer AFTERWARDS + if (isLocalPlayer) + { + // only clear NetworkClient.localPlayer IF IT POINTS TO US! + // see OnDestroy() comments. it does the same. + // (https://github.com/vis2k/Mirror/issues/2635) + if (NetworkClient.localPlayer == this) + NetworkClient.localPlayer = null; + } + + previousLocalPlayer = null; + isLocalPlayer = false; + } + + bool hadAuthority; + internal void NotifyAuthority() + { + if (!hadAuthority && isOwned) + OnStartAuthority(); + if (hadAuthority && !isOwned) + OnStopAuthority(); + hadAuthority = isOwned; + } + + internal void OnStartAuthority() + { + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + // an exception in OnStartAuthority should be caught, so that one + // component's exception doesn't stop all other components from + // being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + comp.OnStartAuthority(); + } + catch (Exception e) + { + Debug.LogException(e, comp); + } + } + } + + internal void OnStopAuthority() + { + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + // an exception in OnStopAuthority should be caught, so that one + // component's exception doesn't stop all other components from + // being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + comp.OnStopAuthority(); + } + catch (Exception e) + { + Debug.LogException(e, comp); + } + } + } + + // Called when NetworkIdentity is destroyed + internal void ClearObservers() + { + foreach (NetworkConnectionToClient conn in observers.Values) + { + conn.RemoveFromObserving(this, true); + } + observers.Clear(); + } + } +} diff --git a/Assets/Mirror/Core/NetworkIdentity.cs.meta b/Assets/Mirror/Core/NetworkIdentity.cs.meta new file mode 100644 index 0000000..7b96521 --- /dev/null +++ b/Assets/Mirror/Core/NetworkIdentity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b91ecbcc199f4492b9a91e820070131 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkLoop.cs b/Assets/Mirror/Core/NetworkLoop.cs new file mode 100644 index 0000000..a9cd490 --- /dev/null +++ b/Assets/Mirror/Core/NetworkLoop.cs @@ -0,0 +1,211 @@ +// our ideal update looks like this: +// transport.process_incoming() +// update_world() +// transport.process_outgoing() +// +// this way we avoid unnecessary latency for low-ish server tick rates. +// for example, if we were to use this tick: +// transport.process_incoming/outgoing() +// update_world() +// +// then anything sent in update_world wouldn't be actually sent out by the +// transport until the next frame. if server runs at 60Hz, then this can add +// 16ms latency for every single packet. +// +// => instead we process incoming, update world, process_outgoing in the same +// frame. it's more clear (no race conditions) and lower latency. +// => we need to add custom Update functions to the Unity engine: +// NetworkEarlyUpdate before Update()/FixedUpdate() +// NetworkLateUpdate after LateUpdate() +// this way the user can update the world in Update/FixedUpdate/LateUpdate +// and networking still runs before/after those functions no matter what! +// => see also: https://docs.unity3d.com/Manual/ExecutionOrder.html +// => update order: +// * we add to the end of EarlyUpdate so it runs after any Unity initializations +// * we add to the end of PreLateUpdate so it runs after LateUpdate(). adding +// to the beginning of PostLateUpdate doesn't actually work. +using System; +using UnityEngine; +using UnityEngine.LowLevel; +using UnityEngine.PlayerLoop; + +namespace Mirror +{ + public static class NetworkLoop + { + // helper enum to add loop to begin/end of subSystemList + internal enum AddMode { Beginning, End } + + // callbacks for others to hook into if they need Early/LateUpdate. + public static Action OnEarlyUpdate; + public static Action OnLateUpdate; + + // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStatics() + { + OnEarlyUpdate = null; + OnLateUpdate = null; + } + + // helper function to find an update function's index in a player loop + // type. this is used for testing to guarantee our functions are added + // at the beginning/end properly. + internal static int FindPlayerLoopEntryIndex(PlayerLoopSystem.UpdateFunction function, PlayerLoopSystem playerLoop, Type playerLoopSystemType) + { + // did we find the type? e.g. EarlyUpdate/PreLateUpdate/etc. + if (playerLoop.type == playerLoopSystemType) + return Array.FindIndex(playerLoop.subSystemList, (elem => elem.updateDelegate == function)); + + // recursively keep looking + if (playerLoop.subSystemList != null) + { + for (int i = 0; i < playerLoop.subSystemList.Length; ++i) + { + int index = FindPlayerLoopEntryIndex(function, playerLoop.subSystemList[i], playerLoopSystemType); + if (index != -1) return index; + } + } + return -1; + } + + // MODIFIED AddSystemToPlayerLoopList from Unity.Entities.ScriptBehaviourUpdateOrder (ECS) + // + // => adds an update function to the Unity internal update type. + // => Unity has different update loops: + // https://medium.com/@thebeardphantom/unity-2018-and-playerloop-5c46a12a677 + // EarlyUpdate + // FixedUpdate + // PreUpdate + // Update + // PreLateUpdate + // PostLateUpdate + // + // function: the custom update function to add + // IMPORTANT: according to a comment in Unity.Entities.ScriptBehaviourUpdateOrder, + // the UpdateFunction can not be virtual because + // Mono 4.6 has problems invoking virtual methods + // as delegates from native! + // ownerType: the .type to fill in so it's obvious who the new function + // belongs to. seems to be mostly for debugging. pass any. + // addMode: prepend or append to update list + internal static bool AddToPlayerLoop(PlayerLoopSystem.UpdateFunction function, Type ownerType, ref PlayerLoopSystem playerLoop, Type playerLoopSystemType, AddMode addMode) + { + // did we find the type? e.g. EarlyUpdate/PreLateUpdate/etc. + if (playerLoop.type == playerLoopSystemType) + { + // debugging + //Debug.Log($"Found playerLoop of type {playerLoop.type} with {playerLoop.subSystemList.Length} Functions:"); + //foreach (PlayerLoopSystem sys in playerLoop.subSystemList) + // Debug.Log($" ->{sys.type}"); + + // make sure the function wasn't added yet. + // with domain reload disabled, it would otherwise be added twice: + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3392 + if (Array.FindIndex(playerLoop.subSystemList, (s => s.updateDelegate == function)) != -1) + { + // loop contains the function, so return true. + return true; + } + + // resize & expand subSystemList to fit one more entry + int oldListLength = (playerLoop.subSystemList != null) ? playerLoop.subSystemList.Length : 0; + Array.Resize(ref playerLoop.subSystemList, oldListLength + 1); + + // IMPORTANT: always insert a FRESH PlayerLoopSystem! + // We CAN NOT resize and then OVERWRITE an entry's type/loop. + // => PlayerLoopSystem has native IntPtr loop members + // => forgetting to clear those would cause undefined behaviour! + // see also: https://github.com/vis2k/Mirror/pull/2652 + PlayerLoopSystem system = new PlayerLoopSystem { + type = ownerType, + updateDelegate = function + }; + + // prepend our custom loop to the beginning + if (addMode == AddMode.Beginning) + { + // shift to the right, write into first array element + Array.Copy(playerLoop.subSystemList, 0, playerLoop.subSystemList, 1, playerLoop.subSystemList.Length - 1); + playerLoop.subSystemList[0] = system; + } + // append our custom loop to the end + else if (addMode == AddMode.End) + { + // simply write into last array element + playerLoop.subSystemList[oldListLength] = system; + } + + // debugging + //Debug.Log($"New playerLoop of type {playerLoop.type} with {playerLoop.subSystemList.Length} Functions:"); + //foreach (PlayerLoopSystem sys in playerLoop.subSystemList) + // Debug.Log($" ->{sys.type}"); + + return true; + } + + // recursively keep looking + if (playerLoop.subSystemList != null) + { + for (int i = 0; i < playerLoop.subSystemList.Length; ++i) + { + if (AddToPlayerLoop(function, ownerType, ref playerLoop.subSystemList[i], playerLoopSystemType, addMode)) + return true; + } + } + return false; + } + + // hook into Unity runtime to actually add our custom functions + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void RuntimeInitializeOnLoad() + { + //Debug.Log("Mirror: adding Network[Early/Late]Update to Unity..."); + + // get loop + // 2019 has GetCURRENTPlayerLoop which is safe to use without + // breaking other custom system's custom loops. + // see also: https://github.com/vis2k/Mirror/pull/2627/files + PlayerLoopSystem playerLoop = PlayerLoop.GetCurrentPlayerLoop(); + + // add NetworkEarlyUpdate to the end of EarlyUpdate so it runs after + // any Unity initializations but before the first Update/FixedUpdate + AddToPlayerLoop(NetworkEarlyUpdate, typeof(NetworkLoop), ref playerLoop, typeof(EarlyUpdate), AddMode.End); + + // add NetworkLateUpdate to the end of PreLateUpdate so it runs after + // LateUpdate(). adding to the beginning of PostLateUpdate doesn't + // actually work. + AddToPlayerLoop(NetworkLateUpdate, typeof(NetworkLoop), ref playerLoop, typeof(PreLateUpdate), AddMode.End); + + // set the new loop + PlayerLoop.SetPlayerLoop(playerLoop); + } + + static void NetworkEarlyUpdate() + { + // loop functions run in edit mode and in play mode. + // however, we only want to call NetworkServer/Client in play mode. + if (!Application.isPlaying) return; + + NetworkTime.EarlyUpdate(); + //Debug.Log($"NetworkEarlyUpdate {Time.time}"); + NetworkServer.NetworkEarlyUpdate(); + NetworkClient.NetworkEarlyUpdate(); + // invoke event after mirror has done it's early updating. + OnEarlyUpdate?.Invoke(); + } + + static void NetworkLateUpdate() + { + // loop functions run in edit mode and in play mode. + // however, we only want to call NetworkServer/Client in play mode. + if (!Application.isPlaying) return; + + //Debug.Log($"NetworkLateUpdate {Time.time}"); + // invoke event before mirror does its final late updating. + OnLateUpdate?.Invoke(); + NetworkServer.NetworkLateUpdate(); + NetworkClient.NetworkLateUpdate(); + } + } +} diff --git a/Assets/Mirror/Core/NetworkLoop.cs.meta b/Assets/Mirror/Core/NetworkLoop.cs.meta new file mode 100644 index 0000000..52b6e6a --- /dev/null +++ b/Assets/Mirror/Core/NetworkLoop.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c6cec4e279774b919386e05545317b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkManager.cs b/Assets/Mirror/Core/NetworkManager.cs new file mode 100644 index 0000000..905ce55 --- /dev/null +++ b/Assets/Mirror/Core/NetworkManager.cs @@ -0,0 +1,1504 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.Serialization; + +namespace Mirror +{ + public enum PlayerSpawnMethod { Random, RoundRobin } + public enum NetworkManagerMode { Offline, ServerOnly, ClientOnly, Host } + public enum HeadlessStartOptions { DoNothing, AutoStartServer, AutoStartClient } + + [DisallowMultipleComponent] + [AddComponentMenu("Network/Network Manager")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-manager")] + public class NetworkManager : MonoBehaviour + { + /// Enable to keep NetworkManager alive when changing scenes. + // This should be set if your game has a single NetworkManager that exists for the lifetime of the process. If there is a NetworkManager in each scene, then this should not be set. + [Header("Configuration")] + [FormerlySerializedAs("m_DontDestroyOnLoad")] + [Tooltip("Should the Network Manager object be persisted through scene changes?")] + public bool dontDestroyOnLoad = true; + + /// Multiplayer games should always run in the background so the network doesn't time out. + [FormerlySerializedAs("m_RunInBackground")] + [Tooltip("Multiplayer games should always run in the background so the network doesn't time out.")] + public bool runInBackground = true; + + /// Should the server auto-start when 'Server Build' is checked in build settings + [Header("Auto-Start Options")] + + [Tooltip("Choose whether Server or Client should auto-start in headless builds")] + public HeadlessStartOptions headlessStartMode = HeadlessStartOptions.DoNothing; + + [Tooltip("Headless Start Mode in Editor\nwhen enabled, headless start mode will be used in editor as well.")] + public bool editorAutoStart; + + /// Server Update frequency, per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE. + [Tooltip("Server & Client send rate per second. Use 60-100Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE.")] + [FormerlySerializedAs("serverTickRate")] + public int sendRate = 60; + + // Deprecated 2023-11-25 + // Using SerializeField and HideInInspector to self-correct for being + // replaced by headlessStartMode. This can be removed in the future. + // See OnValidate() for how we handle this. + [Obsolete("Deprecated - Use headlessStartMode instead.")] + [FormerlySerializedAs("autoStartServerBuild"), SerializeField, HideInInspector] + public bool autoStartServerBuild = true; + + // Deprecated 2023-11-25 + // Using SerializeField and HideInInspector to self-correct for being + // replaced by headlessStartMode. This can be removed in the future. + // See OnValidate() for how we handle this. + [Obsolete("Deprecated - Use headlessStartMode instead.")] + [FormerlySerializedAs("autoConnectClientBuild"), SerializeField, HideInInspector] + public bool autoConnectClientBuild; + + // client send rate follows server send rate to avoid errors for now + /// Client Update frequency, per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE. + // [Tooltip("Client broadcasts 'sendRate' times per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE.")] + // public int clientSendRate = 30; // 33 ms + + /// Automatically switch to this scene upon going offline (on start / on disconnect / on shutdown). + [Header("Scene Management")] + [Scene] + [FormerlySerializedAs("m_OfflineScene")] + [Tooltip("Scene that Mirror will switch to when the client or server is stopped")] + public string offlineScene = ""; + + /// Automatically switch to this scene upon going online (after connect/startserver). + [Scene] + [FormerlySerializedAs("m_OnlineScene")] + [Tooltip("Scene that Mirror will switch to when the server is started. Clients will recieve a Scene Message to load the server's current scene when they connect.")] + public string onlineScene = ""; + + // transport layer + [Header("Network Info")] + [Tooltip("Transport component attached to this object that server and client will use to connect")] + public Transport transport; + + /// Server's address for clients to connect to. + [FormerlySerializedAs("m_NetworkAddress")] + [Tooltip("Network Address where the client should connect to the server. Server does not use this for anything.")] + public string networkAddress = "localhost"; + + /// The maximum number of concurrent network connections to support. + [FormerlySerializedAs("m_MaxConnections")] + [Tooltip("Maximum number of concurrent connections.")] + public int maxConnections = 100; + + // Mirror global disconnect inactive option, independent of Transport. + // not all Transports do this properly, and it's easiest to configure this just once. + // this is very useful for some projects, keep it. + [Tooltip("When enabled, the server automatically disconnects inactive connections after the configured timeout.")] + public bool disconnectInactiveConnections; + + [Tooltip("Timeout in seconds for server to automatically disconnect inactive connections if 'disconnectInactiveConnections' is enabled.")] + public float disconnectInactiveTimeout = 60f; + + [Header("Authentication")] + [Tooltip("Authentication component attached to this object")] + public NetworkAuthenticator authenticator; + + /// The default prefab to be used to create player objects on the server. + // Player objects are created in the default handler for AddPlayer() on + // the server. Implementing OnServerAddPlayer overrides this behaviour. + [Header("Player Object")] + [FormerlySerializedAs("m_PlayerPrefab")] + [Tooltip("Prefab of the player object. Prefab must have a Network Identity component. May be an empty game object or a full avatar.")] + public GameObject playerPrefab; + + /// Enable to automatically create player objects on connect and on scene change. + [FormerlySerializedAs("m_AutoCreatePlayer")] + [Tooltip("Should Mirror automatically spawn the player after scene change?")] + public bool autoCreatePlayer = true; + + /// Where to spawn players. + [FormerlySerializedAs("m_PlayerSpawnMethod")] + [Tooltip("Round Robin or Random order of Start Position selection")] + public PlayerSpawnMethod playerSpawnMethod; + + /// Prefabs that can be spawned over the network need to be registered here. + [FormerlySerializedAs("m_SpawnPrefabs"), HideInInspector] + public List spawnPrefabs = new List(); + + /// List of transforms populated by NetworkStartPositions + public static List startPositions = new List(); + public static int startPositionIndex; + + [Header("Security")] + [Tooltip("For security, it is recommended to disconnect a player if a networked action triggers an exception\nThis could prevent components being accessed in an undefined state, which may be an attack vector for exploits.\nHowever, some games may want to allow exceptions in order to not interrupt the player's experience.")] + public bool exceptionsDisconnect = true; // security by default + + [Header("Snapshot Interpolation")] + public SnapshotInterpolationSettings snapshotSettings = new SnapshotInterpolationSettings(); + + [Header("Connection Quality")] + [Tooltip("Method to use for connection quality evaluation.\nSimple: based on rtt and jitter.\nPragmatic: based on snapshot interpolation adjustment.")] + public ConnectionQualityMethod evaluationMethod; + + [Tooltip("Interval in seconds to evaluate connection quality.\nSet to 0 to disable connection quality evaluation.")] + [Range(0, 60)] + [FormerlySerializedAs("connectionQualityInterval")] + public float evaluationInterval = 3; + + [Header("Debug")] + public bool timeInterpolationGui = false; + + /// The one and only NetworkManager + public static NetworkManager singleton { get; internal set; } + + /// Number of active player objects across all connections on the server. + public int numPlayers => NetworkServer.connections.Count(kv => kv.Value.identity != null); + + /// True if the server is running or client is connected/connecting. + public bool isNetworkActive => NetworkServer.active || NetworkClient.active; + + // TODO remove this + // internal for tests + internal static NetworkConnection clientReadyConnection; + + /// True if the client loaded a new scene when connecting to the server. + // This is set before OnClientConnect is called, so it can be checked + // there to perform different logic if a scene load occurred. + protected bool clientLoadedScene; + + // helper enum to know if we started the networkmanager as server/client/host. + // -> this is necessary because when StartHost changes server scene to + // online scene, FinishLoadScene is called and the host client isn't + // connected yet (no need to connect it before server was fully set up). + // in other words, we need this to know which mode we are running in + // during FinishLoadScene. + public NetworkManagerMode mode { get; private set; } + + // virtual so that inheriting classes' OnValidate() can call base.OnValidate() too + public virtual void OnValidate() + { +#pragma warning disable 618 + // autoStartServerBuild and autoConnectClientBuild are now obsolete, but to avoid + // a breaking change we'll set headlessStartMode to what the user had set before. + // + // headlessStartMode defaults to DoNothing, so if the user had neither of these + // set, then it will remain as DoNothing, and if they set headlessStartMode to + // any selection in the inspector it won't get changed back. + if (autoStartServerBuild) + headlessStartMode = HeadlessStartOptions.AutoStartServer; + else if (autoConnectClientBuild) + headlessStartMode = HeadlessStartOptions.AutoStartClient; + + // Setting both to false here prevents this code from fighting with user + // selection in the inspector, and they're both SerialisedField's. + autoStartServerBuild = false; + autoConnectClientBuild = false; +#pragma warning restore 618 + + // always >= 0 + maxConnections = Mathf.Max(maxConnections, 0); + + if (playerPrefab != null && !playerPrefab.TryGetComponent(out NetworkIdentity _)) + { + Debug.LogError("NetworkManager - Player Prefab must have a NetworkIdentity."); + playerPrefab = null; + } + + // This avoids the mysterious "Replacing existing prefab with assetId ... Old prefab 'Player', New prefab 'Player'" warning. + if (playerPrefab != null && spawnPrefabs.Contains(playerPrefab)) + { + Debug.LogWarning("NetworkManager - Player Prefab doesn't need to be in Spawnable Prefabs list too. Removing it."); + spawnPrefabs.Remove(playerPrefab); + } + } + + // virtual so that inheriting classes' Reset() can call base.Reset() too + // Reset only gets called when the component is added or the user resets the component + // Thats why we validate these things that only need to be validated on adding the NetworkManager here + // If we would do it in OnValidate() then it would run this everytime a value changes + public virtual void Reset() + { + // make sure someone doesn't accidentally add another NetworkManager + // need transform.root because when adding to a child, the parent's + // Reset isn't called. + foreach (NetworkManager manager in transform.root.GetComponentsInChildren()) + { + if (manager != this) + { + Debug.LogError($"{name} detected another component of type {typeof(NetworkManager)} in its hierarchy on {manager.name}. There can only be one, please remove one of them."); + // return early so that transport component isn't auto-added + // to the duplicate NetworkManager. + return; + } + } + } + + // virtual so that inheriting classes' Awake() can call base.Awake() too + public virtual void Awake() + { + // Don't allow collision-destroyed second instance to continue. + if (!InitializeSingleton()) return; + + // Apply configuration in Awake once already + ApplyConfiguration(); + + // Set the networkSceneName to prevent a scene reload + // if client connection to server fails. + networkSceneName = offlineScene; + + // setup OnSceneLoaded callback + SceneManager.sceneLoaded += OnSceneLoaded; + } + + // virtual so that inheriting classes' Start() can call base.Start() too + public virtual void Start() + { + // Auto-start headless server or client. + // + // We can't do this in Awake because Awake is for initialization + // and some transports might not be ready until Start. + // + // Auto-starting in Editor is useful for debugging, so that can + // be enabled with editorAutoStart. + if (Utils.IsHeadless()) + { + if (!Application.isEditor || editorAutoStart) + switch (headlessStartMode) + { + case HeadlessStartOptions.AutoStartServer: + StartServer(); + break; + case HeadlessStartOptions.AutoStartClient: + StartClient(); + break; + } + } + } + + // make sure to call base.Update() when overwriting + public virtual void Update() + { + ApplyConfiguration(); + } + + // virtual so that inheriting classes' LateUpdate() can call base.LateUpdate() too + public virtual void LateUpdate() + { + UpdateScene(); + } + + //////////////////////////////////////////////////////////////////////// + + // keep the online scene change check in a separate function. + // only change scene if the requested online scene is not blank, and is not already loaded. + bool IsServerOnlineSceneChangeNeeded() => + !string.IsNullOrWhiteSpace(onlineScene) && + !Utils.IsSceneActive(onlineScene) && + onlineScene != offlineScene; + + // NetworkManager exposes some NetworkServer/Client configuration. + // we apply it every Update() in order to avoid two sources of truth. + // fixes issues where NetworkServer.sendRate was never set because + // NetworkManager.StartServer was never called, etc. + // => all exposed settings should be applied at all times if NM exists. + void ApplyConfiguration() + { + NetworkServer.tickRate = sendRate; + NetworkClient.snapshotSettings = snapshotSettings; + NetworkClient.connectionQualityInterval = evaluationInterval; + NetworkClient.connectionQualityMethod = evaluationMethod; + } + + // full server setup code, without spawning objects yet + void SetupServer() + { + // Debug.Log("NetworkManager SetupServer"); + InitializeSingleton(); + + // apply settings before initializing anything + NetworkServer.disconnectInactiveConnections = disconnectInactiveConnections; + NetworkServer.disconnectInactiveTimeout = disconnectInactiveTimeout; + NetworkServer.exceptionsDisconnect = exceptionsDisconnect; + + if (runInBackground) + Application.runInBackground = true; + + if (authenticator != null) + { + authenticator.OnStartServer(); + authenticator.OnServerAuthenticated.AddListener(OnServerAuthenticated); + } + + ConfigureHeadlessFrameRate(); + + // start listening to network connections + NetworkServer.Listen(maxConnections); + + // this must be after Listen(), since that registers the default message handlers + RegisterServerMessages(); + + // do not call OnStartServer here yet. + // this is up to the caller. different for server-only vs. host mode. + } + + /// Starts the server, listening for incoming connections. + public void StartServer() + { + if (NetworkServer.active) + { + Debug.LogWarning("Server already started."); + return; + } + + mode = NetworkManagerMode.ServerOnly; + + // StartServer is inherently ASYNCHRONOUS (=doesn't finish immediately) + // + // Here is what it does: + // Listen + // if onlineScene: + // LoadSceneAsync + // ... + // FinishLoadSceneServerOnly + // SpawnObjects + // else: + // SpawnObjects + // + // there is NO WAY to make it synchronous because both LoadSceneAsync + // and LoadScene do not finish loading immediately. as long as we + // have the onlineScene feature, it will be asynchronous! + + SetupServer(); + + // call OnStartServer AFTER Listen, so that NetworkServer.active is + // true and we can call NetworkServer.Spawn in OnStartServer + // overrides. + // (useful for loading & spawning stuff from database etc.) + // + // note: there is no risk of someone connecting after Listen() and + // before OnStartServer() because this all runs in one thread + // and we don't start processing connects until Update. + OnStartServer(); + + // scene change needed? then change scene and spawn afterwards. + if (IsServerOnlineSceneChangeNeeded()) + { + ServerChangeScene(onlineScene); + } + // otherwise spawn directly + else + { + NetworkServer.SpawnObjects(); + } + } + + void SetupClient() + { + InitializeSingleton(); + +#pragma warning disable 618 + // Remove when OnConnectionQualityChanged is removed. + NetworkClient.onConnectionQualityChanged += OnConnectionQualityChanged; +#pragma warning restore 618 + + // apply settings before initializing anything + NetworkClient.exceptionsDisconnect = exceptionsDisconnect; + // NetworkClient.sendRate = clientSendRate; + + if (runInBackground) + Application.runInBackground = true; + + if (authenticator != null) + { + authenticator.OnStartClient(); + authenticator.OnClientAuthenticated.AddListener(OnClientAuthenticated); + } + + } + + /// Starts the client, connects it to the server with networkAddress. + public void StartClient() + { + // Do checks and short circuits before setting anything up. + // If / when we retry, we won't have conflict issues. + if (NetworkClient.active) + { + Debug.LogWarning("Client already started."); + return; + } + + if (string.IsNullOrWhiteSpace(networkAddress)) + { + Debug.LogError("Must set the Network Address field in the manager"); + return; + } + + mode = NetworkManagerMode.ClientOnly; + + SetupClient(); + + // In case this is a headless client... + ConfigureHeadlessFrameRate(); + + RegisterClientMessages(); + + NetworkClient.Connect(networkAddress); + + OnStartClient(); + } + + /// Starts the client, connects it to the server via Uri + public void StartClient(Uri uri) + { + if (NetworkClient.active) + { + Debug.LogWarning("Client already started."); + return; + } + + mode = NetworkManagerMode.ClientOnly; + + SetupClient(); + + RegisterClientMessages(); + + // Debug.Log($"NetworkManager StartClient address:{uri}"); + networkAddress = uri.Host; + + NetworkClient.Connect(uri); + + OnStartClient(); + } + + /// Starts a network "host" - a server and client in the same application. + public void StartHost() + { + if (NetworkServer.active || NetworkClient.active) + { + Debug.LogWarning("Server or Client already started."); + return; + } + + mode = NetworkManagerMode.Host; + + // StartHost is inherently ASYNCHRONOUS (=doesn't finish immediately) + // + // Here is what it does: + // Listen + // ConnectHost + // if onlineScene: + // LoadSceneAsync + // ... + // FinishLoadSceneHost + // FinishStartHost + // SpawnObjects + // StartHostClient <= not guaranteed to happen after SpawnObjects if onlineScene is set! + // ClientAuth + // success: server sends changescene msg to client + // else: + // FinishStartHost + // + // there is NO WAY to make it synchronous because both LoadSceneAsync + // and LoadScene do not finish loading immediately. as long as we + // have the onlineScene feature, it will be asynchronous! + + // setup server first + SetupServer(); + + // scene change needed? then change scene and spawn afterwards. + // => BEFORE host client connects. if client auth succeeds then the + // server tells it to load 'onlineScene'. we can't do that if + // server is still in 'offlineScene'. so load on server first. + if (IsServerOnlineSceneChangeNeeded()) + { + // call FinishStartHost after changing scene. + finishStartHostPending = true; + ServerChangeScene(onlineScene); + } + // otherwise call FinishStartHost directly + else + { + FinishStartHost(); + } + } + + // This may be set true in StartHost and is evaluated in FinishStartHost + bool finishStartHostPending; + + // FinishStartHost is guaranteed to be called after the host server was + // fully started and all the asynchronous StartHost magic is finished + // (= scene loading), or immediately if there was no asynchronous magic. + // + // note: we don't really need FinishStartClient/FinishStartServer. the + // host version is enough. + void FinishStartHost() + { + // ConnectHost needs to be called BEFORE SpawnObjects: + // https://github.com/vis2k/Mirror/pull/1249/ + // -> this sets NetworkServer.localConnection. + // -> localConnection needs to be set before SpawnObjects because: + // -> SpawnObjects calls OnStartServer in all NetworkBehaviours + // -> OnStartServer might spawn an object and set [SyncVar(hook="OnColorChanged")] object.color = green; + // -> this calls SyncVar.set (generated by Weaver), which has + // a custom case for host mode (because host mode doesn't + // get OnDeserialize calls, where SyncVar hooks are usually + // called): + // + // if (!SyncVarEqual(value, ref color)) + // { + // if (NetworkServer.localClientActive && !getSyncVarHookGuard(1uL)) + // { + // setSyncVarHookGuard(1uL, value: true); + // OnColorChangedHook(value); + // setSyncVarHookGuard(1uL, value: false); + // } + // SetSyncVar(value, ref color, 1uL); + // } + // + // -> localClientActive needs to be true, otherwise the hook + // isn't called in host mode! + // + // TODO call this after spawnobjects and worry about the syncvar hook fix later? + NetworkClient.ConnectHost(); + + // invoke user callbacks AFTER ConnectHost has set .activeHost. + // this way initialization can properly handle host mode. + // + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3302 + // where [SyncVar] hooks wouldn't be called for objects spawned in + // NetworkManager.OnStartServer, because .activeHost was still false. + // + // TODO is there a risk of someone connecting between Listen() and FinishStartHost()? + OnStartServer(); + + // call OnStartHost AFTER SetupServer. this way we can use + // NetworkServer.Spawn etc. in there too. just like OnStartServer + // is called after the server is actually properly started. + OnStartHost(); + + // server scene was loaded. now spawn all the objects + NetworkServer.SpawnObjects(); + + // connect client and call OnStartClient AFTER server scene was + // loaded and all objects were spawned. + // DO NOT do this earlier. it would cause race conditions where a + // client will do things before the server is even fully started. + //Debug.Log("StartHostClient called"); + SetupClient(); + RegisterClientMessages(); + + // InvokeOnConnected needs to be called AFTER RegisterClientMessages + // (https://github.com/vis2k/Mirror/pull/1249/) + HostMode.InvokeOnConnected(); + + OnStartClient(); + } + + /// This stops both the client and the server that the manager is using. + public void StopHost() + { + OnStopHost(); + StopClient(); + StopServer(); + } + + /// Stops the server from listening and simulating the game. + public void StopServer() + { + // return if already stopped to avoid recursion deadlock + if (!NetworkServer.active) + return; + + if (authenticator != null) + { + authenticator.OnServerAuthenticated.RemoveListener(OnServerAuthenticated); + authenticator.OnStopServer(); + } + + // Get Network Manager out of DDOL before going to offline scene + // to avoid collision and let a fresh Network Manager be created. + // IMPORTANT: .gameObject can be null if StopClient is called from + // OnApplicationQuit or from tests! + if (gameObject != null + && gameObject.scene.name == "DontDestroyOnLoad" + && !string.IsNullOrWhiteSpace(offlineScene) + && SceneManager.GetActiveScene().path != offlineScene) + SceneManager.MoveGameObjectToScene(gameObject, SceneManager.GetActiveScene()); + + OnStopServer(); + + //Debug.Log("NetworkManager StopServer"); + NetworkServer.Shutdown(); + + // set offline mode BEFORE changing scene so that FinishStartScene + // doesn't think we need initialize anything. + mode = NetworkManagerMode.Offline; + + if (!string.IsNullOrWhiteSpace(offlineScene)) + { + ServerChangeScene(offlineScene); + } + + startPositionIndex = 0; + + networkSceneName = ""; + } + + /// Stops and disconnects the client. + public void StopClient() + { + if (mode == NetworkManagerMode.Offline) + return; + + // For Host client, call OnServerDisconnect before NetworkClient.Disconnect + // because we need NetworkServer.localConnection to not be null + // NetworkClient.Disconnect will set it null. + if (mode == NetworkManagerMode.Host) + OnServerDisconnect(NetworkServer.localConnection); + + // ask client -> transport to disconnect. + // handle voluntary and involuntary disconnects in OnClientDisconnect. + // + // StopClient + // NetworkClient.Disconnect + // Transport.Disconnect + // ... + // Transport.OnClientDisconnect + // NetworkClient.OnTransportDisconnect + // NetworkManager.OnClientDisconnect + NetworkClient.Disconnect(); + +#pragma warning disable 618 + // Remove when OnConnectionQualityChanged is removed. + NetworkClient.onConnectionQualityChanged -= OnConnectionQualityChanged; +#pragma warning restore 618 + + // UNET invoked OnDisconnected cleanup immediately. + // let's keep it for now, in case any projects depend on it. + // TODO simply remove this in the future. + OnClientDisconnectInternal(); + } + + // called when quitting the application by closing the window / pressing + // stop in the editor. virtual so that inheriting classes' + // OnApplicationQuit() can call base.OnApplicationQuit() too + public virtual void OnApplicationQuit() + { + // stop client first + // (we want to send the quit packet to the server instead of waiting + // for a timeout) + if (NetworkClient.isConnected) + { + StopClient(); + //Debug.Log("OnApplicationQuit: stopped client"); + } + + // stop server after stopping client (for proper host mode stopping) + if (NetworkServer.active) + { + StopServer(); + //Debug.Log("OnApplicationQuit: stopped server"); + } + + // Call ResetStatics to reset statics and singleton + ResetStatics(); + } + + /// Set the frame rate for a headless builds. Override to disable or modify. + // useful for dedicated servers. + // useful for headless benchmark clients. + public virtual void ConfigureHeadlessFrameRate() + { + if (Utils.IsHeadless()) + { + Application.targetFrameRate = sendRate; + // Debug.Log($"Server Tick Rate set to {Application.targetFrameRate} Hz."); + } + } + + bool InitializeSingleton() + { + if (singleton != null && singleton == this) + return true; + + if (dontDestroyOnLoad) + { + if (singleton != null) + { + Debug.LogWarning("Multiple NetworkManagers detected in the scene. Only one NetworkManager can exist at a time. The duplicate NetworkManager will be destroyed."); + Destroy(gameObject); + + // Return false to not allow collision-destroyed second instance to continue. + return false; + } + //Debug.Log("NetworkManager created singleton (DontDestroyOnLoad)"); + singleton = this; + if (Application.isPlaying) + { + // Force the object to scene root, in case user made it a child of something + // in the scene since DDOL is only allowed for scene root objects + transform.SetParent(null); + DontDestroyOnLoad(gameObject); + } + } + else + { + //Debug.Log("NetworkManager created singleton (ForScene)"); + singleton = this; + } + + // set active transport AFTER setting singleton. + // so only if we didn't destroy ourselves. + + // This tries to avoid missing transport errors and more clearly tells user what to fix. + if (transport == null) + if (TryGetComponent(out Transport newTransport)) + { + Debug.LogWarning($"No Transport assigned to Network Manager - Using {newTransport} found on same object."); + transport = newTransport; + } + else + { + Debug.LogError("No Transport on Network Manager...add a transport and assign it."); + return false; + } + + Transport.active = transport; + return true; + } + + void RegisterServerMessages() + { + NetworkServer.OnConnectedEvent = OnServerConnectInternal; + NetworkServer.OnDisconnectedEvent = OnServerDisconnect; + NetworkServer.OnErrorEvent = OnServerError; + NetworkServer.RegisterHandler(OnServerAddPlayerInternal); + + // Network Server initially registers its own handler for this, so we replace it here. + NetworkServer.ReplaceHandler(OnServerReadyMessageInternal); + } + + void RegisterClientMessages() + { + NetworkClient.OnConnectedEvent = OnClientConnectInternal; + NetworkClient.OnDisconnectedEvent = OnClientDisconnectInternal; + NetworkClient.OnErrorEvent = OnClientError; + // Don't require authentication because server may send NotReadyMessage from ServerChangeScene + NetworkClient.RegisterHandler(OnClientNotReadyMessageInternal, false); + NetworkClient.RegisterHandler(OnClientSceneInternal, false); + + if (playerPrefab != null) + NetworkClient.RegisterPrefab(playerPrefab); + + foreach (GameObject prefab in spawnPrefabs.Where(t => t != null)) + NetworkClient.RegisterPrefab(prefab); + } + + // This is the only way to clear the singleton, so another instance can be created. + // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + public static void ResetStatics() + { + // call StopHost if we have a singleton + if (singleton) + singleton.StopHost(); + + // reset all statics + startPositions.Clear(); + startPositionIndex = 0; + clientReadyConnection = null; + loadingSceneAsync = null; + networkSceneName = string.Empty; + + // and finally (in case it isn't null already)... + singleton = null; + } + + // virtual so that inheriting classes' OnDestroy() can call base.OnDestroy() too + public virtual void OnDestroy() + { + //Debug.Log("NetworkManager destroyed"); + } + + /// The name of the current network scene. + // set by NetworkManager when changing the scene. + // new clients will automatically load this scene. + // Loading a scene manually won't set it. + public static string networkSceneName { get; protected set; } = ""; + + public static AsyncOperation loadingSceneAsync; + + /// Change the server scene and all client's scenes across the network. + // Called automatically if onlineScene or offlineScene are set, but it + // can be called from user code to switch scenes again while the game is + // in progress. This automatically sets clients to be not-ready during + // the change and ready again to participate in the new scene. + public virtual void ServerChangeScene(string newSceneName) + { + if (string.IsNullOrWhiteSpace(newSceneName)) + { + Debug.LogError("ServerChangeScene empty scene name"); + return; + } + + if (NetworkServer.isLoadingScene && newSceneName == networkSceneName) + { + Debug.LogError($"Scene change is already in progress for {newSceneName}"); + return; + } + + // Throw error if called from client + // Allow changing scene while stopping the server + if (!NetworkServer.active && newSceneName != offlineScene) + { + Debug.LogError("ServerChangeScene can only be called on an active server."); + return; + } + + // Debug.Log($"ServerChangeScene {newSceneName}"); + NetworkServer.SetAllClientsNotReady(); + networkSceneName = newSceneName; + + // Let server prepare for scene change + OnServerChangeScene(newSceneName); + + // set server flag to stop processing messages while changing scenes + // it will be re-enabled in FinishLoadScene. + NetworkServer.isLoadingScene = true; + + loadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName); + + // ServerChangeScene can be called when stopping the server + // when this happens the server is not active so does not need to tell clients about the change + if (NetworkServer.active) + { + // notify all clients about the new scene + NetworkServer.SendToAll(new SceneMessage + { + sceneName = newSceneName + }); + } + + startPositionIndex = 0; + startPositions.Clear(); + } + + // This is only set in ClientChangeScene below...never on server. + // We need to check this in OnClientSceneChanged called from FinishLoadSceneClientOnly + // to prevent AddPlayer message after loading/unloading additive scenes + SceneOperation clientSceneOperation = SceneOperation.Normal; + + internal void ClientChangeScene(string newSceneName, SceneOperation sceneOperation = SceneOperation.Normal, bool customHandling = false) + { + if (string.IsNullOrWhiteSpace(newSceneName)) + { + Debug.LogError("ClientChangeScene empty scene name"); + return; + } + + //Debug.Log($"ClientChangeScene newSceneName: {newSceneName} networkSceneName{networkSceneName}"); + + // Let client prepare for scene change + OnClientChangeScene(newSceneName, sceneOperation, customHandling); + + // After calling OnClientChangeScene, exit if server since server is already doing + // the actual scene change, and we don't need to do it for the host client + if (NetworkServer.active) + return; + + // set client flag to stop processing messages while loading scenes. + // otherwise we would process messages and then lose all the state + // as soon as the load is finishing, causing all kinds of bugs + // because of missing state. + // (client may be null after StopClient etc.) + // Debug.Log("ClientChangeScene: pausing handlers while scene is loading to avoid data loss after scene was loaded."); + NetworkClient.isLoadingScene = true; + + // Cache sceneOperation so we know what was requested by the + // Scene message in OnClientChangeScene and OnClientSceneChanged + clientSceneOperation = sceneOperation; + + // scene handling will happen in overrides of OnClientChangeScene and/or OnClientSceneChanged + // Do not call FinishLoadScene here. Custom handler will assign loadingSceneAsync and we need + // to wait for that to finish. UpdateScene already checks for that to be not null and isDone. + if (customHandling) + return; + + switch (sceneOperation) + { + case SceneOperation.Normal: + loadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName); + break; + case SceneOperation.LoadAdditive: + // Ensure additive scene is not already loaded on client by name or path + // since we don't know which was passed in the Scene message + if (!SceneManager.GetSceneByName(newSceneName).IsValid() && !SceneManager.GetSceneByPath(newSceneName).IsValid()) + loadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName, LoadSceneMode.Additive); + else + { + Debug.LogWarning($"Scene {newSceneName} is already loaded"); + + // Reset the flag that we disabled before entering this switch + NetworkClient.isLoadingScene = false; + } + break; + case SceneOperation.UnloadAdditive: + // Ensure additive scene is actually loaded on client by name or path + // since we don't know which was passed in the Scene message + if (SceneManager.GetSceneByName(newSceneName).IsValid() || SceneManager.GetSceneByPath(newSceneName).IsValid()) + loadingSceneAsync = SceneManager.UnloadSceneAsync(newSceneName, UnloadSceneOptions.UnloadAllEmbeddedSceneObjects); + else + { + Debug.LogWarning($"Cannot unload {newSceneName} with UnloadAdditive operation"); + + // Reset the flag that we disabled before entering this switch + NetworkClient.isLoadingScene = false; + } + break; + } + + // don't change the client's current networkSceneName when loading additive scene content + if (sceneOperation == SceneOperation.Normal) + networkSceneName = newSceneName; + } + + // support additive scene loads: + // NetworkScenePostProcess disables all scene objects on load, and + // * NetworkServer.SpawnObjects enables them again on the server when + // calling OnStartServer + // * NetworkClient.PrepareToSpawnSceneObjects enables them again on the + // client after the server sends ObjectSpawnStartedMessage to client + // in SpawnObserversForConnection. this is only called when the + // client joins, so we need to rebuild scene objects manually again + // TODO merge this with FinishLoadScene()? + void OnSceneLoaded(Scene scene, LoadSceneMode mode) + { + if (mode == LoadSceneMode.Additive) + { + if (NetworkServer.active) + { + // TODO only respawn the server objects from that scene later! + NetworkServer.SpawnObjects(); + // Debug.Log($"Respawned Server objects after additive scene load: {scene.name}"); + } + if (NetworkClient.active) + { + NetworkClient.PrepareToSpawnSceneObjects(); + // Debug.Log($"Rebuild Client spawnableObjects after additive scene load: {scene.name}"); + } + } + } + + void UpdateScene() + { + if (loadingSceneAsync != null && loadingSceneAsync.isDone) + { + //Debug.Log($"ClientChangeScene done readyConn {clientReadyConnection}"); + + // try-finally to guarantee loadingSceneAsync being cleared. + // fixes https://github.com/vis2k/Mirror/issues/2517 where if + // FinishLoadScene throws an exception, loadingSceneAsync would + // never be cleared and this code would run every Update. + try + { + FinishLoadScene(); + } + finally + { + loadingSceneAsync.allowSceneActivation = true; + loadingSceneAsync = null; + } + } + } + + protected void FinishLoadScene() + { + // NOTE: this cannot use NetworkClient.allClients[0] - that client may be for a completely different purpose. + + // process queued messages that we received while loading the scene + //Debug.Log("FinishLoadScene: resuming handlers after scene was loading."); + NetworkServer.isLoadingScene = false; + NetworkClient.isLoadingScene = false; + + // host mode? + if (mode == NetworkManagerMode.Host) + { + FinishLoadSceneHost(); + } + // server-only mode? + else if (mode == NetworkManagerMode.ServerOnly) + { + FinishLoadSceneServerOnly(); + } + // client-only mode? + else if (mode == NetworkManagerMode.ClientOnly) + { + FinishLoadSceneClientOnly(); + } + // otherwise we called it after stopping when loading offline scene. + // do nothing then. + } + + // finish load scene part for host mode. makes code easier and is + // necessary for FinishStartHost later. + // (the 3 things have to happen in that exact order) + void FinishLoadSceneHost() + { + // debug message is very important. if we ever break anything then + // it's very obvious to notice. + //Debug.Log("Finished loading scene in host mode."); + + if (clientReadyConnection != null) + { + clientLoadedScene = true; + clientReadyConnection = null; + } + + // do we need to finish a StartHost() call? + // then call FinishStartHost and let it take care of spawning etc. + if (finishStartHostPending) + { + finishStartHostPending = false; + FinishStartHost(); + + // call OnServerSceneChanged + OnServerSceneChanged(networkSceneName); + + // DO NOT call OnClientSceneChanged here. + // the scene change happened because StartHost loaded the + // server's online scene. it has nothing to do with the client. + // this was not meant as a client scene load, so don't call it. + // + // otherwise AddPlayer would be called twice: + // -> once for client OnConnected + // -> once in OnClientSceneChanged + } + // otherwise we just changed a scene in host mode + else + { + // spawn server objects + NetworkServer.SpawnObjects(); + + // call OnServerSceneChanged + OnServerSceneChanged(networkSceneName); + + if (NetworkClient.isConnected) + OnClientSceneChanged(); + } + } + + // finish load scene part for server-only. . makes code easier and is + // necessary for FinishStartServer later. + void FinishLoadSceneServerOnly() + { + // debug message is very important. if we ever break anything then + // it's very obvious to notice. + //Debug.Log("Finished loading scene in server-only mode."); + + NetworkServer.SpawnObjects(); + OnServerSceneChanged(networkSceneName); + } + + // finish load scene part for client-only. makes code easier and is + // necessary for FinishStartClient later. + void FinishLoadSceneClientOnly() + { + // debug message is very important. if we ever break anything then + // it's very obvious to notice. + //Debug.Log("Finished loading scene in client-only mode."); + + if (clientReadyConnection != null) + { + clientLoadedScene = true; + clientReadyConnection = null; + } + + if (NetworkClient.isConnected) + OnClientSceneChanged(); + } + + /// + /// Registers the transform of a game object as a player spawn location. + /// This is done automatically by NetworkStartPosition components, but can be done manually from user script code. + /// + /// Transform to register. + // Static because it's called from NetworkStartPosition::Awake + // and singleton may not exist yet + public static void RegisterStartPosition(Transform start) + { + // Debug.Log($"RegisterStartPosition: {start.gameObject.name} {start.position}"); + startPositions.Add(start); + + // reorder the list so that round-robin spawning uses the start positions + // in hierarchy order. This assumes all objects with NetworkStartPosition + // component are siblings, either in the scene root or together as children + // under a single parent in the scene. + startPositions = startPositions.OrderBy(transform => transform.GetSiblingIndex()).ToList(); + } + + /// Unregister a Transform from start positions. + // Static because it's called from NetworkStartPosition::OnDestroy + // and singleton may not exist yet + public static void UnRegisterStartPosition(Transform start) + { + //Debug.Log($"UnRegisterStartPosition: {start.name} {start.position}"); + startPositions.Remove(start); + } + + /// Get the next NetworkStartPosition based on the selected PlayerSpawnMethod. + public virtual Transform GetStartPosition() + { + // first remove any dead transforms + startPositions.RemoveAll(t => t == null); + + if (startPositions.Count == 0) + return null; + + if (playerSpawnMethod == PlayerSpawnMethod.Random) + { + return startPositions[UnityEngine.Random.Range(0, startPositions.Count)]; + } + else + { + Transform startPosition = startPositions[startPositionIndex]; + startPositionIndex = (startPositionIndex + 1) % startPositions.Count; + return startPosition; + } + } + + void OnServerConnectInternal(NetworkConnectionToClient conn) + { + //Debug.Log("NetworkManager.OnServerConnectInternal"); + + if (authenticator != null) + { + // we have an authenticator - let it handle authentication + authenticator.OnServerAuthenticate(conn); + } + else + { + // authenticate immediately + OnServerAuthenticated(conn); + } + } + + // called after successful authentication + // TODO do the NetworkServer.OnAuthenticated thing from x branch + void OnServerAuthenticated(NetworkConnectionToClient conn) + { + //Debug.Log("NetworkManager.OnServerAuthenticated"); + + // set connection to authenticated + conn.isAuthenticated = true; + + // proceed with the login handshake by calling OnServerConnect + if (networkSceneName != "" && networkSceneName != offlineScene) + { + SceneMessage msg = new SceneMessage() + { + sceneName = networkSceneName + }; + conn.Send(msg); + } + + OnServerConnect(conn); + } + + void OnServerReadyMessageInternal(NetworkConnectionToClient conn, ReadyMessage msg) + { + //Debug.Log("NetworkManager.OnServerReadyMessageInternal"); + OnServerReady(conn); + } + + void OnServerAddPlayerInternal(NetworkConnectionToClient conn, AddPlayerMessage msg) + { + //Debug.Log("NetworkManager.OnServerAddPlayer"); + + if (autoCreatePlayer && playerPrefab == null) + { + Debug.LogError("The PlayerPrefab is empty on the NetworkManager. Please setup a PlayerPrefab object."); + return; + } + + if (autoCreatePlayer && !playerPrefab.TryGetComponent(out NetworkIdentity _)) + { + Debug.LogError("The PlayerPrefab does not have a NetworkIdentity. Please add a NetworkIdentity to the player prefab."); + return; + } + + if (conn.identity != null) + { + Debug.LogError("There is already a player for this connection."); + return; + } + + OnServerAddPlayer(conn); + } + + void OnClientConnectInternal() + { + //Debug.Log("NetworkManager.OnClientConnectInternal"); + + if (authenticator != null) + { + // we have an authenticator - let it handle authentication + authenticator.OnClientAuthenticate(); + } + else + { + // authenticate immediately + OnClientAuthenticated(); + } + } + + // called after successful authentication + void OnClientAuthenticated() + { + //Debug.Log("NetworkManager.OnClientAuthenticated"); + + // set connection to authenticated + NetworkClient.connection.isAuthenticated = true; + + // Set flag to wait for scene change? + if (string.IsNullOrWhiteSpace(onlineScene) || onlineScene == offlineScene || Utils.IsSceneActive(onlineScene)) + { + clientLoadedScene = false; + } + else + { + // Scene message expected from server. + clientLoadedScene = true; + clientReadyConnection = NetworkClient.connection; + } + + // Call virtual method regardless of whether a scene change is expected or not. + OnClientConnect(); + } + + // Transport callback, invoked after client fully disconnected. + // the call order should always be: + // Disconnect() -> ask Transport -> Transport.OnDisconnected -> Cleanup + void OnClientDisconnectInternal() + { + //Debug.Log("NetworkManager.OnClientDisconnectInternal"); + + // Only let this run once. StopClient in Host mode changes to ServerOnly + if (mode == NetworkManagerMode.ServerOnly || mode == NetworkManagerMode.Offline) + return; + + // user callback + OnClientDisconnect(); + + if (authenticator != null) + { + authenticator.OnClientAuthenticated.RemoveListener(OnClientAuthenticated); + authenticator.OnStopClient(); + } + + // set mode BEFORE changing scene so FinishStartScene doesn't re-initialize anything. + // set mode BEFORE NetworkClient.Disconnect so StopClient only runs once. + // set mode BEFORE OnStopClient so StopClient only runs once. + // If we got here from StopClient in Host mode, change to ServerOnly. + // - If StopHost was called, StopServer will put us in Offline mode. + if (mode == NetworkManagerMode.Host) + mode = NetworkManagerMode.ServerOnly; + else + mode = NetworkManagerMode.Offline; + + //Debug.Log("NetworkManager StopClient"); + OnStopClient(); + + // shutdown client + NetworkClient.Shutdown(); + + // Exit here if we're now in ServerOnly mode (StopClient called in Host mode). + if (mode == NetworkManagerMode.ServerOnly) return; + + // Get Network Manager out of DDOL before going to offline scene + // to avoid collision and let a fresh Network Manager be created. + // IMPORTANT: .gameObject can be null if StopClient is called from + // OnApplicationQuit or from tests! + if (gameObject != null + && gameObject.scene.name == "DontDestroyOnLoad" + && !string.IsNullOrWhiteSpace(offlineScene) + && SceneManager.GetActiveScene().path != offlineScene) + SceneManager.MoveGameObjectToScene(gameObject, SceneManager.GetActiveScene()); + + // If StopHost called in Host mode, StopServer will change scenes after this. + // Check loadingSceneAsync to ensure we don't double-invoke the scene change. + // Check if NetworkServer.active because we can get here via Disconnect before server has started to change scenes. + if (!string.IsNullOrWhiteSpace(offlineScene) && !Utils.IsSceneActive(offlineScene) && loadingSceneAsync == null && !NetworkServer.active) + { + ClientChangeScene(offlineScene, SceneOperation.Normal); + } + + networkSceneName = ""; + } + + void OnClientNotReadyMessageInternal(NotReadyMessage msg) + { + //Debug.Log("NetworkManager.OnClientNotReadyMessageInternal"); + NetworkClient.ready = false; + OnClientNotReady(); + + // NOTE: clientReadyConnection is not set here! don't want OnClientConnect to be invoked again after scene changes. + } + + void OnClientSceneInternal(SceneMessage msg) + { + //Debug.Log("NetworkManager.OnClientSceneInternal"); + + // This needs to run for host client too. NetworkServer.active is checked there + if (NetworkClient.isConnected) + { + ClientChangeScene(msg.sceneName, msg.sceneOperation, msg.customHandling); + } + } + + /// Called on the server when a new client connects. + public virtual void OnServerConnect(NetworkConnectionToClient conn) { } + + /// Called on the server when a client disconnects. + // Called by NetworkServer.OnTransportDisconnect! + public virtual void OnServerDisconnect(NetworkConnectionToClient conn) + { + // by default, this function destroys the connection's player. + // can be overwritten for cases like delayed logouts in MMOs to + // avoid players escaping from PvP situations by logging out. + NetworkServer.DestroyPlayerForConnection(conn); + //Debug.Log("OnServerDisconnect: Client disconnected."); + } + + /// Called on the server when a client is ready (= loaded the scene) + public virtual void OnServerReady(NetworkConnectionToClient conn) + { + if (conn.identity == null) + { + // this is now allowed (was not for a while) + //Debug.Log("Ready with no player object"); + } + NetworkServer.SetClientReady(conn); + } + + /// Called on server when a client requests to add the player. Adds playerPrefab by default. Can be overwritten. + // The default implementation for this function creates a new player object from the playerPrefab. + public virtual void OnServerAddPlayer(NetworkConnectionToClient conn) + { + Transform startPos = GetStartPosition(); + GameObject player = startPos != null + ? Instantiate(playerPrefab, startPos.position, startPos.rotation) + : Instantiate(playerPrefab); + + // instantiating a "Player" prefab gives it the name "Player(clone)" + // => appending the connectionId is WAY more useful for debugging! + player.name = $"{playerPrefab.name} [connId={conn.connectionId}]"; + NetworkServer.AddPlayerForConnection(conn, player); + } + + /// Called on server when transport raises an exception. NetworkConnection may be null. + public virtual void OnServerError(NetworkConnectionToClient conn, TransportError error, string reason) { } + + /// Called from ServerChangeScene immediately before SceneManager.LoadSceneAsync is executed + public virtual void OnServerChangeScene(string newSceneName) { } + + /// Called on server after a scene load with ServerChangeScene() is completed. + public virtual void OnServerSceneChanged(string sceneName) { } + + /// Called on the client when connected to a server. By default it sets client as ready and adds a player. + public virtual void OnClientConnect() + { + // OnClientConnect by default calls AddPlayer but it should not do + // that when we have online/offline scenes. so we need the + // clientLoadedScene flag to prevent it. + if (!clientLoadedScene) + { + // Ready/AddPlayer is usually triggered by a scene load completing. + // if no scene was loaded, then Ready/AddPlayer it here instead. + if (!NetworkClient.ready) + NetworkClient.Ready(); + + if (autoCreatePlayer) + NetworkClient.AddPlayer(); + } + } + + /// Called on clients when disconnected from a server. + public virtual void OnClientDisconnect() { } + + // Deprecated 2023-12-05 + /// Deprecated: NetworkClient handles this now. + [Obsolete("NetworkClient handles this now.")] + public virtual void CalculateConnectionQuality() + { + // Moved to NetworkClient + } + + // Deprecated 2023-12-05 + /// Deprecated: NetworkClient handles this now. + [Obsolete("This will be removed. Subscribe to NetworkClient.onConnectionQualityChanged in your own code")] + public virtual void OnConnectionQualityChanged(ConnectionQuality previous, ConnectionQuality current) + { + // logging the change is very useful to track down user's lag reports. + // we want to include as much detail as possible for debugging. + //Debug.Log($"[Mirror] Connection Quality changed from {previous} to {current}:\n rtt={(NetworkTime.rtt * 1000):F1}ms\n rttVar={(NetworkTime.rttVariance * 1000):F1}ms\n bufferTime={(NetworkClient.bufferTime * 1000):F1}ms"); + } + + /// Called on client when transport raises an exception. + public virtual void OnClientError(TransportError error, string reason) { } + + /// Called on clients when a servers tells the client it is no longer ready, e.g. when switching scenes. + public virtual void OnClientNotReady() { } + + /// Called from ClientChangeScene immediately before SceneManager.LoadSceneAsync is executed + // customHandling: indicates if scene loading will be handled through overrides + public virtual void OnClientChangeScene(string newSceneName, SceneOperation sceneOperation, bool customHandling) { } + + /// Called on clients when a scene has completed loaded, when the scene load was initiated by the server. + // Scene changes can cause player objects to be destroyed. The default + // implementation of OnClientSceneChanged in the NetworkManager is to + // add a player object for the connection if no player object exists. + public virtual void OnClientSceneChanged() + { + // always become ready. + if (NetworkClient.connection.isAuthenticated && !NetworkClient.ready) NetworkClient.Ready(); + + // Only call AddPlayer for normal scene changes, not additive load/unload + if (NetworkClient.connection.isAuthenticated && clientSceneOperation == SceneOperation.Normal && autoCreatePlayer && NetworkClient.localPlayer == null) + { + // add player if existing one is null + NetworkClient.AddPlayer(); + } + } + + // Since there are multiple versions of StartServer, StartClient and + // StartHost, to reliably customize their functionality, users would + // need override all the versions. Instead these callbacks are invoked + // from all versions, so users only need to implement this one case. + + /// This is invoked when a host is started. + public virtual void OnStartHost() { } + + /// This is invoked when a server is started - including when a host is started. + public virtual void OnStartServer() { } + + /// This is invoked when the client is started. + public virtual void OnStartClient() { } + + /// This is called when a server is stopped - including when a host is stopped. + public virtual void OnStopServer() { } + + /// This is called when a client is stopped. + public virtual void OnStopClient() { } + + /// This is called when a host is stopped. + public virtual void OnStopHost() { } + + // keep OnGUI even in builds. useful to debug snap interp. + void OnGUI() + { + if (!timeInterpolationGui) return; + NetworkClient.OnGUI(); + } + } +} diff --git a/Assets/Mirror/Core/NetworkManager.cs.meta b/Assets/Mirror/Core/NetworkManager.cs.meta new file mode 100644 index 0000000..0a7564a --- /dev/null +++ b/Assets/Mirror/Core/NetworkManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8aab4c8111b7c411b9b92cf3dbc5bd4e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkManagerHUD.cs b/Assets/Mirror/Core/NetworkManagerHUD.cs new file mode 100644 index 0000000..62a126b --- /dev/null +++ b/Assets/Mirror/Core/NetworkManagerHUD.cs @@ -0,0 +1,162 @@ +using UnityEngine; + +namespace Mirror +{ + /// Shows NetworkManager controls in a GUI at runtime. + [DisallowMultipleComponent] + [AddComponentMenu("Network/Network Manager HUD")] + [RequireComponent(typeof(NetworkManager))] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-manager-hud")] + public class NetworkManagerHUD : MonoBehaviour + { + NetworkManager manager; + + public int offsetX; + public int offsetY; + + void Awake() + { + manager = GetComponent(); + } + + void OnGUI() + { + // If this width is changed, also change offsetX in GUIConsole::OnGUI + int width = 300; + + GUILayout.BeginArea(new Rect(10 + offsetX, 40 + offsetY, width, 9999)); + + if (!NetworkClient.isConnected && !NetworkServer.active) + StartButtons(); + else + StatusLabels(); + + if (NetworkClient.isConnected && !NetworkClient.ready) + { + if (GUILayout.Button("Client Ready")) + { + // client ready + NetworkClient.Ready(); + if (NetworkClient.localPlayer == null) + NetworkClient.AddPlayer(); + } + } + + StopButtons(); + + GUILayout.EndArea(); + } + + void StartButtons() + { + if (!NetworkClient.active) + { +#if UNITY_WEBGL + // cant be a server in webgl build + if (GUILayout.Button("Single Player")) + { + NetworkServer.dontListen = true; + manager.StartHost(); + } +#else + // Server + Client + if (GUILayout.Button("Host (Server + Client)")) + manager.StartHost(); +#endif + + // Client + IP (+ PORT) + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("Client")) + manager.StartClient(); + + manager.networkAddress = GUILayout.TextField(manager.networkAddress); + // only show a port field if we have a port transport + // we can't have "IP:PORT" in the address field since this only + // works for IPV4:PORT. + // for IPV6:PORT it would be misleading since IPV6 contains ":": + // 2001:0db8:0000:0000:0000:ff00:0042:8329 + if (Transport.active is PortTransport portTransport) + { + // use TryParse in case someone tries to enter non-numeric characters + if (ushort.TryParse(GUILayout.TextField(portTransport.Port.ToString()), out ushort port)) + portTransport.Port = port; + } + + GUILayout.EndHorizontal(); + + // Server Only +#if UNITY_WEBGL + // cant be a server in webgl build + GUILayout.Box("( WebGL cannot be server )"); +#else + if (GUILayout.Button("Server Only")) + manager.StartServer(); +#endif + } + else + { + // Connecting + GUILayout.Label($"Connecting to {manager.networkAddress}.."); + if (GUILayout.Button("Cancel Connection Attempt")) + manager.StopClient(); + } + } + + void StatusLabels() + { + // host mode + // display separately because this always confused people: + // Server: ... + // Client: ... + if (NetworkServer.active && NetworkClient.active) + { + // host mode + GUILayout.Label($"Host: running via {Transport.active}"); + } + else if (NetworkServer.active) + { + // server only + GUILayout.Label($"Server: running via {Transport.active}"); + } + else if (NetworkClient.isConnected) + { + // client only + GUILayout.Label($"Client: connected to {manager.networkAddress} via {Transport.active}"); + } + } + + void StopButtons() + { + if (NetworkServer.active && NetworkClient.isConnected) + { + GUILayout.BeginHorizontal(); +#if UNITY_WEBGL + if (GUILayout.Button("Stop Single Player")) + manager.StopHost(); +#else + // stop host if host mode + if (GUILayout.Button("Stop Host")) + manager.StopHost(); + + // stop client if host mode, leaving server up + if (GUILayout.Button("Stop Client")) + manager.StopClient(); +#endif + GUILayout.EndHorizontal(); + } + else if (NetworkClient.isConnected) + { + // stop client if client-only + if (GUILayout.Button("Stop Client")) + manager.StopClient(); + } + else if (NetworkServer.active) + { + // stop server if server-only + if (GUILayout.Button("Stop Server")) + manager.StopServer(); + } + } + } +} diff --git a/Assets/Mirror/Core/NetworkManagerHUD.cs.meta b/Assets/Mirror/Core/NetworkManagerHUD.cs.meta new file mode 100644 index 0000000..a720b9c --- /dev/null +++ b/Assets/Mirror/Core/NetworkManagerHUD.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6442dc8070ceb41f094e44de0bf87274 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkMessage.cs b/Assets/Mirror/Core/NetworkMessage.cs new file mode 100644 index 0000000..7fc387a --- /dev/null +++ b/Assets/Mirror/Core/NetworkMessage.cs @@ -0,0 +1,4 @@ +namespace Mirror +{ + public interface NetworkMessage {} +} diff --git a/Assets/Mirror/Core/NetworkMessage.cs.meta b/Assets/Mirror/Core/NetworkMessage.cs.meta new file mode 100644 index 0000000..73d3d8f --- /dev/null +++ b/Assets/Mirror/Core/NetworkMessage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb04e4848a2e4452aa2dbd7adb801c51 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkMessages.cs b/Assets/Mirror/Core/NetworkMessages.cs new file mode 100644 index 0000000..7a70d94 --- /dev/null +++ b/Assets/Mirror/Core/NetworkMessages.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; +using UnityEngine; + +namespace Mirror +{ + // for performance, we (ab)use c# generics to cache the message id in a static field + // this is significantly faster than doing the computation at runtime or looking up cached results via Dictionary + // generic classes have separate static fields per type specification + public static class NetworkMessageId where T : struct, NetworkMessage + { + // automated message id from type hash. + // platform independent via stable hashcode. + // => convenient so we don't need to track messageIds across projects + // => addons can work with each other without knowing their ids before + // => 2 bytes is enough to avoid collisions. + // registering a messageId twice will log a warning anyway. + public static readonly ushort Id = CalculateId(); + + // Gets the 32bit fnv1a hash + // To get it down to 16bit but still reduce hash collisions we cant just cast it to ushort + // Instead we take the highest 16bits of the 32bit hash and fold them with xor into the lower 16bits + // This will create a more uniform 16bit hash, the method is described in: + // http://www.isthe.com/chongo/tech/comp/fnv/ in section "Changing the FNV hash size - xor-folding" + static ushort CalculateId() => typeof(T).FullName.GetStableHashCode16(); + } + + // message packing all in one place, instead of constructing headers in all + // kinds of different places + // + // MsgType (2 bytes) + // Content (ContentSize bytes) + public static class NetworkMessages + { + // size of message id header in bytes + public const int IdSize = sizeof(ushort); + + // Id <> Type lookup for debugging, profiler, etc. + // important when debugging messageId errors! + public static readonly Dictionary Lookup = + new Dictionary(); + + // dump all types for debugging + public static void LogTypes() + { + StringBuilder builder = new StringBuilder(); + builder.AppendLine("NetworkMessageIds:"); + foreach (KeyValuePair kvp in Lookup) + { + builder.AppendLine($" Id={kvp.Key} = {kvp.Value}"); + } + Debug.Log(builder.ToString()); + } + + // max message content size (without header) calculation for convenience + // -> Transport.GetMaxPacketSize is the raw maximum + // -> Every message gets serialized into <> + // -> Every serialized message get put into a batch with one timestamp per batch + // -> Every message in a batch has a varuint size header. + // use the worst case VarUInt size for the largest possible + // message size = int.max. + public static int MaxContentSize(int channelId) + { + // calculate the max possible size that can fit in a batch + int transportMax = Transport.active.GetMaxPacketSize(channelId); + return transportMax - IdSize - Batcher.MaxMessageOverhead(transportMax); + } + + // max message size which includes header + content. + public static int MaxMessageSize(int channelId) => + MaxContentSize(channelId) + IdSize; + + // automated message id from type hash. + // platform independent via stable hashcode. + // => convenient so we don't need to track messageIds across projects + // => addons can work with each other without knowing their ids before + // => 2 bytes is enough to avoid collisions. + // registering a messageId twice will log a warning anyway. + // keep this for convenience. easier to use than NetworkMessageId.Id. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ushort GetId() where T : struct, NetworkMessage => + NetworkMessageId.Id; + + // pack message before sending + // -> NetworkWriter passed as arg so that we can use .ToArraySegment + // and do an allocation free send before recycling it. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Pack(T message, NetworkWriter writer) + where T : struct, NetworkMessage + { + writer.WriteUShort(NetworkMessageId.Id); + writer.Write(message); + } + + // read only the message id. + // common function in case we ever change the header size. + public static bool UnpackId(NetworkReader reader, out ushort messageId) + { + // read message type + try + { + messageId = reader.ReadUShort(); + return true; + } + catch (System.IO.EndOfStreamException) + { + messageId = 0; + return false; + } + } + + // version for handlers with channelId + // inline! only exists for 20-30 messages and they call it all the time. + internal static NetworkMessageDelegate WrapHandler(Action handler, bool requireAuthentication, bool exceptionsDisconnect) + where T : struct, NetworkMessage + where C : NetworkConnection + => (conn, reader, channelId) => + { + // protect against DOS attacks if attackers try to send invalid + // data packets to crash the server/client. there are a thousand + // ways to cause an exception in data handling: + // - invalid headers + // - invalid message ids + // - invalid data causing exceptions + // - negative ReadBytesAndSize prefixes + // - invalid utf8 strings + // - etc. + // + // let's catch them all and then disconnect that connection to avoid + // further attacks. + T message = default; + // record start position for NetworkDiagnostics because reader might contain multiple messages if using batching + int startPos = reader.Position; + try + { + if (requireAuthentication && !conn.isAuthenticated) + { + // message requires authentication, but the connection was not authenticated + Debug.LogWarning($"Disconnecting connection: {conn}. Received message {typeof(T)} that required authentication, but the user has not authenticated yet"); + conn.Disconnect(); + return; + } + + //Debug.Log($"ConnectionRecv {conn} msgType:{typeof(T)} content:{BitConverter.ToString(reader.buffer.Array, reader.buffer.Offset, reader.buffer.Count)}"); + + // if it is a value type, just use default(T) + // otherwise allocate a new instance + message = reader.Read(); + } + catch (Exception exception) + { + // should we disconnect on exceptions? + if (exceptionsDisconnect) + { + Debug.LogError($"Disconnecting connection: {conn} because reading a message of type {typeof(T)} caused an Exception. This can happen if the other side accidentally (or an attacker intentionally) sent invalid data. Reason: {exception}"); + conn.Disconnect(); + return; + } + // otherwise log it but allow the connection to keep playing + else + { + Debug.LogError($"Caught an Exception when reading a message from: {conn} of type {typeof(T)}. Reason: {exception}"); + return; + } + } + finally + { + int endPos = reader.Position; + // TODO: Figure out the correct channel + NetworkDiagnostics.OnReceive(message, channelId, endPos - startPos); + } + + // user handler exception should not stop the whole server + try + { + // user implemented handler + handler((C)conn, message, channelId); + } + catch (Exception exception) + { + // should we disconnect on exceptions? + if (exceptionsDisconnect) + { + Debug.LogError($"Disconnecting connection: {conn} because handling a message of type {typeof(T)} caused an Exception. This can happen if the other side accidentally (or an attacker intentionally) sent invalid data. Reason: {exception}"); + conn.Disconnect(); + } + // otherwise log it but allow the connection to keep playing + else + { + Debug.LogError($"Caught an Exception when handling a message from: {conn} of type {typeof(T)}. Reason: {exception}"); + } + } + }; + + // version for handlers without channelId + // TODO obsolete this some day to always use the channelId version. + // all handlers in this version are wrapped with 1 extra action. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static NetworkMessageDelegate WrapHandler(Action handler, bool requireAuthentication, bool exceptionsDisconnect) + where T : struct, NetworkMessage + where C : NetworkConnection + { + // wrap action as channelId version, call original + void Wrapped(C conn, T msg, int _) => handler(conn, msg); + return WrapHandler((Action)Wrapped, requireAuthentication, exceptionsDisconnect); + } + } +} diff --git a/Assets/Mirror/Core/NetworkMessages.cs.meta b/Assets/Mirror/Core/NetworkMessages.cs.meta new file mode 100644 index 0000000..910b75c --- /dev/null +++ b/Assets/Mirror/Core/NetworkMessages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2db134099f0df4d96a84ae7a0cd9b4bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkReader.cs b/Assets/Mirror/Core/NetworkReader.cs new file mode 100644 index 0000000..82fb7cd --- /dev/null +++ b/Assets/Mirror/Core/NetworkReader.cs @@ -0,0 +1,249 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text; +using Unity.Collections.LowLevel.Unsafe; +using UnityEngine; + +namespace Mirror +{ + /// Network Reader for most simple types like floats, ints, buffers, structs, etc. Use NetworkReaderPool.GetReader() to avoid allocations. + // Note: This class is intended to be extremely pedantic, + // and throw exceptions whenever stuff is going slightly wrong. + // The exceptions will be handled in NetworkServer/NetworkClient. + // + // Note that NetworkWriter can be passed in constructor thanks to implicit + // ArraySegment conversion: + // NetworkReader reader = new NetworkReader(writer); + public class NetworkReader + { + // internal buffer + // byte[] pointer would work, but we use ArraySegment to also support + // the ArraySegment constructor + internal ArraySegment buffer; + + /// Next position to read from the buffer + // 'int' is the best type for .Position. 'short' is too small if we send >32kb which would result in negative .Position + // -> converting long to int is fine until 2GB of data (MAX_INT), so we don't have to worry about overflows here + public int Position; + + /// Remaining bytes that can be read, for convenience. + public int Remaining => buffer.Count - Position; + + /// Total buffer capacity, independent of reader position. + public int Capacity => buffer.Count; + + // cache encoding for ReadString instead of creating it with each time + // 1000 readers before: 1MB GC, 30ms + // 1000 readers after: 0.8MB GC, 18ms + // member(!) to avoid static state. + // + // throwOnInvalidBytes is true. + // if false, it would silently ignore the invalid bytes but continue + // with the valid ones, creating strings like "a�������". + // instead, we want to catch it manually and return String.Empty. + // this is safer. see test: ReadString_InvalidUTF8(). + internal readonly UTF8Encoding encoding = new UTF8Encoding(false, true); + + // while allocation free ReadArraySegment is encouraged, + // some functions can allocate a new byte[], List, Texture, etc. + // we should keep a reasonable allocation size limit: + // -> server won't accidentally allocate 2GB on a mobile device + // -> client won't allocate 2GB on server for ClientToServer [SyncVar]s + // -> unlike max string length of 64 KB, we need a larger limit here. + // large enough to not break existing projects, + // small enough to reasonably limit allocation attacks. + // -> we don't know the exact size of ReadList etc. because is + // managed. instead, this is considered a 'collection length' limit. + public const int AllocationLimit = 1024 * 1024 * 16; // 16 MB * sizeof(T) + + public NetworkReader(ArraySegment segment) + { + buffer = segment; + } + +#if !UNITY_2021_3_OR_NEWER + // Unity 2019 doesn't have the implicit byte[] to segment conversion yet + public NetworkReader(byte[] bytes) + { + buffer = new ArraySegment(bytes, 0, bytes.Length); + } +#endif + + // sometimes it's useful to point a reader on another buffer instead of + // allocating a new reader (e.g. NetworkReaderPool) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetBuffer(ArraySegment segment) + { + buffer = segment; + Position = 0; + } + +#if !UNITY_2021_3_OR_NEWER + // Unity 2019 doesn't have the implicit byte[] to segment conversion yet + public void SetBuffer(byte[] bytes) + { + buffer = new ArraySegment(bytes, 0, bytes.Length); + Position = 0; + } +#endif + + // ReadBlittable from DOTSNET + // this is extremely fast, but only works for blittable types. + // => private to make sure nobody accidentally uses it for non-blittable + // + // Benchmark: see NetworkWriter.WriteBlittable! + // + // Note: + // ReadBlittable assumes same endianness for server & client. + // All Unity 2018+ platforms are little endian. + // + // This is not safe to expose to random structs. + // * StructLayout.Sequential is the default, which is safe. + // if the struct contains a reference type, it is converted to Auto. + // but since all structs here are unmanaged blittable, it's safe. + // see also: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=netframework-4.8#system-runtime-interopservices-layoutkind-sequential + // * StructLayout.Pack depends on CPU word size. + // this may be different 4 or 8 on some ARM systems, etc. + // this is not safe, and would cause bytes/shorts etc. to be padded. + // see also: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.structlayoutattribute.pack?view=net-6.0 + // * If we force pack all to '1', they would have no padding which is + // great for bandwidth. but on some android systems, CPU can't read + // unaligned memory. + // see also: https://github.com/vis2k/Mirror/issues/3044 + // * The only option would be to force explicit layout with multiples + // of word size. but this requires lots of weaver checking and is + // still questionable (IL2CPP etc.). + // + // Note: inlining ReadBlittable is enough. don't inline ReadInt etc. + // we don't want ReadBlittable to be copied in place everywhere. + internal unsafe T ReadBlittable() + where T : unmanaged + { + // check if blittable for safety +#if UNITY_EDITOR + if (!UnsafeUtility.IsBlittable(typeof(T))) + { + throw new ArgumentException($"{typeof(T)} is not blittable!"); + } +#endif + + // calculate size + // sizeof(T) gets the managed size at compile time. + // Marshal.SizeOf gets the unmanaged size at runtime (slow). + // => our 1mio writes benchmark is 6x slower with Marshal.SizeOf + // => for blittable types, sizeof(T) is even recommended: + // https://docs.microsoft.com/en-us/dotnet/standard/native-interop/best-practices + int size = sizeof(T); + + // ensure remaining + if (Remaining < size) + { + throw new EndOfStreamException($"ReadBlittable<{typeof(T)}> not enough data in buffer to read {size} bytes: {ToString()}"); + } + + // read blittable + T value; + fixed (byte* ptr = &buffer.Array[buffer.Offset + Position]) + { +#if UNITY_ANDROID + // on some android systems, reading *(T*)ptr throws a NRE if + // the ptr isn't aligned (i.e. if Position is 1,2,3,5, etc.). + // here we have to use memcpy. + // + // => we can't get a pointer of a struct in C# without + // marshalling allocations + // => instead, we stack allocate an array of type T and use that + // => stackalloc avoids GC and is very fast. it only works for + // value types, but all blittable types are anyway. + // + // this way, we can still support blittable reads on android. + // see also: https://github.com/vis2k/Mirror/issues/3044 + // (solution discovered by AIIO, FakeByte, mischa) + T* valueBuffer = stackalloc T[1]; + UnsafeUtility.MemCpy(valueBuffer, ptr, size); + value = valueBuffer[0]; +#else + // cast buffer to a T* pointer and then read from it. + value = *(T*)ptr; +#endif + } + Position += size; + return value; + } + + // blittable'?' template for code reuse + // note: bool isn't blittable. need to read as byte. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal T? ReadBlittableNullable() + where T : unmanaged => + ReadByte() != 0 ? ReadBlittable() : default(T?); + + public byte ReadByte() => ReadBlittable(); + + /// Read 'count' bytes into the bytes array + // NOTE: returns byte[] because all reader functions return something. + public byte[] ReadBytes(byte[] bytes, int count) + { + // user may call ReadBytes(ReadInt()). ensure positive count. + if (count < 0) throw new ArgumentOutOfRangeException("ReadBytes requires count >= 0"); + + // check if passed byte array is big enough + if (count > bytes.Length) + { + throw new EndOfStreamException($"ReadBytes can't read {count} + bytes because the passed byte[] only has length {bytes.Length}"); + } + // ensure remaining + if (Remaining < count) + { + throw new EndOfStreamException($"ReadBytesSegment can't read {count} bytes because it would read past the end of the stream. {ToString()}"); + } + + Array.Copy(buffer.Array, buffer.Offset + Position, bytes, 0, count); + Position += count; + return bytes; + } + + /// Read 'count' bytes allocation-free as ArraySegment that points to the internal array. + public ArraySegment ReadBytesSegment(int count) + { + // user may call ReadBytes(ReadInt()). ensure positive count. + if (count < 0) throw new ArgumentOutOfRangeException("ReadBytesSegment requires count >= 0"); + + // ensure remaining + if (Remaining < count) + { + throw new EndOfStreamException($"ReadBytesSegment can't read {count} bytes because it would read past the end of the stream. {ToString()}"); + } + + // return the segment + ArraySegment result = new ArraySegment(buffer.Array, buffer.Offset + Position, count); + Position += count; + return result; + } + + /// Reads any data type that mirror supports. Uses weaver populated Reader(T).read + public T Read() + { + Func readerDelegate = Reader.read; + if (readerDelegate == null) + { + Debug.LogError($"No reader found for {typeof(T)}. Use a type supported by Mirror or define a custom reader extension for {typeof(T)}."); + return default; + } + return readerDelegate(this); + } + + // print the full buffer with position / capacity. + public override string ToString() => + $"[{buffer.ToHexString()} @ {Position}/{Capacity}]"; + } + + /// Helper class that weaver populates with all reader types. + // Note that c# creates a different static variable for each type + // -> Weaver.ReaderWriterProcessor.InitializeReaderAndWriters() populates it + public static class Reader + { + public static Func read; + } +} diff --git a/Assets/Mirror/Core/NetworkReader.cs.meta b/Assets/Mirror/Core/NetworkReader.cs.meta new file mode 100644 index 0000000..65ad3f0 --- /dev/null +++ b/Assets/Mirror/Core/NetworkReader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1610f05ec5bd14d6882e689f7372596a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs b/Assets/Mirror/Core/NetworkReaderExtensions.cs new file mode 100644 index 0000000..4493be3 --- /dev/null +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs @@ -0,0 +1,388 @@ +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; + +namespace Mirror +{ + // Mirror's Weaver automatically detects all NetworkReader function types, + // but they do all need to be extensions. + public static class NetworkReaderExtensions + { + public static byte ReadByte(this NetworkReader reader) => reader.ReadBlittable(); + public static byte? ReadByteNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static sbyte ReadSByte(this NetworkReader reader) => reader.ReadBlittable(); + public static sbyte? ReadSByteNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + // bool is not blittable. read as ushort. + public static char ReadChar(this NetworkReader reader) => (char)reader.ReadBlittable(); + public static char? ReadCharNullable(this NetworkReader reader) => (char?)reader.ReadBlittableNullable(); + + // bool is not blittable. read as byte. + public static bool ReadBool(this NetworkReader reader) => reader.ReadBlittable() != 0; + public static bool? ReadBoolNullable(this NetworkReader reader) + { + byte? value = reader.ReadBlittableNullable(); + return value.HasValue ? (value.Value != 0) : default(bool?); + } + + public static short ReadShort(this NetworkReader reader) => (short)reader.ReadUShort(); + public static short? ReadShortNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static ushort ReadUShort(this NetworkReader reader) => reader.ReadBlittable(); + public static ushort? ReadUShortNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static int ReadInt(this NetworkReader reader) => reader.ReadBlittable(); + public static int? ReadIntNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static uint ReadUInt(this NetworkReader reader) => reader.ReadBlittable(); + public static uint? ReadUIntNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static long ReadLong(this NetworkReader reader) => reader.ReadBlittable(); + public static long? ReadLongNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static ulong ReadULong(this NetworkReader reader) => reader.ReadBlittable(); + public static ulong? ReadULongNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static float ReadFloat(this NetworkReader reader) => reader.ReadBlittable(); + public static float? ReadFloatNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static double ReadDouble(this NetworkReader reader) => reader.ReadBlittable(); + public static double? ReadDoubleNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static decimal ReadDecimal(this NetworkReader reader) => reader.ReadBlittable(); + public static decimal? ReadDecimalNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + /// if an invalid utf8 string is sent + public static string ReadString(this NetworkReader reader) + { + // read number of bytes + ushort size = reader.ReadUShort(); + + // null support, see NetworkWriter + if (size == 0) + return null; + + ushort realSize = (ushort)(size - 1); + + // make sure it's within limits to avoid allocation attacks etc. + if (realSize > NetworkWriter.MaxStringLength) + throw new EndOfStreamException($"NetworkReader.ReadString - Value too long: {realSize} bytes. Limit is: {NetworkWriter.MaxStringLength} bytes"); + + ArraySegment data = reader.ReadBytesSegment(realSize); + + // convert directly from buffer to string via encoding + // throws in case of invalid utf8. + // see test: ReadString_InvalidUTF8() + return reader.encoding.GetString(data.Array, data.Offset, data.Count); + } + + public static byte[] ReadBytes(this NetworkReader reader, int count) + { + // prevent allocation attacks with a reasonable limit. + // server shouldn't allocate too much on client devices. + // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. + if (count > NetworkReader.AllocationLimit) + { + // throw EndOfStream for consistency with ReadBlittable when out of data + throw new EndOfStreamException($"NetworkReader attempted to allocate {count} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); + } + + byte[] bytes = new byte[count]; + reader.ReadBytes(bytes, count); + return bytes; + } + + /// if count is invalid + public static byte[] ReadBytesAndSize(this NetworkReader reader) + { + // count = 0 means the array was null + // otherwise count -1 is the length of the array + uint count = reader.ReadUInt(); + // Use checked() to force it to throw OverflowException if data is invalid + return count == 0 ? null : reader.ReadBytes(checked((int)(count - 1u))); + } + // Reads ArraySegment and size header + /// if count is invalid + public static ArraySegment ReadArraySegmentAndSize(this NetworkReader reader) + { + // count = 0 means the array was null + // otherwise count - 1 is the length of the array + uint count = reader.ReadUInt(); + // Use checked() to force it to throw OverflowException if data is invalid + return count == 0 ? default : reader.ReadBytesSegment(checked((int)(count - 1u))); + } + + public static Vector2 ReadVector2(this NetworkReader reader) => reader.ReadBlittable(); + public static Vector2? ReadVector2Nullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static Vector3 ReadVector3(this NetworkReader reader) => reader.ReadBlittable(); + public static Vector3? ReadVector3Nullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static Vector4 ReadVector4(this NetworkReader reader) => reader.ReadBlittable(); + public static Vector4? ReadVector4Nullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static Vector2Int ReadVector2Int(this NetworkReader reader) => reader.ReadBlittable(); + public static Vector2Int? ReadVector2IntNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static Vector3Int ReadVector3Int(this NetworkReader reader) => reader.ReadBlittable(); + public static Vector3Int? ReadVector3IntNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static Color ReadColor(this NetworkReader reader) => reader.ReadBlittable(); + public static Color? ReadColorNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static Color32 ReadColor32(this NetworkReader reader) => reader.ReadBlittable(); + public static Color32? ReadColor32Nullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static Quaternion ReadQuaternion(this NetworkReader reader) => reader.ReadBlittable(); + public static Quaternion? ReadQuaternionNullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + // Rect is a struct with properties instead of fields + public static Rect ReadRect(this NetworkReader reader) => new Rect(reader.ReadVector2(), reader.ReadVector2()); + public static Rect? ReadRectNullable(this NetworkReader reader) => reader.ReadBool() ? ReadRect(reader) : default(Rect?); + + // Plane is a struct with properties instead of fields + public static Plane ReadPlane(this NetworkReader reader) => new Plane(reader.ReadVector3(), reader.ReadFloat()); + public static Plane? ReadPlaneNullable(this NetworkReader reader) => reader.ReadBool() ? ReadPlane(reader) : default(Plane?); + + // Ray is a struct with properties instead of fields + public static Ray ReadRay(this NetworkReader reader) => new Ray(reader.ReadVector3(), reader.ReadVector3()); + public static Ray? ReadRayNullable(this NetworkReader reader) => reader.ReadBool() ? ReadRay(reader) : default(Ray?); + + // LayerMask is a struct with properties instead of fields + public static LayerMask ReadLayerMask(this NetworkReader reader) + { + // LayerMask doesn't have a constructor that takes an initial value. + // 32 layers as a flags enum, max value of 496, we only need a UShort. + LayerMask layerMask = default; + layerMask.value = reader.ReadUShort(); + return layerMask; + } + + public static LayerMask? ReadLayerMaskNullable(this NetworkReader reader) => reader.ReadBool() ? ReadLayerMask(reader) : default(LayerMask?); + + public static Matrix4x4 ReadMatrix4x4(this NetworkReader reader) => reader.ReadBlittable(); + public static Matrix4x4? ReadMatrix4x4Nullable(this NetworkReader reader) => reader.ReadBlittableNullable(); + + public static Guid ReadGuid(this NetworkReader reader) + { +#if !UNITY_2021_3_OR_NEWER + // Unity 2019 doesn't have Span yet + return new Guid(reader.ReadBytes(16)); +#else + // ReadBlittable(Guid) isn't safe. see ReadBlittable comments. + // Guid is Sequential, but we can't guarantee packing. + if (reader.Remaining >= 16) + { + ReadOnlySpan span = new ReadOnlySpan(reader.buffer.Array, reader.buffer.Offset + reader.Position, 16); + reader.Position += 16; + return new Guid(span); + } + throw new EndOfStreamException($"ReadGuid out of range: {reader}"); +#endif + } + public static Guid? ReadGuidNullable(this NetworkReader reader) => reader.ReadBool() ? ReadGuid(reader) : default(Guid?); + + public static NetworkIdentity ReadNetworkIdentity(this NetworkReader reader) + { + uint netId = reader.ReadUInt(); + if (netId == 0) + return null; + + // NOTE: a netId not being in spawned is common. + // for example, "[SyncVar] NetworkIdentity target" netId would not + // be known on client if the monster walks out of proximity for a + // moment. no need to log any error or warning here. + return Utils.GetSpawnedInServerOrClient(netId); + } + + public static NetworkBehaviour ReadNetworkBehaviour(this NetworkReader reader) + { + // read netId first. + // + // IMPORTANT: if netId != 0, writer always writes componentIndex. + // reusing ReadNetworkIdentity() might return a null NetworkIdentity + // even if netId was != 0 but the identity disappeared on the client, + // resulting in unequal amounts of data being written / read. + // https://github.com/vis2k/Mirror/issues/2972 + uint netId = reader.ReadUInt(); + if (netId == 0) + return null; + + // read component index in any case, BEFORE searching the spawned + // NetworkIdentity by netId. + byte componentIndex = reader.ReadByte(); + + // NOTE: a netId not being in spawned is common. + // for example, "[SyncVar] NetworkIdentity target" netId would not + // be known on client if the monster walks out of proximity for a + // moment. no need to log any error or warning here. + NetworkIdentity identity = Utils.GetSpawnedInServerOrClient(netId); + + return identity != null + ? identity.NetworkBehaviours[componentIndex] + : null; + } + + public static T ReadNetworkBehaviour(this NetworkReader reader) where T : NetworkBehaviour + { + return reader.ReadNetworkBehaviour() as T; + } + + public static NetworkBehaviourSyncVar ReadNetworkBehaviourSyncVar(this NetworkReader reader) + { + uint netId = reader.ReadUInt(); + byte componentIndex = default; + + // if netId is not 0, then index is also sent to read before returning + if (netId != 0) + { + componentIndex = reader.ReadByte(); + } + + return new NetworkBehaviourSyncVar(netId, componentIndex); + } + + public static Transform ReadTransform(this NetworkReader reader) + { + // Don't use null propagation here as it could lead to MissingReferenceException + NetworkIdentity networkIdentity = reader.ReadNetworkIdentity(); + return networkIdentity != null ? networkIdentity.transform : null; + } + + public static GameObject ReadGameObject(this NetworkReader reader) + { + // Don't use null propagation here as it could lead to MissingReferenceException + NetworkIdentity networkIdentity = reader.ReadNetworkIdentity(); + return networkIdentity != null ? networkIdentity.gameObject : null; + } + + // while SyncList is recommended for NetworkBehaviours, + // structs may have .List members which weaver needs to be able to + // fully serialize for NetworkMessages etc. + // note that Weaver/Readers/GenerateReader() handles this manually. + public static List ReadList(this NetworkReader reader) + { + int length = reader.ReadInt(); + + // 'null' is encoded as '-1' + if (length < 0) return null; + + // prevent allocation attacks with a reasonable limit. + // server shouldn't allocate too much on client devices. + // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. + if (length > NetworkReader.AllocationLimit) + { + // throw EndOfStream for consistency with ReadBlittable when out of data + throw new EndOfStreamException($"NetworkReader attempted to allocate a List<{typeof(T)}> {length} elements, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); + } + + List result = new List(length); + for (int i = 0; i < length; i++) + { + result.Add(reader.Read()); + } + return result; + } + + // while SyncSet is recommended for NetworkBehaviours, + // structs may have .Set members which weaver needs to be able to + // fully serialize for NetworkMessages etc. + // note that Weaver/Readers/GenerateReader() handles this manually. + // TODO writer not found. need to adjust weaver first. see tests. + /* + public static HashSet ReadHashSet(this NetworkReader reader) + { + int length = reader.ReadInt(); + if (length < 0) + return null; + HashSet result = new HashSet(); + for (int i = 0; i < length; i++) + { + result.Add(reader.Read()); + } + return result; + } + */ + + public static T[] ReadArray(this NetworkReader reader) + { + int length = reader.ReadInt(); + + // 'null' is encoded as '-1' + if (length < 0) return null; + + // prevent allocation attacks with a reasonable limit. + // server shouldn't allocate too much on client devices. + // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. + if (length > NetworkReader.AllocationLimit) + { + // throw EndOfStream for consistency with ReadBlittable when out of data + throw new EndOfStreamException($"NetworkReader attempted to allocate an Array<{typeof(T)}> with {length} elements, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); + } + + // we can't check if reader.Remaining < length, + // because we don't know sizeof(T) since it's a managed type. + // if (length > reader.Remaining) throw new EndOfStreamException($"Received array that is too large: {length}"); + + T[] result = new T[length]; + for (int i = 0; i < length; i++) + { + result[i] = reader.Read(); + } + return result; + } + + public static Uri ReadUri(this NetworkReader reader) + { + string uriString = reader.ReadString(); + return (string.IsNullOrWhiteSpace(uriString) ? null : new Uri(uriString)); + } + + public static Texture2D ReadTexture2D(this NetworkReader reader) + { + // support 'null' textures for [SyncVar]s etc. + // https://github.com/vis2k/Mirror/issues/3144 + short width = reader.ReadShort(); + if (width == -1) return null; + + // read height + short height = reader.ReadShort(); + + // prevent allocation attacks with a reasonable limit. + // server shouldn't allocate too much on client devices. + // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. + // log an error and return default. + // we don't want attackers to be able to trigger exceptions. + int totalSize = width * height; + if (totalSize > NetworkReader.AllocationLimit) + { + Debug.LogWarning($"NetworkReader attempted to allocate a Texture2D with total size (width * height) of {totalSize}, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); + return null; + } + + Texture2D texture2D = new Texture2D(width, height); + + // read pixel content + Color32[] pixels = reader.ReadArray(); + texture2D.SetPixels32(pixels); + texture2D.Apply(); + return texture2D; + } + + public static Sprite ReadSprite(this NetworkReader reader) + { + // support 'null' textures for [SyncVar]s etc. + // https://github.com/vis2k/Mirror/issues/3144 + Texture2D texture = reader.ReadTexture2D(); + if (texture == null) return null; + + // otherwise create a valid sprite + return Sprite.Create(texture, reader.ReadRect(), reader.ReadVector2()); + } + + public static DateTime ReadDateTime(this NetworkReader reader) => DateTime.FromOADate(reader.ReadDouble()); + public static DateTime? ReadDateTimeNullable(this NetworkReader reader) => reader.ReadBool() ? ReadDateTime(reader) : default(DateTime?); + } +} diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs.meta b/Assets/Mirror/Core/NetworkReaderExtensions.cs.meta new file mode 100644 index 0000000..66536c9 --- /dev/null +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 364a9f7ccd5541e19aa2ae0b81f0b3cf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkReaderPool.cs b/Assets/Mirror/Core/NetworkReaderPool.cs new file mode 100644 index 0000000..d50258a --- /dev/null +++ b/Assets/Mirror/Core/NetworkReaderPool.cs @@ -0,0 +1,45 @@ +// API consistent with Microsoft's ObjectPool. +using System; +using System.Runtime.CompilerServices; + +namespace Mirror +{ + /// Pool of NetworkReaders to avoid allocations. + public static class NetworkReaderPool + { + // reuse Pool + // we still wrap it in NetworkReaderPool.Get/Recyle so we can reset the + // position and array before reusing. + static readonly Pool Pool = new Pool( + // byte[] will be assigned in GetReader + () => new NetworkReaderPooled(new byte[]{}), + // initial capacity to avoid allocations in the first few frames + 1000 + ); + + /// Get the next reader in the pool. If pool is empty, creates a new Reader + public static NetworkReaderPooled Get(byte[] bytes) + { + // grab from pool & set buffer + NetworkReaderPooled reader = Pool.Get(); + reader.SetBuffer(bytes); + return reader; + } + + /// Get the next reader in the pool. If pool is empty, creates a new Reader + public static NetworkReaderPooled Get(ArraySegment segment) + { + // grab from pool & set buffer + NetworkReaderPooled reader = Pool.Get(); + reader.SetBuffer(segment); + return reader; + } + + /// Returns a reader to the pool. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Return(NetworkReaderPooled reader) + { + Pool.Return(reader); + } + } +} diff --git a/Assets/Mirror/Core/NetworkReaderPool.cs.meta b/Assets/Mirror/Core/NetworkReaderPool.cs.meta new file mode 100644 index 0000000..2c94768 --- /dev/null +++ b/Assets/Mirror/Core/NetworkReaderPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2bacff63613ad634a98f9e4d15d29dbf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkReaderPooled.cs b/Assets/Mirror/Core/NetworkReaderPooled.cs new file mode 100644 index 0000000..5348904 --- /dev/null +++ b/Assets/Mirror/Core/NetworkReaderPooled.cs @@ -0,0 +1,15 @@ +// "NetworkReaderPooled" instead of "PooledNetworkReader" to group files, for +// easier IDE workflow and more elegant code. +using System; + +namespace Mirror +{ + /// Pooled NetworkReader, automatically returned to pool when using 'using' + // TODO make sealed again after removing obsolete NetworkReaderPooled! + public class NetworkReaderPooled : NetworkReader, IDisposable + { + internal NetworkReaderPooled(byte[] bytes) : base(bytes) {} + internal NetworkReaderPooled(ArraySegment segment) : base(segment) {} + public void Dispose() => NetworkReaderPool.Return(this); + } +} diff --git a/Assets/Mirror/Core/NetworkReaderPooled.cs.meta b/Assets/Mirror/Core/NetworkReaderPooled.cs.meta new file mode 100644 index 0000000..4eb6e9d --- /dev/null +++ b/Assets/Mirror/Core/NetworkReaderPooled.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: faafa97c32e44adf8e8888de817a370a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkServer.cs b/Assets/Mirror/Core/NetworkServer.cs new file mode 100644 index 0000000..f8d889e --- /dev/null +++ b/Assets/Mirror/Core/NetworkServer.cs @@ -0,0 +1,1981 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Mirror.RemoteCalls; +using UnityEngine; + +namespace Mirror +{ + /// NetworkServer handles remote connections and has a local connection for a local client. + public static partial class NetworkServer + { + static bool initialized; + public static int maxConnections; + + /// Server Update frequency, per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE. + // overwritten by NetworkManager (if any) + public static int tickRate = 60; + + // tick rate is in Hz. + // convert to interval in seconds for convenience where needed. + // + // send interval is 1 / sendRate. + // but for tests we need a way to set it to exactly 0. + // 1 / int.max would not be exactly 0, so handel that manually. + public static float tickInterval => tickRate < int.MaxValue ? 1f / tickRate : 0; // for 30 Hz, that's 33ms + + // time & value snapshot interpolation are separate. + // -> time is interpolated globally on NetworkClient / NetworkConnection + // -> value is interpolated per-component, i.e. NetworkTransform. + // however, both need to be on the same send interval. + public static int sendRate => tickRate; + public static float sendInterval => sendRate < int.MaxValue ? 1f / sendRate : 0; // for 30 Hz, that's 33ms + static double lastSendTime; + + /// Connection to host mode client (if any) + public static LocalConnectionToClient localConnection { get; private set; } + + /// Dictionary of all server connections, with connectionId as key + public static Dictionary connections = + new Dictionary(); + + /// Message Handlers dictionary, with messageId as key + internal static Dictionary handlers = + new Dictionary(); + + /// All spawned NetworkIdentities by netId. + // server sees ALL spawned ones. + public static readonly Dictionary spawned = + new Dictionary(); + + /// Single player mode can use dontListen to not accept incoming connections + // see also: https://github.com/vis2k/Mirror/pull/2595 + public static bool dontListen; + + /// active checks if the server has been started either has standalone or as host server. + public static bool active { get; internal set; } + + /// active checks if the server has been started in host mode. + // naming consistent with NetworkClient.activeHost. + public static bool activeHost => localConnection != null; + + // scene loading + public static bool isLoadingScene; + + // interest management component (optional) + // by default, everyone observes everyone + public static InterestManagementBase aoi; + + // For security, it is recommended to disconnect a player if a networked + // action triggers an exception\nThis could prevent components being + // accessed in an undefined state, which may be an attack vector for + // exploits. + // + // However, some games may want to allow exceptions in order to not + // interrupt the player's experience. + public static bool exceptionsDisconnect = true; // security by default + + // Mirror global disconnect inactive option, independent of Transport. + // not all Transports do this properly, and it's easiest to configure this just once. + // this is very useful for some projects, keep it. + public static bool disconnectInactiveConnections; + public static float disconnectInactiveTimeout = 60; + + // OnConnected / OnDisconnected used to be NetworkMessages that were + // invoked. this introduced a bug where external clients could send + // Connected/Disconnected messages over the network causing undefined + // behaviour. + // => public so that custom NetworkManagers can hook into it + public static Action OnConnectedEvent; + public static Action OnDisconnectedEvent; + public static Action OnErrorEvent; + + // keep track of actual achieved tick rate. + // might become lower under heavy load. + // very useful for profiling etc. + // measured over 1s each, same as frame rate. no EMA here. + public static int actualTickRate; + static double actualTickRateStart; // start time when counting + static int actualTickRateCounter; // current counter since start + + // profiling + // includes transport update time, because transport calls handlers etc. + // averaged over 1s by passing 'tickRate' to constructor. + public static TimeSample earlyUpdateDuration; + public static TimeSample lateUpdateDuration; + + // capture full Unity update time from before Early- to after LateUpdate + public static TimeSample fullUpdateDuration; + + /// Starts server and listens to incoming connections with max connections limit. + public static void Listen(int maxConns) + { + Initialize(); + maxConnections = maxConns; + + // only start server if we want to listen + if (!dontListen) + { + Transport.active.ServerStart(); + + if (Transport.active is PortTransport portTransport) + { + if (Utils.IsHeadless()) + { +#if !UNITY_EDITOR + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine($"Server listening on port {portTransport.Port}"); + Console.ResetColor(); +#else + Debug.Log($"Server listening on port {portTransport.Port}"); +#endif + } + } + else + Debug.Log("Server started listening"); + } + + active = true; + RegisterMessageHandlers(); + } + + // initialization / shutdown /////////////////////////////////////////// + static void Initialize() + { + if (initialized) + return; + + // safety: ensure Weaving succeded. + // if it silently failed, we would get lots of 'writer not found' + // and other random errors at runtime instead. this is cleaner. + if (!WeaverFuse.Weaved()) + { + // if it failed, throw an exception to early exit all Listen calls. + throw new Exception("NetworkServer won't start because Weaving failed or didn't run."); + } + + // Debug.Log($"NetworkServer Created version {Version.Current}"); + + //Make sure connections are cleared in case any old connections references exist from previous sessions + connections.Clear(); + + // reset Interest Management so that rebuild intervals + // start at 0 when starting again. + if (aoi != null) aoi.ResetState(); + + // reset NetworkTime + NetworkTime.ResetStatics(); + + Debug.Assert(Transport.active != null, "There was no active transport when calling NetworkServer.Listen, If you are calling Listen manually then make sure to set 'Transport.active' first"); + AddTransportHandlers(); + + initialized = true; + + // profiling + earlyUpdateDuration = new TimeSample(sendRate); + lateUpdateDuration = new TimeSample(sendRate); + fullUpdateDuration = new TimeSample(sendRate); + } + + static void AddTransportHandlers() + { + // += so that other systems can also hook into it (i.e. statistics) + Transport.active.OnServerConnected += OnTransportConnected; + Transport.active.OnServerDataReceived += OnTransportData; + Transport.active.OnServerDisconnected += OnTransportDisconnected; + Transport.active.OnServerError += OnTransportError; + } + + /// Shuts down the server and disconnects all clients + // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + public static void Shutdown() + { + if (initialized) + { + DisconnectAll(); + + // stop the server. + // we do NOT call Transport.Shutdown, because someone only + // called NetworkServer.Shutdown. we can't assume that the + // client is supposed to be shut down too! + // + // NOTE: stop no matter what, even if 'dontListen': + // someone might enabled dontListen at runtime. + // but we still need to stop the server. + // fixes https://github.com/vis2k/Mirror/issues/2536 + Transport.active.ServerStop(); + + // transport handlers are hooked into when initializing. + // so only remove them when shutting down. + RemoveTransportHandlers(); + + initialized = false; + } + + // Reset all statics here.... + dontListen = false; + isLoadingScene = false; + lastSendTime = 0; + actualTickRate = 0; + + localConnection = null; + + connections.Clear(); + connectionsCopy.Clear(); + handlers.Clear(); + + // destroy all spawned objects, _then_ set inactive. + // make sure .active is still true before calling this. + // otherwise modifying SyncLists in OnStopServer would throw + // because .IsWritable() check checks if NetworkServer.active. + // https://github.com/MirrorNetworking/Mirror/issues/3344 + CleanupSpawned(); + active = false; + + // sets nextNetworkId to 1 + // sets clientAuthorityCallback to null + // sets previousLocalPlayer to null + NetworkIdentity.ResetStatics(); + + // clear events. someone might have hooked into them before, but + // we don't want to use those hooks after Shutdown anymore. + OnConnectedEvent = null; + OnDisconnectedEvent = null; + OnErrorEvent = null; + + if (aoi != null) aoi.ResetState(); + } + + static void RemoveTransportHandlers() + { + // -= so that other systems can also hook into it (i.e. statistics) + Transport.active.OnServerConnected -= OnTransportConnected; + Transport.active.OnServerDataReceived -= OnTransportData; + Transport.active.OnServerDisconnected -= OnTransportDisconnected; + Transport.active.OnServerError -= OnTransportError; + } + + // Note: NetworkClient.DestroyAllClientObjects does the same on client. + static void CleanupSpawned() + { + // iterate a COPY of spawned. + // DestroyObject removes them from the original collection. + // removing while iterating is not allowed. + foreach (NetworkIdentity identity in spawned.Values.ToList()) + { + if (identity != null) + { + // NetworkServer.Destroy resets if scene object, destroys if prefab. + Destroy(identity.gameObject); + } + } + + spawned.Clear(); + } + + internal static void RegisterMessageHandlers() + { + RegisterHandler(OnClientReadyMessage); + RegisterHandler(OnCommandMessage); + RegisterHandler(NetworkTime.OnServerPing, false); + RegisterHandler(NetworkTime.OnServerPong, false); + RegisterHandler(OnEntityStateMessage, true); + RegisterHandler(OnTimeSnapshotMessage, true); + } + + // remote calls //////////////////////////////////////////////////////// + // Handle command from specific player, this could be one of multiple + // players on a single client + // default ready handler. + static void OnClientReadyMessage(NetworkConnectionToClient conn, ReadyMessage msg) + { + // Debug.Log($"Default handler for ready message from {conn}"); + SetClientReady(conn); + } + + static void OnCommandMessage(NetworkConnectionToClient conn, CommandMessage msg, int channelId) + { + if (!conn.isReady) + { + // Clients may be set NotReady due to scene change or other game logic by user, e.g. respawning. + // Ignore commands that may have been in flight before client received NotReadyMessage message. + // Unreliable messages may be out of order, so don't spam warnings for those. + if (channelId == Channels.Reliable) + { + // Attempt to identify the target object, component, and method to narrow down the cause of the error. + if (spawned.TryGetValue(msg.netId, out NetworkIdentity netIdentity)) + if (msg.componentIndex < netIdentity.NetworkBehaviours.Length && netIdentity.NetworkBehaviours[msg.componentIndex] is NetworkBehaviour component) + if (RemoteProcedureCalls.GetFunctionMethodName(msg.functionHash, out string methodName)) + { + Debug.LogWarning($"Command {methodName} received for {netIdentity.name} [netId={msg.netId}] component {component.name} [index={msg.componentIndex}] when client not ready.\nThis may be ignored if client intentionally set NotReady."); + return; + } + + Debug.LogWarning("Command received while client is not ready.\nThis may be ignored if client intentionally set NotReady."); + } + return; + } + + if (!spawned.TryGetValue(msg.netId, out NetworkIdentity identity)) + { + // over reliable channel, commands should always come after spawn. + // over unreliable, they might come in before the object was spawned. + // for example, NetworkTransform. + // let's not spam the console for unreliable out of order messages. + if (channelId == Channels.Reliable) + Debug.LogWarning($"Spawned object not found when handling Command message {identity.name} netId={msg.netId}"); + return; + } + + // Commands can be for player objects, OR other objects with client-authority + // -> so if this connection's controller has a different netId then + // only allow the command if clientAuthorityOwner + bool requiresAuthority = RemoteProcedureCalls.CommandRequiresAuthority(msg.functionHash); + if (requiresAuthority && identity.connectionToClient != conn) + { + // Attempt to identify the component and method to narrow down the cause of the error. + if (msg.componentIndex < identity.NetworkBehaviours.Length && identity.NetworkBehaviours[msg.componentIndex] is NetworkBehaviour component) + if (RemoteProcedureCalls.GetFunctionMethodName(msg.functionHash, out string methodName)) + { + Debug.LogWarning($"Command {methodName} received for {identity.name} [netId={msg.netId}] component {component.name} [index={msg.componentIndex}] without authority"); + return; + } + + Debug.LogWarning($"Command received for {identity.name} [netId={msg.netId}] without authority"); + return; + } + + // Debug.Log($"OnCommandMessage for netId:{msg.netId} conn:{conn}"); + + using (NetworkReaderPooled networkReader = NetworkReaderPool.Get(msg.payload)) + identity.HandleRemoteCall(msg.componentIndex, msg.functionHash, RemoteCallType.Command, networkReader, conn); + } + + // client to server broadcast ////////////////////////////////////////// + // for client's owned ClientToServer components. + static void OnEntityStateMessage(NetworkConnectionToClient connection, EntityStateMessage message) + { + // need to validate permissions carefully. + // an attacker may attempt to modify a not-owned or not-ClientToServer component. + + // valid netId? + if (spawned.TryGetValue(message.netId, out NetworkIdentity identity) && identity != null) + { + // owned by the connection? + if (identity.connectionToClient == connection) + { + using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload)) + { + // DeserializeServer checks permissions internally. + // failure to deserialize disconnects to prevent exploits. + if (!identity.DeserializeServer(reader)) + { + if (exceptionsDisconnect) + { + Debug.LogError($"Server failed to deserialize client state for {identity.name} with netId={identity.netId}, Disconnecting."); + connection.Disconnect(); + } + else + Debug.LogWarning($"Server failed to deserialize client state for {identity.name} with netId={identity.netId}."); + } + } + } + // An attacker may attempt to modify another connection's entity + // This could also be a race condition of message in flight when + // RemoveClientAuthority is called, so not malicious. + // Don't disconnect, just log the warning. + else + Debug.LogWarning($"EntityStateMessage from {connection} for {identity.name} without authority."); + } + // no warning. don't spam server logs. + // else Debug.LogWarning($"Did not find target for sync message for {message.netId} . Note: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message."); + } + + // client sends TimeSnapshotMessage every sendInterval. + // batching already includes the remoteTimestamp. + // we simply insert it on-message here. + // => only for reliable channel. unreliable would always arrive earlier. + static void OnTimeSnapshotMessage(NetworkConnectionToClient connection, TimeSnapshotMessage _) + { + // insert another snapshot for snapshot interpolation. + // before calling OnDeserialize so components can use + // NetworkTime.time and NetworkTime.timeStamp. + + // TODO validation? + // maybe we shouldn't allow timeline to deviate more than a certain %. + // for now, this is only used for client authority movement. + + // Unity 2019 doesn't have Time.timeAsDouble yet + // + // NetworkTime uses unscaled time and ignores Time.timeScale. + // fixes Time.timeScale getting server & client time out of sync: + // https://github.com/MirrorNetworking/Mirror/issues/3409 + connection.OnTimeSnapshot(new TimeSnapshot(connection.remoteTimeStamp, NetworkTime.localTime)); + } + + // connections ///////////////////////////////////////////////////////// + /// Add a connection and setup callbacks. Returns true if not added yet. + public static bool AddConnection(NetworkConnectionToClient conn) + { + if (!connections.ContainsKey(conn.connectionId)) + { + // connection cannot be null here or conn.connectionId + // would throw NRE + connections[conn.connectionId] = conn; + return true; + } + // already a connection with this id + return false; + } + + /// Removes a connection by connectionId. Returns true if removed. + public static bool RemoveConnection(int connectionId) => + connections.Remove(connectionId); + + // called by LocalClient to add itself. don't call directly. + // TODO consider internal setter instead? + internal static void SetLocalConnection(LocalConnectionToClient conn) + { + if (localConnection != null) + { + Debug.LogError("Local Connection already exists"); + return; + } + + localConnection = conn; + } + + // removes local connection to client + internal static void RemoveLocalConnection() + { + if (localConnection != null) + { + localConnection.Disconnect(); + localConnection = null; + } + RemoveConnection(0); + } + + /// True if we have external connections (that are not host) + public static bool HasExternalConnections() + { + // any connections? + if (connections.Count > 0) + { + // only host connection? + if (connections.Count == 1 && localConnection != null) + return false; + + // otherwise we have real external connections + return true; + } + return false; + } + + // send //////////////////////////////////////////////////////////////// + /// Send a message to all clients, even those that haven't joined the world yet (non ready) + public static void SendToAll(T message, int channelId = Channels.Reliable, bool sendToReadyOnly = false) + where T : struct, NetworkMessage + { + if (!active) + { + Debug.LogWarning("Can not send using NetworkServer.SendToAll(T msg) because NetworkServer is not active"); + return; + } + + // Debug.Log($"Server.SendToAll {typeof(T)}"); + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + // pack message only once + NetworkMessages.Pack(message, writer); + ArraySegment segment = writer.ToArraySegment(); + + // validate packet size immediately. + // we know how much can fit into one batch at max. + // if it's larger, log an error immediately with the type . + // previously we only logged in Update() when processing batches, + // but there we don't have type information anymore. + int max = NetworkMessages.MaxMessageSize(channelId); + if (writer.Position > max) + { + Debug.LogError($"NetworkServer.SendToAll: message of type {typeof(T)} with a size of {writer.Position} bytes is larger than the max allowed message size in one batch: {max}.\nThe message was dropped, please make it smaller."); + return; + } + + // filter and then send to all internet connections at once + // -> makes code more complicated, but is HIGHLY worth it to + // avoid allocations, allow for multicast, etc. + int count = 0; + foreach (NetworkConnectionToClient conn in connections.Values) + { + if (sendToReadyOnly && !conn.isReady) + continue; + + count++; + conn.Send(segment, channelId); + } + + NetworkDiagnostics.OnSend(message, channelId, segment.Count, count); + } + } + + /// Send a message to all clients which have joined the world (are ready). + // TODO put rpcs into NetworkServer.Update WorldState packet, then finally remove SendToReady! + public static void SendToReady(T message, int channelId = Channels.Reliable) + where T : struct, NetworkMessage + { + if (!active) + { + Debug.LogWarning("Can not send using NetworkServer.SendToReady(T msg) because NetworkServer is not active"); + return; + } + + SendToAll(message, channelId, true); + } + + // this is like SendToReadyObservers - but it doesn't check the ready flag on the connection. + // this is used for ObjectDestroy messages. + static void SendToObservers(NetworkIdentity identity, T message, int channelId = Channels.Reliable) + where T : struct, NetworkMessage + { + // Debug.Log($"Server.SendToObservers {typeof(T)}"); + if (identity == null || identity.observers.Count == 0) + return; + + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + // pack message into byte[] once + NetworkMessages.Pack(message, writer); + ArraySegment segment = writer.ToArraySegment(); + + // validate packet size immediately. + // we know how much can fit into one batch at max. + // if it's larger, log an error immediately with the type . + // previously we only logged in Update() when processing batches, + // but there we don't have type information anymore. + int max = NetworkMessages.MaxMessageSize(channelId); + if (writer.Position > max) + { + Debug.LogError($"NetworkServer.SendToObservers: message of type {typeof(T)} with a size of {writer.Position} bytes is larger than the max allowed message size in one batch: {max}.\nThe message was dropped, please make it smaller."); + return; + } + + foreach (NetworkConnectionToClient conn in identity.observers.Values) + { + conn.Send(segment, channelId); + } + + NetworkDiagnostics.OnSend(message, channelId, segment.Count, identity.observers.Count); + } + } + + /// Send a message to only clients which are ready with option to include the owner of the object identity + // TODO obsolete this later. it's not used anymore + public static void SendToReadyObservers(NetworkIdentity identity, T message, bool includeOwner = true, int channelId = Channels.Reliable) + where T : struct, NetworkMessage + { + // Debug.Log($"Server.SendToReady {typeof(T)}"); + if (identity == null || identity.observers.Count == 0) + return; + + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + // pack message only once + NetworkMessages.Pack(message, writer); + ArraySegment segment = writer.ToArraySegment(); + + // validate packet size immediately. + // we know how much can fit into one batch at max. + // if it's larger, log an error immediately with the type . + // previously we only logged in Update() when processing batches, + // but there we don't have type information anymore. + int max = NetworkMessages.MaxMessageSize(channelId); + if (writer.Position > max) + { + Debug.LogError($"NetworkServer.SendToReadyObservers: message of type {typeof(T)} with a size of {writer.Position} bytes is larger than the max allowed message size in one batch: {max}.\nThe message was dropped, please make it smaller."); + return; + } + + int count = 0; + foreach (NetworkConnectionToClient conn in identity.observers.Values) + { + bool isOwner = conn == identity.connectionToClient; + if ((!isOwner || includeOwner) && conn.isReady) + { + count++; + conn.Send(segment, channelId); + } + } + + NetworkDiagnostics.OnSend(message, channelId, segment.Count, count); + } + } + + /// Send a message to only clients which are ready including the owner of the NetworkIdentity + // TODO obsolete this later. it's not used anymore + public static void SendToReadyObservers(NetworkIdentity identity, T message, int channelId) + where T : struct, NetworkMessage + { + SendToReadyObservers(identity, message, true, channelId); + } + + // transport events //////////////////////////////////////////////////// + // called by transport + static void OnTransportConnected(int connectionId) + { + // Debug.Log($"Server accepted client:{connectionId}"); + + // connectionId needs to be != 0 because 0 is reserved for local player + // note that some transports like kcp generate connectionId by + // hashing which can be < 0 as well, so we need to allow < 0! + if (connectionId == 0) + { + Debug.LogError($"Server.HandleConnect: invalid connectionId: {connectionId} . Needs to be != 0, because 0 is reserved for local player."); + Transport.active.ServerDisconnect(connectionId); + return; + } + + // connectionId not in use yet? + if (connections.ContainsKey(connectionId)) + { + Transport.active.ServerDisconnect(connectionId); + // Debug.Log($"Server connectionId {connectionId} already in use...kicked client"); + return; + } + + // are more connections allowed? if not, kick + // (it's easier to handle this in Mirror, so Transports can have + // less code and third party transport might not do that anyway) + // (this way we could also send a custom 'tooFull' message later, + // Transport can't do that) + if (connections.Count < maxConnections) + { + // add connection + NetworkConnectionToClient conn = new NetworkConnectionToClient(connectionId); + OnConnected(conn); + } + else + { + // kick + Transport.active.ServerDisconnect(connectionId); + // Debug.Log($"Server full, kicked client {connectionId}"); + } + } + + internal static void OnConnected(NetworkConnectionToClient conn) + { + // Debug.Log($"Server accepted client:{conn}"); + + // add connection and invoke connected event + AddConnection(conn); + OnConnectedEvent?.Invoke(conn); + } + + static bool UnpackAndInvoke(NetworkConnectionToClient connection, NetworkReader reader, int channelId) + { + if (NetworkMessages.UnpackId(reader, out ushort msgType)) + { + // try to invoke the handler for that message + if (handlers.TryGetValue(msgType, out NetworkMessageDelegate handler)) + { + handler.Invoke(connection, reader, channelId); + connection.lastMessageTime = Time.time; + return true; + } + else + { + // message in a batch are NOT length prefixed to save bandwidth. + // every message needs to be handled and read until the end. + // otherwise it would overlap into the next message. + // => need to warn and disconnect to avoid undefined behaviour. + // => WARNING, not error. can happen if attacker sends random data. + Debug.LogWarning($"Unknown message id: {msgType} for connection: {connection}. This can happen if no handler was registered for this message."); + // simply return false. caller is responsible for disconnecting. + //connection.Disconnect(); + return false; + } + } + else + { + // => WARNING, not error. can happen if attacker sends random data. + Debug.LogWarning($"Invalid message header for connection: {connection}."); + // simply return false. caller is responsible for disconnecting. + //connection.Disconnect(); + return false; + } + } + + // called by transport + internal static void OnTransportData(int connectionId, ArraySegment data, int channelId) + { + if (connections.TryGetValue(connectionId, out NetworkConnectionToClient connection)) + { + // client might batch multiple messages into one packet. + // feed it to the Unbatcher. + // NOTE: we don't need to associate a channelId because we + // always process all messages in the batch. + if (!connection.unbatcher.AddBatch(data)) + { + if (exceptionsDisconnect) + { + Debug.LogError($"NetworkServer: received message from connectionId:{connectionId} was too short (messages should start with message id). Disconnecting."); + connection.Disconnect(); + } + else + Debug.LogWarning($"NetworkServer: received message from connectionId:{connectionId} was too short (messages should start with message id)."); + + return; + } + + // process all messages in the batch. + // only while NOT loading a scene. + // if we get a scene change message, then we need to stop + // processing. otherwise we might apply them to the old scene. + // => fixes https://github.com/vis2k/Mirror/issues/2651 + // + // NOTE: if scene starts loading, then the rest of the batch + // would only be processed when OnTransportData is called + // the next time. + // => consider moving processing to NetworkEarlyUpdate. + while (!isLoadingScene && + connection.unbatcher.GetNextMessage(out ArraySegment message, out double remoteTimestamp)) + { + using (NetworkReaderPooled reader = NetworkReaderPool.Get(message)) + { + // enough to read at least header size? + if (reader.Remaining >= NetworkMessages.IdSize) + { + // make remoteTimeStamp available to the user + connection.remoteTimeStamp = remoteTimestamp; + + // handle message + if (!UnpackAndInvoke(connection, reader, channelId)) + { + // warn, disconnect and return if failed + // -> warning because attackers might send random data + // -> messages in a batch aren't length prefixed. + // failing to read one would cause undefined + // behaviour for every message afterwards. + // so we need to disconnect. + // -> return to avoid the below unbatches.count error. + // we already disconnected and handled it. + if (exceptionsDisconnect) + { + Debug.LogError($"NetworkServer: failed to unpack and invoke message. Disconnecting {connectionId}."); + connection.Disconnect(); + } + else + Debug.LogWarning($"NetworkServer: failed to unpack and invoke message from connectionId:{connectionId}."); + + return; + } + } + // otherwise disconnect + else + { + if (exceptionsDisconnect) + { + Debug.LogError($"NetworkServer: received message from connectionId:{connectionId} was too short (messages should start with message id). Disconnecting."); + connection.Disconnect(); + } + else + Debug.LogWarning($"NetworkServer: received message from connectionId:{connectionId} was too short (messages should start with message id)."); + + return; + } + } + } + + // if we weren't interrupted by a scene change, + // then all batched messages should have been processed now. + // otherwise batches would silently grow. + // we need to log an error to avoid debugging hell. + // + // EXAMPLE: https://github.com/vis2k/Mirror/issues/2882 + // -> UnpackAndInvoke silently returned because no handler for id + // -> Reader would never be read past the end + // -> Batch would never be retired because end is never reached + // + // NOTE: prefixing every message in a batch with a length would + // avoid ever not reading to the end. for extra bandwidth. + // + // IMPORTANT: always keep this check to detect memory leaks. + // this took half a day to debug last time. + if (!isLoadingScene && connection.unbatcher.BatchesCount > 0) + { + Debug.LogError($"Still had {connection.unbatcher.BatchesCount} batches remaining after processing, even though processing was not interrupted by a scene change. This should never happen, as it would cause ever growing batches.\nPossible reasons:\n* A message didn't deserialize as much as it serialized\n*There was no message handler for a message id, so the reader wasn't read until the end."); + } + } + else Debug.LogError($"HandleData Unknown connectionId:{connectionId}"); + } + + // called by transport + // IMPORTANT: often times when disconnecting, we call this from Mirror + // too because we want to remove the connection and handle + // the disconnect immediately. + // => which is fine as long as we guarantee it only runs once + // => which we do by removing the connection! + internal static void OnTransportDisconnected(int connectionId) + { + // Debug.Log($"Server disconnect client:{connectionId}"); + if (connections.TryGetValue(connectionId, out NetworkConnectionToClient conn)) + { + RemoveConnection(connectionId); + // Debug.Log($"Server lost client:{connectionId}"); + + // NetworkManager hooks into OnDisconnectedEvent to make + // DestroyPlayerForConnection(conn) optional, e.g. for PvP MMOs + // where players shouldn't be able to escape combat instantly. + if (OnDisconnectedEvent != null) + { + OnDisconnectedEvent.Invoke(conn); + } + // if nobody hooked into it, then simply call DestroyPlayerForConnection + else + { + DestroyPlayerForConnection(conn); + } + } + } + + // transport errors are forwarded to high level + static void OnTransportError(int connectionId, TransportError error, string reason) + { + // transport errors will happen. logging a warning is enough. + // make sure the user does not panic. + Debug.LogWarning($"Server Transport Error for connId={connectionId}: {error}: {reason}. This is fine."); + // try get connection. passes null otherwise. + connections.TryGetValue(connectionId, out NetworkConnectionToClient conn); + OnErrorEvent?.Invoke(conn, error, reason); + } + + /// Destroys all of the connection's owned objects on the server. + // This is used when a client disconnects, to remove the players for + // that client. This also destroys non-player objects that have client + // authority set for this connection. + public static void DestroyPlayerForConnection(NetworkConnectionToClient conn) + { + // destroy all objects owned by this connection, including the player object + conn.DestroyOwnedObjects(); + // remove connection from all of its observing entities observers + // fixes https://github.com/vis2k/Mirror/issues/2737 + // -> cleaning those up in NetworkConnection.Disconnect is NOT enough + // because voluntary disconnects from the other end don't call + // NetworkConnection.Disconnect() + conn.RemoveFromObservingsObservers(); + conn.identity = null; + } + + // message handlers //////////////////////////////////////////////////// + /// Register a handler for message type T. Most should require authentication. + // TODO obsolete this some day to always use the channelId version. + // all handlers in this version are wrapped with 1 extra action. + public static void RegisterHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + ushort msgType = NetworkMessageId.Id; + if (handlers.ContainsKey(msgType)) + { + Debug.LogWarning($"NetworkServer.RegisterHandler replacing handler for {typeof(T).FullName}, id={msgType}. If replacement is intentional, use ReplaceHandler instead to avoid this warning."); + } + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + handlers[msgType] = NetworkMessages.WrapHandler(handler, requireAuthentication, exceptionsDisconnect); + } + + /// Register a handler for message type T. Most should require authentication. + // This version passes channelId to the handler. + public static void RegisterHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + ushort msgType = NetworkMessageId.Id; + if (handlers.ContainsKey(msgType)) + { + Debug.LogWarning($"NetworkServer.RegisterHandler replacing handler for {typeof(T).FullName}, id={msgType}. If replacement is intentional, use ReplaceHandler instead to avoid this warning."); + } + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + handlers[msgType] = NetworkMessages.WrapHandler(handler, requireAuthentication, exceptionsDisconnect); + } + + /// Replace a handler for message type T. Most should require authentication. + public static void ReplaceHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + ReplaceHandler((_, value) => { handler(value); }, requireAuthentication); + } + + /// Replace a handler for message type T. Most should require authentication. + public static void ReplaceHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + ushort msgType = NetworkMessageId.Id; + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + handlers[msgType] = NetworkMessages.WrapHandler(handler, requireAuthentication, exceptionsDisconnect); + } + + /// Replace a handler for message type T. Most should require authentication. + public static void ReplaceHandler(Action handler, bool requireAuthentication = true) + where T : struct, NetworkMessage + { + ushort msgType = NetworkMessageId.Id; + + // register Id <> Type in lookup for debugging. + NetworkMessages.Lookup[msgType] = typeof(T); + + handlers[msgType] = NetworkMessages.WrapHandler(handler, requireAuthentication, exceptionsDisconnect); + } + + /// Unregister a handler for a message type T. + public static void UnregisterHandler() + where T : struct, NetworkMessage + { + ushort msgType = NetworkMessageId.Id; + handlers.Remove(msgType); + } + + /// Clears all registered message handlers. + public static void ClearHandlers() => handlers.Clear(); + + internal static bool GetNetworkIdentity(GameObject go, out NetworkIdentity identity) + { + if (!go.TryGetComponent(out identity)) + { + Debug.LogError($"GameObject {go.name} doesn't have NetworkIdentity."); + return false; + } + return true; + } + + // disconnect ////////////////////////////////////////////////////////// + /// Disconnect all connections, including the local connection. + // synchronous: handles disconnect events and cleans up fully before returning! + public static void DisconnectAll() + { + // disconnect and remove all connections. + // we can not use foreach here because if + // conn.Disconnect -> Transport.ServerDisconnect calls + // OnDisconnect -> NetworkServer.OnDisconnect(connectionId) + // immediately then OnDisconnect would remove the connection while + // we are iterating here. + // see also: https://github.com/vis2k/Mirror/issues/2357 + // this whole process should be simplified some day. + // until then, let's copy .Values to avoid InvalidOperationException. + // note that this is only called when stopping the server, so the + // copy is no performance problem. + foreach (NetworkConnectionToClient conn in connections.Values.ToList()) + { + // disconnect via connection->transport + conn.Disconnect(); + + // we want this function to be synchronous: handle disconnect + // events and clean up fully before returning. + // -> OnTransportDisconnected can safely be called without + // waiting for the Transport's callback. + // -> it has checks to only run once. + + // call OnDisconnected unless local player in host mod + // TODO unnecessary check? + if (conn.connectionId != NetworkConnection.LocalConnectionId) + OnTransportDisconnected(conn.connectionId); + } + + // cleanup + connections.Clear(); + localConnection = null; + // this used to set active=false. + // however, then Shutdown can't properly destroy objects: + // https://github.com/MirrorNetworking/Mirror/issues/3344 + // "DisconnectAll" should only disconnect all, not set inactive. + // active = false; + } + + // add/remove/replace player /////////////////////////////////////////// + /// Called by server after AddPlayer message to add the player for the connection. + // When a player is added for a connection, the client for that + // connection is made ready automatically. The player object is + // automatically spawned, so you do not need to call NetworkServer.Spawn + // for that object. This function is used for "adding" a player, not for + // "replacing" the player on a connection. If there is already a player + // on this playerControllerId for this connection, this will fail. + public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameObject player, uint assetId) + { + if (GetNetworkIdentity(player, out NetworkIdentity identity)) + { + identity.assetId = assetId; + } + return AddPlayerForConnection(conn, player); + } + + /// Called by server after AddPlayer message to add the player for the connection. + // When a player is added for a connection, the client for that + // connection is made ready automatically. The player object is + // automatically spawned, so you do not need to call NetworkServer.Spawn + // for that object. This function is used for "adding" a player, not for + // "replacing" the player on a connection. If there is already a player + // on this playerControllerId for this connection, this will fail. + public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameObject player) + { + if (!player.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogWarning($"AddPlayer: player GameObject has no NetworkIdentity. Please add a NetworkIdentity to {player}"); + return false; + } + + // cannot have a player object in "Add" version + if (conn.identity != null) + { + Debug.Log("AddPlayer: player object already exists"); + return false; + } + + // make sure we have a controller before we call SetClientReady + // because the observers will be rebuilt only if we have a controller + conn.identity = identity; + + // Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients) + identity.SetClientOwner(conn); + + // special case, we are in host mode, set hasAuthority to true so that all overrides see it + if (conn is LocalConnectionToClient) + { + identity.isOwned = true; + NetworkClient.InternalAddPlayer(identity); + } + + // set ready if not set yet + SetClientReady(conn); + + // Debug.Log($"Adding new playerGameObject object netId: {identity.netId} asset ID: {identity.assetId}"); + + Respawn(identity); + return true; + } + + /// Replaces connection's player object. The old object is not destroyed. + // This does NOT change the ready state of the connection, so it can + // safely be used while changing scenes. + public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, bool keepAuthority = false) + { + if (!player.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"ReplacePlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to {player}"); + return false; + } + + if (identity.connectionToClient != null && identity.connectionToClient != conn) + { + Debug.LogError($"Cannot replace player for connection. New player is already owned by a different connection{player}"); + return false; + } + + //NOTE: there can be an existing player + //Debug.Log("NetworkServer ReplacePlayer"); + + NetworkIdentity previousPlayer = conn.identity; + + conn.identity = identity; + + // Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients) + identity.SetClientOwner(conn); + + // special case, we are in host mode, set hasAuthority to true so that all overrides see it + if (conn is LocalConnectionToClient) + { + identity.isOwned = true; + NetworkClient.InternalAddPlayer(identity); + } + + // add connection to observers AFTER the playerController was set. + // by definition, there is nothing to observe if there is no player + // controller. + // + // IMPORTANT: do this in AddPlayerForConnection & ReplacePlayerForConnection! + SpawnObserversForConnection(conn); + + //Debug.Log($"Replacing playerGameObject object netId:{player.GetComponent().netId} asset ID {player.GetComponent().assetId}"); + + Respawn(identity); + + if (keepAuthority) + { + // This needs to be sent to clear isLocalPlayer on + // client while keeping hasAuthority true + SendChangeOwnerMessage(previousPlayer, conn); + } + else + { + // This clears both isLocalPlayer and hasAuthority on client + previousPlayer.RemoveClientAuthority(); + } + + return true; + } + + /// Replaces connection's player object. The old object is not destroyed. + // This does NOT change the ready state of the connection, so it can + // safely be used while changing scenes. + public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, uint assetId, bool keepAuthority = false) + { + if (GetNetworkIdentity(player, out NetworkIdentity identity)) + { + identity.assetId = assetId; + } + return ReplacePlayerForConnection(conn, player, keepAuthority); + } + + /// Removes the player object from the connection + // destroyServerObject: Indicates whether the server object should be destroyed + public static void RemovePlayerForConnection(NetworkConnectionToClient conn, bool destroyServerObject) + { + if (conn.identity != null) + { + if (destroyServerObject) + Destroy(conn.identity.gameObject); + else + UnSpawn(conn.identity.gameObject); + + conn.identity = null; + } + //else Debug.Log($"Connection {conn} has no identity"); + } + + // ready /////////////////////////////////////////////////////////////// + /// Flags client connection as ready (=joined world). + // When a client has signaled that it is ready, this method tells the + // server that the client is ready to receive spawned objects and state + // synchronization updates. This is usually called in a handler for the + // SYSTEM_READY message. If there is not specific action a game needs to + // take for this message, relying on the default ready handler function + // is probably fine, so this call wont be needed. + public static void SetClientReady(NetworkConnectionToClient conn) + { + // Debug.Log($"SetClientReadyInternal for conn:{conn}"); + + // set ready + conn.isReady = true; + + // client is ready to start spawning objects + if (conn.identity != null) + SpawnObserversForConnection(conn); + } + + static void SpawnObserversForConnection(NetworkConnectionToClient conn) + { + //Debug.Log($"Spawning {spawned.Count} objects for conn {conn}"); + + if (!conn.isReady) + { + // client needs to finish initializing before we can spawn objects + // otherwise it would not find them. + return; + } + + // let connection know that we are about to start spawning... + conn.Send(new ObjectSpawnStartedMessage()); + + // add connection to each nearby NetworkIdentity's observers, which + // internally sends a spawn message for each one to the connection. + foreach (NetworkIdentity identity in spawned.Values) + { + // try with far away ones in ummorpg! + if (identity.gameObject.activeSelf) //TODO this is different + { + //Debug.Log($"Sending spawn message for current server objects name:{identity.name} netId:{identity.netId} sceneId:{identity.sceneId:X}"); + + // we need to support three cases: + // - legacy system (identity has .visibility) + // - new system (networkserver has .aoi) + // - default case: no .visibility and no .aoi means add all + // connections by default) + // + // ForceHidden/ForceShown overwrite all systems so check it + // first! + + // ForceShown: add no matter what + if (identity.visibility == Visibility.ForceShown) + { + identity.AddObserver(conn); + } + // ForceHidden: don't show no matter what + else if (identity.visibility == Visibility.ForceHidden) + { + // do nothing + } + // default: legacy system / new system / no system support + else if (identity.visibility == Visibility.Default) + { + // aoi system + if (aoi != null) + { + // call OnCheckObserver + if (aoi.OnCheckObserver(identity, conn)) + identity.AddObserver(conn); + } + // no system: add all observers by default + else + { + identity.AddObserver(conn); + } + } + } + } + + // let connection know that we finished spawning, so it can call + // OnStartClient on each one (only after all were spawned, which + // is how Unity's Start() function works too) + conn.Send(new ObjectSpawnFinishedMessage()); + } + + /// Marks the client of the connection to be not-ready. + // Clients that are not ready do not receive spawned objects or state + // synchronization updates. They client can be made ready again by + // calling SetClientReady(). + public static void SetClientNotReady(NetworkConnectionToClient conn) + { + conn.isReady = false; + conn.RemoveFromObservingsObservers(); + conn.Send(new NotReadyMessage()); + } + + /// Marks all connected clients as no longer ready. + // All clients will no longer be sent state synchronization updates. The + // player's clients can call ClientManager.Ready() again to re-enter the + // ready state. This is useful when switching scenes. + public static void SetAllClientsNotReady() + { + foreach (NetworkConnectionToClient conn in connections.Values) + { + SetClientNotReady(conn); + } + } + + // show / hide for connection ////////////////////////////////////////// + internal static void ShowForConnection(NetworkIdentity identity, NetworkConnection conn) + { + if (conn.isReady) + SendSpawnMessage(identity, conn); + } + + internal static void HideForConnection(NetworkIdentity identity, NetworkConnection conn) + { + ObjectHideMessage msg = new ObjectHideMessage + { + netId = identity.netId + }; + conn.Send(msg); + } + + // spawning //////////////////////////////////////////////////////////// + internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnection conn) + { + if (identity.serverOnly) return; + + //Debug.Log($"Server SendSpawnMessage: name:{identity.name} sceneId:{identity.sceneId:X} netid:{identity.netId}"); + + // one writer for owner, one for observers + using (NetworkWriterPooled ownerWriter = NetworkWriterPool.Get(), observersWriter = NetworkWriterPool.Get()) + { + bool isOwner = identity.connectionToClient == conn; + ArraySegment payload = CreateSpawnMessagePayload(isOwner, identity, ownerWriter, observersWriter); + SpawnMessage message = new SpawnMessage + { + netId = identity.netId, + isLocalPlayer = conn.identity == identity, + isOwner = isOwner, + sceneId = identity.sceneId, + assetId = identity.assetId, + // use local values for VR support + position = identity.transform.localPosition, + rotation = identity.transform.localRotation, + scale = identity.transform.localScale, + payload = payload + }; + conn.Send(message); + } + } + + static ArraySegment CreateSpawnMessagePayload(bool isOwner, NetworkIdentity identity, NetworkWriterPooled ownerWriter, NetworkWriterPooled observersWriter) + { + // Only call SerializeAll if there are NetworkBehaviours + if (identity.NetworkBehaviours.Length == 0) + { + return default; + } + + // serialize all components with initialState = true + // (can be null if has none) + identity.SerializeServer(true, ownerWriter, observersWriter); + + // convert to ArraySegment to avoid reader allocations + // if nothing was written, .ToArraySegment returns an empty segment. + ArraySegment ownerSegment = ownerWriter.ToArraySegment(); + ArraySegment observersSegment = observersWriter.ToArraySegment(); + + // use owner segment if 'conn' owns this identity, otherwise + // use observers segment + ArraySegment payload = isOwner ? ownerSegment : observersSegment; + + return payload; + } + + internal static void SendChangeOwnerMessage(NetworkIdentity identity, NetworkConnectionToClient conn) + { + // Don't send if identity isn't spawned or only exists on server + if (identity.netId == 0 || identity.serverOnly) return; + + // Don't send if conn doesn't have the identity spawned yet + // May be excluded from the client by interest management + if (!conn.observing.Contains(identity)) return; + + //Debug.Log($"Server SendChangeOwnerMessage: name={identity.name} netid={identity.netId}"); + + conn.Send(new ChangeOwnerMessage + { + netId = identity.netId, + isOwner = identity.connectionToClient == conn, + isLocalPlayer = conn.identity == identity + }); + } + + // check NetworkIdentity parent before spawning it. + // - without parent, they are spawned + // - with parent, only if the parent is active in hierarchy + // + // note that active parents may have inactive parents of their own. + // we need to check .activeInHierarchy. + // + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3330 + // https://github.com/vis2k/Mirror/issues/2778 + static bool ValidParent(NetworkIdentity identity) => + identity.transform.parent == null || + identity.transform.parent.gameObject.activeInHierarchy; + + /// Spawns NetworkIdentities in the scene on the server. + // NetworkIdentity objects in a scene are disabled by default. Calling + // SpawnObjects() causes these scene objects to be enabled and spawned. + // It is like calling NetworkServer.Spawn() for each of them. + public static bool SpawnObjects() + { + // only if server active + if (!active) + return false; + + // find all NetworkIdentities in the scene. + // all of them are disabled because of NetworkScenePostProcess. + NetworkIdentity[] identities = Resources.FindObjectsOfTypeAll(); + + // first pass: activate all scene objects + foreach (NetworkIdentity identity in identities) + { + // only spawn scene objects which haven't been spawned yet. + // SpawnObjects may be called multiple times for additive scenes. + // https://github.com/MirrorNetworking/Mirror/issues/3318 + // + // note that we even activate objects under inactive parents. + // while they are not spawned, they do need to be activated + // in order to be spawned later. so here, we don't check parents. + // https://github.com/MirrorNetworking/Mirror/issues/3330 + if (Utils.IsSceneObject(identity) && identity.netId == 0) + { + // Debug.Log($"SpawnObjects sceneId:{identity.sceneId:X} name:{identity.gameObject.name}"); + identity.gameObject.SetActive(true); + } + } + + // second pass: spawn all scene objects + foreach (NetworkIdentity identity in identities) + { + // scene objects may be children of inactive parents. + // users would put them under disabled parents to 'deactivate' them. + // those should not be used by Mirror at all. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3330 + // https://github.com/vis2k/Mirror/issues/2778 + if (Utils.IsSceneObject(identity) && identity.netId == 0 && ValidParent(identity)) + { + // pass connection so that authority is not lost when server loads a scene + // https://github.com/vis2k/Mirror/pull/2987 + Spawn(identity.gameObject, identity.connectionToClient); + } + } + + return true; + } + + /// Spawns an object and also assigns Client Authority to the specified client. + // This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object. + public static void Spawn(GameObject obj, GameObject ownerPlayer) + { + if (!ownerPlayer.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError("Player object has no NetworkIdentity"); + return; + } + + if (identity.connectionToClient == null) + { + Debug.LogError("Player object is not a player."); + return; + } + + Spawn(obj, identity.connectionToClient); + } + + static void Respawn(NetworkIdentity identity) + { + if (identity.netId == 0) + { + // If the object has not been spawned, then do a full spawn and update observers + Spawn(identity.gameObject, identity.connectionToClient); + } + else + { + // otherwise just replace his data + SendSpawnMessage(identity, identity.connectionToClient); + } + } + + /// Spawn the given game object on all clients which are ready. + // This will cause a new object to be instantiated from the registered + // prefab, or from a custom spawn function. + public static void Spawn(GameObject obj, NetworkConnection ownerConnection = null) + { + SpawnObject(obj, ownerConnection); + } + + /// Spawns an object and also assigns Client Authority to the specified client. + // This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object. + public static void Spawn(GameObject obj, uint assetId, NetworkConnection ownerConnection = null) + { + if (GetNetworkIdentity(obj, out NetworkIdentity identity)) + { + identity.assetId = assetId; + } + SpawnObject(obj, ownerConnection); + } + + static void SpawnObject(GameObject obj, NetworkConnection ownerConnection) + { + // verify if we can spawn this + if (Utils.IsPrefab(obj)) + { + Debug.LogError($"GameObject {obj.name} is a prefab, it can't be spawned. Instantiate it first.", obj); + return; + } + + if (!active) + { + Debug.LogError($"SpawnObject for {obj}, NetworkServer is not active. Cannot spawn objects without an active server.", obj); + return; + } + + if (!obj.TryGetComponent(out NetworkIdentity identity)) + { + Debug.LogError($"SpawnObject {obj} has no NetworkIdentity. Please add a NetworkIdentity to {obj}", obj); + return; + } + + if (identity.SpawnedFromInstantiate) + { + // Using Instantiate on SceneObject is not allowed, so stop spawning here + // NetworkIdentity.Awake already logs error, no need to log a second error here + return; + } + + // Spawn should only be called once per netId. + // calling it twice would lead to undefined behaviour. + // https://github.com/MirrorNetworking/Mirror/pull/3205 + if (spawned.ContainsKey(identity.netId)) + { + Debug.LogWarning($"{identity.name} [netId={identity.netId}] was already spawned.", identity.gameObject); + return; + } + + identity.connectionToClient = (NetworkConnectionToClient)ownerConnection; + + // special case to make sure hasAuthority is set + // on start server in host mode + if (ownerConnection is LocalConnectionToClient) + identity.isOwned = true; + + // NetworkServer.Unspawn sets object as inactive. + // NetworkServer.Spawn needs to set them active again in case they were previously unspawned / inactive. + identity.gameObject.SetActive(true); + + // only call OnStartServer if not spawned yet. + // check used to be in NetworkIdentity. may not be necessary anymore. + if (!identity.isServer && identity.netId == 0) + { + // configure NetworkIdentity + // this may be called in host mode, so we need to initialize + // isLocalPlayer/isClient flags too. + identity.isLocalPlayer = NetworkClient.localPlayer == identity; + identity.isClient = NetworkClient.active; + identity.isServer = true; + identity.netId = NetworkIdentity.GetNextNetworkId(); + + // add to spawned (after assigning netId) + spawned[identity.netId] = identity; + + // callback after all fields were set + identity.OnStartServer(); + } + + // Debug.Log($"SpawnObject instance ID {identity.netId} asset ID {identity.assetId}"); + + if (aoi) + { + // This calls user code which might throw exceptions + // We don't want this to leave us in bad state + try + { + aoi.OnSpawned(identity); + } + catch (Exception e) + { + Debug.LogException(e); + } + } + + RebuildObservers(identity, true); + } + + /// This takes an object that has been spawned and un-spawns it. + // The object will be removed from clients that it was spawned on, or + // the custom spawn handler function on the client will be called for + // the object. + // Unlike when calling NetworkServer.Destroy(), on the server the object + // will NOT be destroyed. This allows the server to re-use the object, + // even spawn it again later. + public static void UnSpawn(GameObject obj) + { + // Debug.Log($"DestroyObject instance:{identity.netId}"); + + // NetworkServer.Unspawn should only be called on server or host. + // on client, show a warning to explain what it does. + if (!active) + { + Debug.LogWarning("NetworkServer.Unspawn() called without an active server. Servers can only destroy while active, clients can only ask the server to destroy (for example, with a [Command]), after which the server may decide to destroy the object and broadcast the change to all clients."); + return; + } + + if (obj == null) + { + Debug.Log("NetworkServer.Unspawn(): object is null"); + return; + } + + if (!GetNetworkIdentity(obj, out NetworkIdentity identity)) + { + return; + } + + // only call OnRebuildObservers while active, + // not while shutting down + // (https://github.com/vis2k/Mirror/issues/2977) + if (active && aoi) + { + // This calls user code which might throw exceptions + // We don't want this to leave us in bad state + try + { + aoi.OnDestroyed(identity); + } + catch (Exception e) + { + Debug.LogException(e); + } + } + + // remove from NetworkServer (this) dictionary + spawned.Remove(identity.netId); + + identity.connectionToClient?.RemoveOwnedObject(identity); + + // send object destroy message to all observers, clear observers + SendToObservers(identity, new ObjectDestroyMessage + { + netId = identity.netId + }); + identity.ClearObservers(); + + // in host mode, call OnStopClient/OnStopLocalPlayer manually + if (NetworkClient.active && activeHost) + { + if (identity.isLocalPlayer) + identity.OnStopLocalPlayer(); + + identity.OnStopClient(); + // The object may have been spawned with host client ownership, + // e.g. a pet so we need to clear hasAuthority and call + // NotifyAuthority which invokes OnStopAuthority if hasAuthority. + identity.isOwned = false; + identity.NotifyAuthority(); + + // remove from NetworkClient dictionary + NetworkClient.connection.owned.Remove(identity); + NetworkClient.spawned.Remove(identity.netId); + } + + // we are on the server. call OnStopServer. + identity.OnStopServer(); + + // finally reset the state and deactivate it + identity.ResetState(); + identity.gameObject.SetActive(false); + } + + // destroy ///////////////////////////////////////////////////////////// + /// Destroys this object and corresponding objects on all clients. + // In some cases it is useful to remove an object but not delete it on + // the server. For that, use NetworkServer.UnSpawn() instead of + // NetworkServer.Destroy(). + public static void Destroy(GameObject obj) + { + // NetworkServer.Destroy should only be called on server or host. + // on client, show a warning to explain what it does. + if (!active) + { + Debug.LogWarning("NetworkServer.Destroy() called without an active server. Servers can only destroy while active, clients can only ask the server to destroy (for example, with a [Command]), after which the server may decide to destroy the object and broadcast the change to all clients."); + return; + } + + if (obj == null) + { + Debug.Log("NetworkServer.Destroy(): object is null"); + return; + } + + // first, we unspawn it on clients and server + UnSpawn(obj); + + // additionally, if it's a prefab then we destroy it completely. + // we never destroy scene objects on server or on client, since once + // they are gone, they are gone forever and can't be instantiate again. + // for example, server may Destroy() a scene object and once a match + // restarts, the scene objects would be gone from the new match. + if (GetNetworkIdentity(obj, out NetworkIdentity identity) && + identity.sceneId == 0) + { + identity.destroyCalled = true; + + // Destroy if application is running + if (Application.isPlaying) + { + UnityEngine.Object.Destroy(obj); + } + // Destroy can't be used in Editor during tests. use DestroyImmediate. + else + { + GameObject.DestroyImmediate(obj); + } + } + } + + // interest management ///////////////////////////////////////////////// + // Helper function to add all server connections as observers. + // This is used if none of the components provides their own + // OnRebuildObservers function. + // rebuild observers default method (no AOI) - adds all connections + static void RebuildObserversDefault(NetworkIdentity identity, bool initialize) + { + // only add all connections when rebuilding the first time. + // second time we just keep them without rebuilding anything. + if (initialize) + { + // not force hidden? + if (identity.visibility != Visibility.ForceHidden) + { + AddAllReadyServerConnectionsToObservers(identity); + } + } + } + + internal static void AddAllReadyServerConnectionsToObservers(NetworkIdentity identity) + { + // add all server connections + foreach (NetworkConnectionToClient conn in connections.Values) + { + // only if authenticated (don't send to people during logins) + if (conn.isReady) + identity.AddObserver(conn); + } + + // add local host connection (if any) + if (localConnection != null && localConnection.isReady) + { + identity.AddObserver(localConnection); + } + } + + // RebuildObservers does a local rebuild for the NetworkIdentity. + // This causes the set of players that can see this object to be rebuild. + // + // IMPORTANT: + // => global rebuild would be more simple, BUT + // => local rebuild is way faster for spawn/despawn because we can + // simply rebuild a select NetworkIdentity only + // => having both .observers and .observing is necessary for local + // rebuilds + // + // in other words, this is the perfect solution even though it's not + // completely simple (due to .observers & .observing) + // + // Mirror maintains .observing automatically in the background. best of + // both worlds without any worrying now! + public static void RebuildObservers(NetworkIdentity identity, bool initialize) + { + // if there is no interest management system, + // or if 'force shown' then add all connections + if (aoi == null || identity.visibility == Visibility.ForceShown) + { + RebuildObserversDefault(identity, initialize); + } + // otherwise let interest management system rebuild + else + { + aoi.Rebuild(identity, initialize); + } + } + + + // broadcasting //////////////////////////////////////////////////////// + // helper function to get the right serialization for a connection + static NetworkWriter SerializeForConnection(NetworkIdentity identity, NetworkConnectionToClient connection) + { + // get serialization for this entity (cached) + // IMPORTANT: int tick avoids floating point inaccuracy over days/weeks + NetworkIdentitySerialization serialization = identity.GetServerSerializationAtTick(Time.frameCount); + + // is this entity owned by this connection? + bool owned = identity.connectionToClient == connection; + + // send serialized data + // owner writer if owned + if (owned) + { + // was it dirty / did we actually serialize anything? + if (serialization.ownerWriter.Position > 0) + return serialization.ownerWriter; + } + // observers writer if not owned + else + { + // was it dirty / did we actually serialize anything? + if (serialization.observersWriter.Position > 0) + return serialization.observersWriter; + } + + // nothing was serialized + return null; + } + + // helper function to broadcast the world to a connection + static void BroadcastToConnection(NetworkConnectionToClient connection) + { + // for each entity that this connection is seeing + foreach (NetworkIdentity identity in connection.observing) + { + // make sure it's not null or destroyed. + // (which can happen if someone uses + // GameObject.Destroy instead of + // NetworkServer.Destroy) + if (identity != null) + { + // get serialization for this entity viewed by this connection + // (if anything was serialized this time) + NetworkWriter serialization = SerializeForConnection(identity, connection); + if (serialization != null) + { + EntityStateMessage message = new EntityStateMessage + { + netId = identity.netId, + payload = serialization.ToArraySegment() + }; + connection.Send(message); + } + } + // spawned list should have no null entries because we + // always call Remove in OnObjectDestroy everywhere. + // if it does have null then someone used + // GameObject.Destroy instead of NetworkServer.Destroy. + else Debug.LogWarning($"Found 'null' entry in observing list for connectionId={connection.connectionId}. Please call NetworkServer.Destroy to destroy networked objects. Don't use GameObject.Destroy."); + } + } + + // helper function to check a connection for inactivity and disconnect if necessary + // returns true if disconnected + static bool DisconnectIfInactive(NetworkConnectionToClient connection) + { + // check for inactivity + if (disconnectInactiveConnections && + !connection.IsAlive(disconnectInactiveTimeout)) + { + Debug.LogWarning($"Disconnecting {connection} for inactivity!"); + connection.Disconnect(); + return true; + } + return false; + } + + // NetworkLateUpdate called after any Update/FixedUpdate/LateUpdate + // (we add this to the UnityEngine in NetworkLoop) + // internal for tests + internal static readonly List connectionsCopy = + new List(); + + static void Broadcast() + { + // copy all connections into a helper collection so that + // OnTransportDisconnected can be called while iterating. + // -> OnTransportDisconnected removes from the collection + // -> which would throw 'can't modify while iterating' errors + // => see also: https://github.com/vis2k/Mirror/issues/2739 + // (copy nonalloc) + // TODO remove this when we move to 'lite' transports with only + // socket send/recv later. + connectionsCopy.Clear(); + connections.Values.CopyTo(connectionsCopy); + + // go through all connections + foreach (NetworkConnectionToClient connection in connectionsCopy) + { + // check for inactivity. disconnects if necessary. + if (DisconnectIfInactive(connection)) + continue; + + // has this connection joined the world yet? + // for each READY connection: + // pull in UpdateVarsMessage for each entity it observes + if (connection.isReady) + { + // send time for snapshot interpolation every sendInterval. + // BroadcastToConnection() may not send if nothing is new. + // + // sent over unreliable. + // NetworkTime / Transform both use unreliable. + // + // make sure Broadcast() is only called every sendInterval, + // even if targetFrameRate isn't set in host mode (!) + // (done via AccurateInterval) + connection.Send(new TimeSnapshotMessage(), Channels.Unreliable); + + // broadcast world state to this connection + BroadcastToConnection(connection); + } + + // update connection to flush out batched messages + connection.Update(); + } + + // TODO this is way too slow because we iterate ALL spawned :/ + // TODO this is way too complicated :/ + // to understand what this tries to prevent, consider this example: + // monster has health=100 + // we change health=200, dirty bit is set + // player comes in range, gets full serialization spawn packet. + // next Broadcast(), player gets the health=200 change because dirty bit was set. + // + // this code clears all dirty bits if no players are around to prevent it. + // BUT there are two issues: + // 1. what if a playerB was around the whole time? + // 2. why don't we handle broadcast and spawn packets both HERE? + // handling spawn separately is why we need this complex magic + // + // see test: DirtyBitsAreClearedForSpawnedWithoutObservers() + // see test: SyncObjectChanges_DontGrowWithoutObservers() + // + // PAUL: we also do this to avoid ever growing SyncList .changes + //ClearSpawnedDirtyBits(); + // + // this was moved to NetworkIdentity.AddObserver! + // same result, but no more O(N) loop in here! + // TODO remove this comment after moving spawning into Broadcast()! + } + + // update ////////////////////////////////////////////////////////////// + // NetworkEarlyUpdate called before any Update/FixedUpdate + // (we add this to the UnityEngine in NetworkLoop) + internal static void NetworkEarlyUpdate() + { + // measure update time for profiling. + if (active) + { + earlyUpdateDuration.Begin(); + fullUpdateDuration.Begin(); + } + + // process all incoming messages first before updating the world + if (Transport.active != null) + Transport.active.ServerEarlyUpdate(); + + // step each connection's local time interpolation in early update. + foreach (NetworkConnectionToClient connection in connections.Values) + connection.UpdateTimeInterpolation(); + + if (active) earlyUpdateDuration.End(); + } + + internal static void NetworkLateUpdate() + { + if (active) + { + // measure update time for profiling. + lateUpdateDuration.Begin(); + + // only broadcast world if active + // broadcast every sendInterval. + // AccurateInterval to avoid update frequency inaccuracy issues: + // https://github.com/vis2k/Mirror/pull/3153 + // + // for example, host mode server doesn't set .targetFrameRate. + // Broadcast() would be called every tick. + // snapshots might be sent way too often, etc. + // + // during tests, we always call Broadcast() though. + // + // also important for syncInterval=0 components like + // NetworkTransform, so they can sync on same interval as time + // snapshots _but_ not every single tick. + // Unity 2019 doesn't have Time.timeAsDouble yet + if (!Application.isPlaying || AccurateInterval.Elapsed(NetworkTime.localTime, sendInterval, ref lastSendTime)) + Broadcast(); + } + + // process all outgoing messages after updating the world + // (even if not active. still want to process disconnects etc.) + if (Transport.active != null) + Transport.active.ServerLateUpdate(); + + // measure actual tick rate every second. + if (active) + { + ++actualTickRateCounter; + + // NetworkTime.localTime has defines for 2019 / 2020 compatibility + if (NetworkTime.localTime >= actualTickRateStart + 1) + { + // calculate avg by exact elapsed time. + // assuming 1s wouldn't be accurate, usually a few more ms passed. + float elapsed = (float)(NetworkTime.localTime - actualTickRateStart); + actualTickRate = Mathf.RoundToInt(actualTickRateCounter / elapsed); + actualTickRateStart = NetworkTime.localTime; + actualTickRateCounter = 0; + } + + // measure total update time. including transport. + // because in early update, transport update calls handlers. + lateUpdateDuration.End(); + fullUpdateDuration.End(); + } + } + } +} diff --git a/Assets/Mirror/Core/NetworkServer.cs.meta b/Assets/Mirror/Core/NetworkServer.cs.meta new file mode 100644 index 0000000..9861342 --- /dev/null +++ b/Assets/Mirror/Core/NetworkServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a5f5ec068f5604c32b160bc49ee97b75 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkStartPosition.cs b/Assets/Mirror/Core/NetworkStartPosition.cs new file mode 100644 index 0000000..e11029b --- /dev/null +++ b/Assets/Mirror/Core/NetworkStartPosition.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +namespace Mirror +{ + /// Start position for player spawning, automatically registers itself in the NetworkManager. + [DisallowMultipleComponent] + [AddComponentMenu("Network/Network Start Position")] + [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-start-position")] + public class NetworkStartPosition : MonoBehaviour + { + public void Awake() + { + NetworkManager.RegisterStartPosition(transform); + } + + public void OnDestroy() + { + NetworkManager.UnRegisterStartPosition(transform); + } + } +} diff --git a/Assets/Mirror/Core/NetworkStartPosition.cs.meta b/Assets/Mirror/Core/NetworkStartPosition.cs.meta new file mode 100644 index 0000000..ae9ab89 --- /dev/null +++ b/Assets/Mirror/Core/NetworkStartPosition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41f84591ce72545258ea98cb7518d8b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkTime.cs b/Assets/Mirror/Core/NetworkTime.cs new file mode 100644 index 0000000..6319970 --- /dev/null +++ b/Assets/Mirror/Core/NetworkTime.cs @@ -0,0 +1,243 @@ +// NetworkTime now uses NetworkClient's snapshot interpolated timeline. +// this gives ideal results & ensures everything is on the same timeline. +// previously, NetworkTransforms were on separate timelines. +// +// however, some of the old NetworkTime code remains for ping time (rtt). +// some users may still be using that. +using System; +using System.Runtime.CompilerServices; +using UnityEngine; +#if !UNITY_2020_3_OR_NEWER +using Stopwatch = System.Diagnostics.Stopwatch; +#endif + +namespace Mirror +{ + /// Synchronizes server time to clients. + public static class NetworkTime + { + /// Ping message interval, used to calculate latency / RTT and predicted time. + // 2s was enough to get a good average RTT. + // for prediction, we want to react to latency changes more rapidly. + const float DefaultPingInterval = 0.1f; // for resets + public static float PingInterval = DefaultPingInterval; + + /// Average out the last few results from Ping + // const because it's used immediately in _rtt constructor. + public const int PingWindowSize = 50; // average over 50 * 100ms = 5s + + static double lastPingTime; + + static ExponentialMovingAverage _rtt = new ExponentialMovingAverage(PingWindowSize); + + /// Returns double precision clock time _in this system_, unaffected by the network. +#if UNITY_2020_3_OR_NEWER + public static double localTime + { + // NetworkTime uses unscaled time and ignores Time.timeScale. + // fixes Time.timeScale getting server & client time out of sync: + // https://github.com/MirrorNetworking/Mirror/issues/3409 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => Time.unscaledTimeAsDouble; + } +#else + // need stopwatch for older Unity versions, but it's quite slow. + // CAREFUL: unlike Time.time, the stopwatch time is not a FRAME time. + // it changes during the frame, so we have an extra step to "cache" it in EarlyUpdate. + static readonly Stopwatch stopwatch = new Stopwatch(); + static NetworkTime() => stopwatch.Start(); + static double localFrameTime; + public static double localTime => localFrameTime; +#endif + + /// The time in seconds since the server started. + // via global NetworkClient snapshot interpolated timeline (if client). + // on server, this is simply Time.timeAsDouble. + // + // I measured the accuracy of float and I got this: + // for the same day, accuracy is better than 1 ms + // after 1 day, accuracy goes down to 7 ms + // after 10 days, accuracy is 61 ms + // after 30 days , accuracy is 238 ms + // after 60 days, accuracy is 454 ms + // in other words, if the server is running for 2 months, + // and you cast down to float, then the time will jump in 0.4s intervals. + public static double time + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => NetworkServer.active + ? localTime + : NetworkClient.localTimeline; + } + + // prediction ////////////////////////////////////////////////////////// + // NetworkTime.time is server time, behind by bufferTime. + // for prediction, we want server time, ahead by latency. + // so that client inputs at predictedTime=2 arrive on server at time=2. + // the more accurate this is, the more closesly will corrections be + // be applied and the less jitter we will see. + // + // we'll use a two step process to calculate predicted time: + // 1. move snapshot interpolated time to server time, without being behind by bufferTime + // 2. constantly send this time to server (included in ping message) + // server replies with how far off it was. + // client averages that offset and applies it to predictedTime to get ever closer. + // + // this is also very easy to test & verify: + // - add LatencySimulation with 50ms latency + // - log predictionError on server in OnServerPing, see if it gets closer to 0 + // + // credits: FakeByte, imer, NinjaKickja, mischa + // const because it's used immediately in _predictionError constructor. + + static int PredictionErrorWindowSize = 20; // average over 20 * 100ms = 2s + static ExponentialMovingAverage _predictionErrorUnadjusted = new ExponentialMovingAverage(PredictionErrorWindowSize); + public static double predictionErrorUnadjusted => _predictionErrorUnadjusted.Value; + public static double predictionErrorAdjusted { get; private set; } // for debugging + + /// Predicted timeline in order for client inputs to be timestamped with the exact time when they will most likely arrive on the server. This is the basis for all prediction like PredictedRigidbody. + // on client, this is based on localTime (aka Time.time) instead of the snapshot interpolated timeline. + // this gives much better and immediately accurate results. + // -> snapshot interpolation timeline tries to emulate a server timeline without hard offset corrections. + // -> predictedTime does have hard offset corrections, so might as well use Time.time directly for this. + // + // note that predictedTime over unreliable is enough! + // even with reliable components, it gives better results than if we were + // to implemented predictedTime over reliable channel. + public static double predictedTime + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => NetworkServer.active + ? localTime // server always uses it's own timeline + : localTime + predictionErrorUnadjusted; // add the offset that the server told us we are off by + } + //////////////////////////////////////////////////////////////////////// + + /// Clock difference in seconds between the client and the server. Always 0 on server. + // original implementation used 'client - server' time. keep it this way. + // TODO obsolete later. people shouldn't worry about this. + public static double offset => localTime - time; + + /// Round trip time (in seconds) that it takes a message to go client->server->client. + public static double rtt => _rtt.Value; + + /// Round trip time variance aka jitter, in seconds. + // "rttVariance" instead of "rttVar" for consistency with older versions. + public static double rttVariance => _rtt.Variance; + + // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload + [RuntimeInitializeOnLoadMethod] + public static void ResetStatics() + { + PingInterval = DefaultPingInterval; + lastPingTime = 0; + _rtt = new ExponentialMovingAverage(PingWindowSize); +#if !UNITY_2020_3_OR_NEWER + stopwatch.Restart(); +#endif + } + + internal static void UpdateClient() + { + // localTime (double) instead of Time.time for accuracy over days + if (localTime >= lastPingTime + PingInterval) + SendPing(); + } + + // Separate method so we can call it from NetworkClient directly. + internal static void SendPing() + { + // send raw predicted time without the offset applied yet. + // we then apply the offset to it after. + NetworkPingMessage pingMessage = new NetworkPingMessage + ( + localTime, + predictedTime + ); + NetworkClient.Send(pingMessage, Channels.Unreliable); + lastPingTime = localTime; + } + + // client rtt calculation ////////////////////////////////////////////// + // executed at the server when we receive a ping message + // reply with a pong containing the time from the client + // and time from the server + internal static void OnServerPing(NetworkConnectionToClient conn, NetworkPingMessage message) + { + // calculate the prediction offset that the client needs to apply to unadjusted time to reach server time. + // this will be sent back to client for corrections. + double unadjustedError = localTime - message.localTime; + + // to see how well the client's final prediction worked, compare with adjusted time. + // this is purely for debugging. + // >0 means: server is ... seconds ahead of client's prediction (good if small) + // <0 means: server is ... seconds behind client's prediction. + // in other words, client is predicting too far ahead (not good) + double adjustedError = localTime - message.predictedTimeAdjusted; + // Debug.Log($"[Server] unadjustedError:{(unadjustedError*1000):F1}ms adjustedError:{(adjustedError*1000):F1}ms"); + + // Debug.Log($"OnServerPing conn:{conn}"); + NetworkPongMessage pongMessage = new NetworkPongMessage + ( + message.localTime, + unadjustedError, + adjustedError + ); + conn.Send(pongMessage, Channels.Unreliable); + } + + // Executed at the client when we receive a Pong message + // find out how long it took since we sent the Ping + // and update time offset & prediction offset. + internal static void OnClientPong(NetworkPongMessage message) + { + // prevent attackers from sending timestamps which are in the future + if (message.localTime > localTime) return; + + // how long did this message take to come back + double newRtt = localTime - message.localTime; + _rtt.Add(newRtt); + + // feed unadjusted prediction error into our exponential moving average + // store adjusted prediction error for debug / GUI purposes + _predictionErrorUnadjusted.Add(message.predictionErrorUnadjusted); + predictionErrorAdjusted = message.predictionErrorAdjusted; + // Debug.Log($"[Client] predictionError avg={(_predictionErrorUnadjusted.Value*1000):F1} ms"); + } + + // server rtt calculation ////////////////////////////////////////////// + // Executed at the client when we receive a ping message from the server. + // in other words, this is for server sided ping + rtt calculation. + // reply with a pong containing the time from the server + internal static void OnClientPing(NetworkPingMessage message) + { + // Debug.Log($"OnClientPing conn:{conn}"); + NetworkPongMessage pongMessage = new NetworkPongMessage + ( + message.localTime, + 0, 0 // server doesn't predict + ); + NetworkClient.Send(pongMessage, Channels.Unreliable); + } + + // Executed at the server when we receive a Pong message back. + // find out how long it took since we sent the Ping + // and update time offset + internal static void OnServerPong(NetworkConnectionToClient conn, NetworkPongMessage message) + { + // prevent attackers from sending timestamps which are in the future + if (message.localTime > localTime) return; + + // how long did this message take to come back + double newRtt = localTime - message.localTime; + conn._rtt.Add(newRtt); + } + + internal static void EarlyUpdate() + { +#if !UNITY_2020_3_OR_NEWER + localFrameTime = stopwatch.Elapsed.TotalSeconds; +#endif + } + } +} diff --git a/Assets/Mirror/Core/NetworkTime.cs.meta b/Assets/Mirror/Core/NetworkTime.cs.meta new file mode 100644 index 0000000..1dc9e0a --- /dev/null +++ b/Assets/Mirror/Core/NetworkTime.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 09a0c241fc4a5496dbf4a0ab6e9a312c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkWriter.cs b/Assets/Mirror/Core/NetworkWriter.cs new file mode 100644 index 0000000..7ecf126 --- /dev/null +++ b/Assets/Mirror/Core/NetworkWriter.cs @@ -0,0 +1,249 @@ +using System; +using System.Runtime.CompilerServices; +using System.Text; +using Unity.Collections.LowLevel.Unsafe; +using UnityEngine; + +namespace Mirror +{ + /// Network Writer for most simple types like floats, ints, buffers, structs, etc. Use NetworkWriterPool.GetReader() to avoid allocations. + public class NetworkWriter + { + // the limit of ushort is so we can write string size prefix as only 2 bytes. + // -1 so we can still encode 'null' into it too. + public const ushort MaxStringLength = ushort.MaxValue - 1; + + // create writer immediately with it's own buffer so no one can mess with it and so that we can resize it. + // note: BinaryWriter allocates too much, so we only use a MemoryStream + // => 1500 bytes by default because on average, most packets will be <= MTU + public const int DefaultCapacity = 1500; + internal byte[] buffer = new byte[DefaultCapacity]; + + /// Next position to write to the buffer + public int Position; + + /// Current capacity. Automatically resized if necessary. + public int Capacity => buffer.Length; + + // cache encoding for WriteString instead of creating it each time. + // 1000 readers before: 1MB GC, 30ms + // 1000 readers after: 0.8MB GC, 18ms + // not(!) static for thread safety. + // + // throwOnInvalidBytes is true. + // writer should throw and user should fix if this ever happens. + // unlike reader, which needs to expect it to happen from attackers. + internal readonly UTF8Encoding encoding = new UTF8Encoding(false, true); + + /// Reset both the position and length of the stream + // Leaves the capacity the same so that we can reuse this writer without + // extra allocations + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Reset() + { + Position = 0; + } + + // NOTE that our runtime resizing comes at no extra cost because: + // 1. 'has space' checks are necessary even for fixed sized writers. + // 2. all writers will eventually be large enough to stop resizing. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void EnsureCapacity(int value) + { + if (buffer.Length < value) + { + int capacity = Math.Max(value, buffer.Length * 2); + Array.Resize(ref buffer, capacity); + } + } + + /// Copies buffer until 'Position' to a new array. + // Try to use ToArraySegment instead to avoid allocations! + public byte[] ToArray() + { + byte[] data = new byte[Position]; + Array.ConstrainedCopy(buffer, 0, data, 0, Position); + return data; + } + + /// Returns allocation-free ArraySegment until 'Position'. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ArraySegment ToArraySegment() => + new ArraySegment(buffer, 0, Position); + + // implicit conversion for convenience + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator ArraySegment(NetworkWriter w) => + w.ToArraySegment(); + + // WriteBlittable from DOTSNET. + // this is extremely fast, but only works for blittable types. + // + // Benchmark: + // WriteQuaternion x 100k, Macbook Pro 2015 @ 2.2Ghz, Unity 2018 LTS (debug mode) + // + // | Median | Min | Max | Avg | Std | (ms) + // before | 30.35 | 29.86 | 48.99 | 32.54 | 4.93 | + // blittable* | 5.69 | 5.52 | 27.51 | 7.78 | 5.65 | + // + // * without IsBlittable check + // => 4-6x faster! + // + // WriteQuaternion x 100k, Macbook Pro 2015 @ 2.2Ghz, Unity 2020.1 (release mode) + // + // | Median | Min | Max | Avg | Std | (ms) + // before | 9.41 | 8.90 | 23.02 | 10.72 | 3.07 | + // blittable* | 1.48 | 1.40 | 16.03 | 2.60 | 2.71 | + // + // * without IsBlittable check + // => 6x faster! + // + // Note: + // WriteBlittable assumes same endianness for server & client. + // All Unity 2018+ platforms are little endian. + // => run NetworkWriterTests.BlittableOnThisPlatform() to verify! + // + // This is not safe to expose to random structs. + // * StructLayout.Sequential is the default, which is safe. + // if the struct contains a reference type, it is converted to Auto. + // but since all structs here are unmanaged blittable, it's safe. + // see also: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=netframework-4.8#system-runtime-interopservices-layoutkind-sequential + // * StructLayout.Pack depends on CPU word size. + // this may be different 4 or 8 on some ARM systems, etc. + // this is not safe, and would cause bytes/shorts etc. to be padded. + // see also: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.structlayoutattribute.pack?view=net-6.0 + // * If we force pack all to '1', they would have no padding which is + // great for bandwidth. but on some android systems, CPU can't read + // unaligned memory. + // see also: https://github.com/vis2k/Mirror/issues/3044 + // * The only option would be to force explicit layout with multiples + // of word size. but this requires lots of weaver checking and is + // still questionable (IL2CPP etc.). + // + // Note: inlining WriteBlittable is enough. don't inline WriteInt etc. + // we don't want WriteBlittable to be copied in place everywhere. + internal unsafe void WriteBlittable(T value) + where T : unmanaged + { + // check if blittable for safety +#if UNITY_EDITOR + if (!UnsafeUtility.IsBlittable(typeof(T))) + { + Debug.LogError($"{typeof(T)} is not blittable!"); + return; + } +#endif + // calculate size + // sizeof(T) gets the managed size at compile time. + // Marshal.SizeOf gets the unmanaged size at runtime (slow). + // => our 1mio writes benchmark is 6x slower with Marshal.SizeOf + // => for blittable types, sizeof(T) is even recommended: + // https://docs.microsoft.com/en-us/dotnet/standard/native-interop/best-practices + int size = sizeof(T); + + // ensure capacity + // NOTE that our runtime resizing comes at no extra cost because: + // 1. 'has space' checks are necessary even for fixed sized writers. + // 2. all writers will eventually be large enough to stop resizing. + EnsureCapacity(Position + size); + + // write blittable + fixed (byte* ptr = &buffer[Position]) + { +#if UNITY_ANDROID + // on some android systems, assigning *(T*)ptr throws a NRE if + // the ptr isn't aligned (i.e. if Position is 1,2,3,5, etc.). + // here we have to use memcpy. + // + // => we can't get a pointer of a struct in C# without + // marshalling allocations + // => instead, we stack allocate an array of type T and use that + // => stackalloc avoids GC and is very fast. it only works for + // value types, but all blittable types are anyway. + // + // this way, we can still support blittable reads on android. + // see also: https://github.com/vis2k/Mirror/issues/3044 + // (solution discovered by AIIO, FakeByte, mischa) + T* valueBuffer = stackalloc T[1]{value}; + UnsafeUtility.MemCpy(ptr, valueBuffer, size); +#else + // cast buffer to T* pointer, then assign value to the area + *(T*)ptr = value; +#endif + } + Position += size; + } + + // blittable'?' template for code reuse + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void WriteBlittableNullable(T? value) + where T : unmanaged + { + // bool isn't blittable. write as byte. + WriteByte((byte)(value.HasValue ? 0x01 : 0x00)); + + // only write value if exists. saves bandwidth. + if (value.HasValue) + WriteBlittable(value.Value); + } + + public void WriteByte(byte value) => WriteBlittable(value); + + // for byte arrays with consistent size, where the reader knows how many to read + // (like a packet opcode that's always the same) + public void WriteBytes(byte[] array, int offset, int count) + { + EnsureCapacity(Position + count); + Array.ConstrainedCopy(array, offset, this.buffer, Position, count); + Position += count; + } + // write an unsafe byte* array. + // useful for bit tree compression, etc. + public unsafe bool WriteBytes(byte* ptr, int offset, int size) + { + EnsureCapacity(Position + size); + + fixed (byte* destination = &buffer[Position]) + { + // write 'size' bytes at position + // 10 mio writes: 868ms + // Array.Copy(value.Array, value.Offset, buffer, Position, value.Count); + // 10 mio writes: 775ms + // Buffer.BlockCopy(value.Array, value.Offset, buffer, Position, value.Count); + // 10 mio writes: 637ms + UnsafeUtility.MemCpy(destination, ptr + offset, size); + } + + Position += size; + return true; + } + + /// Writes any type that mirror supports. Uses weaver populated Writer(T).write. + public void Write(T value) + { + Action writeDelegate = Writer.write; + if (writeDelegate == null) + { + Debug.LogError($"No writer found for {typeof(T)}. This happens either if you are missing a NetworkWriter extension for your custom type, or if weaving failed. Try to reimport a script to weave again."); + } + else + { + writeDelegate(this, value); + } + } + + // print with buffer content for easier debugging. + // [content, position / capacity]. + // showing "position / space" would be too confusing. + public override string ToString() => + $"[{ToArraySegment().ToHexString()} @ {Position}/{Capacity}]"; + } + + /// Helper class that weaver populates with all writer types. + // Note that c# creates a different static variable for each type + // -> Weaver.ReaderWriterProcessor.InitializeReaderAndWriters() populates it + public static class Writer + { + public static Action write; + } +} diff --git a/Assets/Mirror/Core/NetworkWriter.cs.meta b/Assets/Mirror/Core/NetworkWriter.cs.meta new file mode 100644 index 0000000..c938496 --- /dev/null +++ b/Assets/Mirror/Core/NetworkWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48d2207bcef1f4477b624725f075f9bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkWriterExtensions.cs b/Assets/Mirror/Core/NetworkWriterExtensions.cs new file mode 100644 index 0000000..fef9f61 --- /dev/null +++ b/Assets/Mirror/Core/NetworkWriterExtensions.cs @@ -0,0 +1,430 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + // Mirror's Weaver automatically detects all NetworkWriter function types, + // but they do all need to be extensions. + public static class NetworkWriterExtensions + { + public static void WriteByte(this NetworkWriter writer, byte value) => writer.WriteBlittable(value); + public static void WriteByteNullable(this NetworkWriter writer, byte? value) => writer.WriteBlittableNullable(value); + + public static void WriteSByte(this NetworkWriter writer, sbyte value) => writer.WriteBlittable(value); + public static void WriteSByteNullable(this NetworkWriter writer, sbyte? value) => writer.WriteBlittableNullable(value); + + // char is not blittable. convert to ushort. + public static void WriteChar(this NetworkWriter writer, char value) => writer.WriteBlittable((ushort)value); + public static void WriteCharNullable(this NetworkWriter writer, char? value) => writer.WriteBlittableNullable((ushort?)value); + + // bool is not blittable. convert to byte. + public static void WriteBool(this NetworkWriter writer, bool value) => writer.WriteBlittable((byte)(value ? 1 : 0)); + public static void WriteBoolNullable(this NetworkWriter writer, bool? value) => writer.WriteBlittableNullable(value.HasValue ? ((byte)(value.Value ? 1 : 0)) : new byte?()); + + public static void WriteShort(this NetworkWriter writer, short value) => writer.WriteBlittable(value); + public static void WriteShortNullable(this NetworkWriter writer, short? value) => writer.WriteBlittableNullable(value); + + public static void WriteUShort(this NetworkWriter writer, ushort value) => writer.WriteBlittable(value); + public static void WriteUShortNullable(this NetworkWriter writer, ushort? value) => writer.WriteBlittableNullable(value); + + public static void WriteInt(this NetworkWriter writer, int value) => writer.WriteBlittable(value); + public static void WriteIntNullable(this NetworkWriter writer, int? value) => writer.WriteBlittableNullable(value); + + public static void WriteUInt(this NetworkWriter writer, uint value) => writer.WriteBlittable(value); + public static void WriteUIntNullable(this NetworkWriter writer, uint? value) => writer.WriteBlittableNullable(value); + + public static void WriteLong(this NetworkWriter writer, long value) => writer.WriteBlittable(value); + public static void WriteLongNullable(this NetworkWriter writer, long? value) => writer.WriteBlittableNullable(value); + + public static void WriteULong(this NetworkWriter writer, ulong value) => writer.WriteBlittable(value); + public static void WriteULongNullable(this NetworkWriter writer, ulong? value) => writer.WriteBlittableNullable(value); + + public static void WriteFloat(this NetworkWriter writer, float value) => writer.WriteBlittable(value); + public static void WriteFloatNullable(this NetworkWriter writer, float? value) => writer.WriteBlittableNullable(value); + + public static void WriteDouble(this NetworkWriter writer, double value) => writer.WriteBlittable(value); + public static void WriteDoubleNullable(this NetworkWriter writer, double? value) => writer.WriteBlittableNullable(value); + + public static void WriteDecimal(this NetworkWriter writer, decimal value) => writer.WriteBlittable(value); + public static void WriteDecimalNullable(this NetworkWriter writer, decimal? value) => writer.WriteBlittableNullable(value); + + public static void WriteString(this NetworkWriter writer, string value) + { + // write 0 for null support, increment real size by 1 + // (note: original HLAPI would write "" for null strings, but if a + // string is null on the server then it should also be null + // on the client) + if (value == null) + { + writer.WriteUShort(0); + return; + } + + // WriteString copies into the buffer manually. + // need to ensure capacity here first, manually. + int maxSize = writer.encoding.GetMaxByteCount(value.Length); + writer.EnsureCapacity(writer.Position + 2 + maxSize); // 2 bytes position + N bytes encoding + + // encode it into the buffer first. + // reserve 2 bytes for header after we know how much was written. + int written = writer.encoding.GetBytes(value, 0, value.Length, writer.buffer, writer.Position + 2); + + // check if within max size, otherwise Reader can't read it. + if (written > NetworkWriter.MaxStringLength) + throw new IndexOutOfRangeException($"NetworkWriter.WriteString - Value too long: {written} bytes. Limit: {NetworkWriter.MaxStringLength} bytes"); + + // .Position is unchanged, so fill in the size header now. + // we already ensured that max size fits into ushort.max-1. + writer.WriteUShort(checked((ushort)(written + 1))); // Position += 2 + + // now update position by what was written above + writer.Position += written; + } + + // Weaver needs a write function with just one byte[] parameter + // (we don't name it .Write(byte[]) because it's really a WriteBytesAndSize since we write size / null info too) + public static void WriteBytesAndSize(this NetworkWriter writer, byte[] buffer) + { + // buffer might be null, so we can't use .Length in that case + writer.WriteBytesAndSize(buffer, 0, buffer != null ? buffer.Length : 0); + } + + // for byte arrays with dynamic size, where the reader doesn't know how many will come + // (like an inventory with different items etc.) + public static void WriteBytesAndSize(this NetworkWriter writer, byte[] buffer, int offset, int count) + { + // null is supported because [SyncVar]s might be structs with null byte[] arrays + // write 0 for null array, increment normal size by 1 to save bandwidth + // (using size=-1 for null would limit max size to 32kb instead of 64kb) + if (buffer == null) + { + writer.WriteUInt(0u); + return; + } + writer.WriteUInt(checked((uint)count) + 1u); + writer.WriteBytes(buffer, offset, count); + } + + // writes ArraySegment of byte (most common type) and size header + public static void WriteArraySegmentAndSize(this NetworkWriter writer, ArraySegment segment) + { + writer.WriteBytesAndSize(segment.Array, segment.Offset, segment.Count); + } + + // writes ArraySegment of any type, and size header + public static void WriteArraySegment(this NetworkWriter writer, ArraySegment segment) + { + int length = segment.Count; + writer.WriteInt(length); + for (int i = 0; i < length; i++) + { + writer.Write(segment.Array[segment.Offset + i]); + } + } + + public static void WriteVector2(this NetworkWriter writer, Vector2 value) => writer.WriteBlittable(value); + public static void WriteVector2Nullable(this NetworkWriter writer, Vector2? value) => writer.WriteBlittableNullable(value); + + public static void WriteVector3(this NetworkWriter writer, Vector3 value) => writer.WriteBlittable(value); + public static void WriteVector3Nullable(this NetworkWriter writer, Vector3? value) => writer.WriteBlittableNullable(value); + + public static void WriteVector4(this NetworkWriter writer, Vector4 value) => writer.WriteBlittable(value); + public static void WriteVector4Nullable(this NetworkWriter writer, Vector4? value) => writer.WriteBlittableNullable(value); + + public static void WriteVector2Int(this NetworkWriter writer, Vector2Int value) => writer.WriteBlittable(value); + public static void WriteVector2IntNullable(this NetworkWriter writer, Vector2Int? value) => writer.WriteBlittableNullable(value); + + public static void WriteVector3Int(this NetworkWriter writer, Vector3Int value) => writer.WriteBlittable(value); + public static void WriteVector3IntNullable(this NetworkWriter writer, Vector3Int? value) => writer.WriteBlittableNullable(value); + + public static void WriteColor(this NetworkWriter writer, Color value) => writer.WriteBlittable(value); + public static void WriteColorNullable(this NetworkWriter writer, Color? value) => writer.WriteBlittableNullable(value); + + public static void WriteColor32(this NetworkWriter writer, Color32 value) => writer.WriteBlittable(value); + public static void WriteColor32Nullable(this NetworkWriter writer, Color32? value) => writer.WriteBlittableNullable(value); + + public static void WriteQuaternion(this NetworkWriter writer, Quaternion value) => writer.WriteBlittable(value); + public static void WriteQuaternionNullable(this NetworkWriter writer, Quaternion? value) => writer.WriteBlittableNullable(value); + + // Rect is a struct with properties instead of fields + public static void WriteRect(this NetworkWriter writer, Rect value) + { + writer.WriteVector2(value.position); + writer.WriteVector2(value.size); + } + public static void WriteRectNullable(this NetworkWriter writer, Rect? value) + { + writer.WriteBool(value.HasValue); + if (value.HasValue) + writer.WriteRect(value.Value); + } + + // Plane is a struct with properties instead of fields + public static void WritePlane(this NetworkWriter writer, Plane value) + { + writer.WriteVector3(value.normal); + writer.WriteFloat(value.distance); + } + public static void WritePlaneNullable(this NetworkWriter writer, Plane? value) + { + writer.WriteBool(value.HasValue); + if (value.HasValue) + writer.WritePlane(value.Value); + } + + // Ray is a struct with properties instead of fields + public static void WriteRay(this NetworkWriter writer, Ray value) + { + writer.WriteVector3(value.origin); + writer.WriteVector3(value.direction); + } + public static void WriteRayNullable(this NetworkWriter writer, Ray? value) + { + writer.WriteBool(value.HasValue); + if (value.HasValue) + writer.WriteRay(value.Value); + } + + // LayerMask is a struct with properties instead of fields + public static void WriteLayerMask(this NetworkWriter writer, LayerMask layerMask) + { + // 32 layers as a flags enum, max value of 496, we only need a UShort. + writer.WriteUShort((ushort)layerMask.value); + } + public static void WriteLayerMaskNullable(this NetworkWriter writer, LayerMask? layerMask) + { + writer.WriteBool(layerMask.HasValue); + if (layerMask.HasValue) + writer.WriteLayerMask(layerMask.Value); + } + + public static void WriteMatrix4x4(this NetworkWriter writer, Matrix4x4 value) => writer.WriteBlittable(value); + public static void WriteMatrix4x4Nullable(this NetworkWriter writer, Matrix4x4? value) => writer.WriteBlittableNullable(value); + + public static void WriteGuid(this NetworkWriter writer, Guid value) + { +#if !UNITY_2021_3_OR_NEWER + // Unity 2019 doesn't have Span yet + byte[] data = value.ToByteArray(); + writer.WriteBytes(data, 0, data.Length); +#else + // WriteBlittable(Guid) isn't safe. see WriteBlittable comments. + // Guid is Sequential, but we can't guarantee packing. + // TryWriteBytes is safe and allocation free. + writer.EnsureCapacity(writer.Position + 16); + value.TryWriteBytes(new Span(writer.buffer, writer.Position, 16)); + writer.Position += 16; +#endif + } + public static void WriteGuidNullable(this NetworkWriter writer, Guid? value) + { + writer.WriteBool(value.HasValue); + if (value.HasValue) + writer.WriteGuid(value.Value); + } + + public static void WriteNetworkIdentity(this NetworkWriter writer, NetworkIdentity value) + { + if (value == null) + { + writer.WriteUInt(0); + return; + } + + // users might try to use unspawned / prefab GameObjects in + // rpcs/cmds/syncvars/messages. they would be null on the other + // end, and it might not be obvious why. let's make it obvious. + // https://github.com/vis2k/Mirror/issues/2060 + // + // => warning (instead of exception) because we also use a warning + // if a GameObject doesn't have a NetworkIdentity component etc. + if (value.netId == 0) + Debug.LogWarning($"Attempted to serialize unspawned GameObject: {value.name}. Prefabs and unspawned GameObjects would always be null on the other side. Please spawn it before using it in [SyncVar]s/Rpcs/Cmds/NetworkMessages etc."); + + writer.WriteUInt(value.netId); + } + + public static void WriteNetworkBehaviour(this NetworkWriter writer, NetworkBehaviour value) + { + if (value == null) + { + writer.WriteUInt(0); + return; + } + + // users might try to use unspawned / prefab NetworkBehaviours in + // rpcs/cmds/syncvars/messages. they would be null on the other + // end, and it might not be obvious why. let's make it obvious. + // https://github.com/vis2k/Mirror/issues/2060 + // and more recently https://github.com/MirrorNetworking/Mirror/issues/3399 + // + // => warning (instead of exception) because we also use a warning + // when writing an unspawned NetworkIdentity + if (value.netId == 0) + { + Debug.LogWarning($"Attempted to serialize unspawned NetworkBehaviour: of type {value.GetType()} on GameObject {value.name}. Prefabs and unspawned GameObjects would always be null on the other side. Please spawn it before using it in [SyncVar]s/Rpcs/Cmds/NetworkMessages etc."); + writer.WriteUInt(0); + return; + } + + writer.WriteUInt(value.netId); + writer.WriteByte(value.ComponentIndex); + } + + public static void WriteTransform(this NetworkWriter writer, Transform value) + { + if (value == null) + { + writer.WriteUInt(0); + return; + } + if (value.TryGetComponent(out NetworkIdentity identity)) + { + writer.WriteUInt(identity.netId); + } + else + { + // if users attempt to pass a transform without NetworkIdentity + // to a [Command] or [SyncVar], it should show an obvious warning. + Debug.LogWarning($"Attempted to sync a Transform ({value}) which isn't networked. Transforms without a NetworkIdentity component can't be synced."); + writer.WriteUInt(0); + } + } + + public static void WriteGameObject(this NetworkWriter writer, GameObject value) + { + if (value == null) + { + writer.WriteUInt(0); + return; + } + + // warn if the GameObject doesn't have a NetworkIdentity, + if (!value.TryGetComponent(out NetworkIdentity identity)) + Debug.LogWarning($"Attempted to sync a GameObject ({value}) which isn't networked. GameObject without a NetworkIdentity component can't be synced."); + + // serialize the correct amount of data in any case to make sure + // that the other end can read the expected amount of data too. + writer.WriteNetworkIdentity(identity); + } + + // while SyncList is recommended for NetworkBehaviours, + // structs may have .List members which weaver needs to be able to + // fully serialize for NetworkMessages etc. + // note that Weaver/Writers/GenerateWriter() handles this manually. + public static void WriteList(this NetworkWriter writer, List list) + { + // 'null' is encoded as '-1' + if (list is null) + { + writer.WriteInt(-1); + return; + } + + // check if within max size, otherwise Reader can't read it. + if (list.Count > NetworkReader.AllocationLimit) + throw new IndexOutOfRangeException($"NetworkWriter.WriteList - List<{typeof(T)}> too big: {list.Count} elements. Limit: {NetworkReader.AllocationLimit}"); + + writer.WriteInt(list.Count); + for (int i = 0; i < list.Count; i++) + writer.Write(list[i]); + } + + // while SyncSet is recommended for NetworkBehaviours, + // structs may have .Set members which weaver needs to be able to + // fully serialize for NetworkMessages etc. + // note that Weaver/Writers/GenerateWriter() handles this manually. + // TODO writer not found. need to adjust weaver first. see tests. + /* + public static void WriteHashSet(this NetworkWriter writer, HashSet hashSet) + { + if (hashSet is null) + { + writer.WriteInt(-1); + return; + } + writer.WriteInt(hashSet.Count); + foreach (T item in hashSet) + writer.Write(item); + } + */ + + public static void WriteArray(this NetworkWriter writer, T[] array) + { + // 'null' is encoded as '-1' + if (array is null) + { + writer.WriteInt(-1); + return; + } + + // check if within max size, otherwise Reader can't read it. + if (array.Length > NetworkReader.AllocationLimit) + throw new IndexOutOfRangeException($"NetworkWriter.WriteArray - Array<{typeof(T)}> too big: {array.Length} elements. Limit: {NetworkReader.AllocationLimit}"); + + writer.WriteInt(array.Length); + for (int i = 0; i < array.Length; i++) + writer.Write(array[i]); + } + + public static void WriteUri(this NetworkWriter writer, Uri uri) + { + writer.WriteString(uri?.ToString()); + } + + public static void WriteTexture2D(this NetworkWriter writer, Texture2D texture2D) + { + // TODO allocation protection when sending textures to server. + // currently can allocate 32k x 32k x 4 byte = 3.8 GB + + // support 'null' textures for [SyncVar]s etc. + // https://github.com/vis2k/Mirror/issues/3144 + // simply send -1 for width. + if (texture2D == null) + { + writer.WriteShort(-1); + return; + } + + // check if within max size, otherwise Reader can't read it. + int totalSize = texture2D.width * texture2D.height; + if (totalSize > NetworkReader.AllocationLimit) + throw new IndexOutOfRangeException($"NetworkWriter.WriteTexture2D - Texture2D total size (width*height) too big: {totalSize}. Limit: {NetworkReader.AllocationLimit}"); + + // write dimensions first so reader can create the texture with size + // 32k x 32k short is more than enough + writer.WriteShort((short)texture2D.width); + writer.WriteShort((short)texture2D.height); + writer.WriteArray(texture2D.GetPixels32()); + } + + public static void WriteSprite(this NetworkWriter writer, Sprite sprite) + { + // support 'null' textures for [SyncVar]s etc. + // https://github.com/vis2k/Mirror/issues/3144 + // simply send a 'null' for texture content. + if (sprite == null) + { + writer.WriteTexture2D(null); + return; + } + + writer.WriteTexture2D(sprite.texture); + writer.WriteRect(sprite.rect); + writer.WriteVector2(sprite.pivot); + } + + public static void WriteDateTime(this NetworkWriter writer, DateTime dateTime) + { + writer.WriteDouble(dateTime.ToOADate()); + } + + public static void WriteDateTimeNullable(this NetworkWriter writer, DateTime? dateTime) + { + writer.WriteBool(dateTime.HasValue); + if (dateTime.HasValue) + writer.WriteDouble(dateTime.Value.ToOADate()); + } + } +} diff --git a/Assets/Mirror/Core/NetworkWriterExtensions.cs.meta b/Assets/Mirror/Core/NetworkWriterExtensions.cs.meta new file mode 100644 index 0000000..9bbdaf0 --- /dev/null +++ b/Assets/Mirror/Core/NetworkWriterExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 94259792df2a404892c3e2377f58d0cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkWriterPool.cs b/Assets/Mirror/Core/NetworkWriterPool.cs new file mode 100644 index 0000000..5eefa2a --- /dev/null +++ b/Assets/Mirror/Core/NetworkWriterPool.cs @@ -0,0 +1,37 @@ +// API consistent with Microsoft's ObjectPool. +using System.Runtime.CompilerServices; + +namespace Mirror +{ + /// Pool of NetworkWriters to avoid allocations. + public static class NetworkWriterPool + { + // reuse Pool + // we still wrap it in NetworkWriterPool.Get/Recycle so we can reset the + // position before reusing. + // this is also more consistent with NetworkReaderPool where we need to + // assign the internal buffer before reusing. + static readonly Pool Pool = new Pool( + () => new NetworkWriterPooled(), + // initial capacity to avoid allocations in the first few frames + // 1000 * 1200 bytes = around 1 MB. + 1000 + ); + + /// Get a writer from the pool. Creates new one if pool is empty. + public static NetworkWriterPooled Get() + { + // grab from pool & reset position + NetworkWriterPooled writer = Pool.Get(); + writer.Reset(); + return writer; + } + + /// Return a writer to the pool. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Return(NetworkWriterPooled writer) + { + Pool.Return(writer); + } + } +} diff --git a/Assets/Mirror/Core/NetworkWriterPool.cs.meta b/Assets/Mirror/Core/NetworkWriterPool.cs.meta new file mode 100644 index 0000000..19d2bb7 --- /dev/null +++ b/Assets/Mirror/Core/NetworkWriterPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f34b53bea38e4f259eb8dc211e4fdb6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/NetworkWriterPooled.cs b/Assets/Mirror/Core/NetworkWriterPooled.cs new file mode 100644 index 0000000..5ac371d --- /dev/null +++ b/Assets/Mirror/Core/NetworkWriterPooled.cs @@ -0,0 +1,13 @@ +// "NetworkWriterPooled" instead of "PooledNetworkWriter" to group files, for +// easier IDE workflow and more elegant code. +using System; + +namespace Mirror +{ + /// Pooled NetworkWriter, automatically returned to pool when using 'using' + // TODO make sealed again after removing obsolete NetworkWriterPooled! + public class NetworkWriterPooled : NetworkWriter, IDisposable + { + public void Dispose() => NetworkWriterPool.Return(this); + } +} diff --git a/Assets/Mirror/Core/NetworkWriterPooled.cs.meta b/Assets/Mirror/Core/NetworkWriterPooled.cs.meta new file mode 100644 index 0000000..5571d6f --- /dev/null +++ b/Assets/Mirror/Core/NetworkWriterPooled.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9fab936bf3c4716a452d94ad5ecbebe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/PortTransport.cs b/Assets/Mirror/Core/PortTransport.cs new file mode 100644 index 0000000..19a7dfd --- /dev/null +++ b/Assets/Mirror/Core/PortTransport.cs @@ -0,0 +1,13 @@ +// convenience interface for transports which use a port. +// useful for cases where someone wants to 'just set the port' independent of +// which transport it is. +// +// note that not all transports have ports, but most do. + +namespace Mirror +{ + public interface PortTransport + { + ushort Port { get; set; } + } +} diff --git a/Assets/Mirror/Core/PortTransport.cs.meta b/Assets/Mirror/Core/PortTransport.cs.meta new file mode 100644 index 0000000..3f96d30 --- /dev/null +++ b/Assets/Mirror/Core/PortTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7c7c2820d7974cb28c7bfe9aae890a0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Prediction.meta b/Assets/Mirror/Core/Prediction.meta new file mode 100644 index 0000000..83fb83b --- /dev/null +++ b/Assets/Mirror/Core/Prediction.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7e8e801f9c7f4b858d9a6c162e64ca84 +timeCreated: 1694005962 \ No newline at end of file diff --git a/Assets/Mirror/Core/Prediction/Prediction.cs b/Assets/Mirror/Core/Prediction/Prediction.cs new file mode 100644 index 0000000..55204f5 --- /dev/null +++ b/Assets/Mirror/Core/Prediction/Prediction.cs @@ -0,0 +1,176 @@ +// standalone, easy to test algorithms for prediction +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror +{ + // prediction may capture Rigidbody3D/2D/etc. state + // have a common interface. + public interface PredictedState + { + double timestamp { get; } + + // use Vector3 for both Rigidbody3D and Rigidbody2D, that's fine + Vector3 position { get; set; } + Vector3 positionDelta { get; set; } + + Quaternion rotation { get; set; } + Quaternion rotationDelta { get; set; } + + Vector3 velocity { get; set; } + Vector3 velocityDelta { get; set; } + + Vector3 angularVelocity { get; set; } + Vector3 angularVelocityDelta { get; set; } + } + + public static class Prediction + { + // get the two states closest to a given timestamp. + // those can be used to interpolate the exact state at that time. + public static bool Sample( + SortedList history, + double timestamp, // current server time + out T before, + out T after, + out int afterIndex, + out double t) // interpolation factor + { + before = default; + after = default; + t = 0; + afterIndex = -1; + + // can't sample an empty history + // interpolation needs at least two entries. + // can't Lerp(A, A, 1.5). dist(A, A) * 1.5 is always 0. + if (history.Count < 2) { + return false; + } + + // older than oldest + if (timestamp < history.Keys[0]) { + return false; + } + + // iterate through the history + // TODO this needs to be faster than O(N) + // search around that area. + // should be O(1) most of the time, unless sampling was off. + int index = 0; // manually count when iterating. easier than for-int loop. + KeyValuePair prev = new KeyValuePair(); + foreach (KeyValuePair entry in history) { + // exact match? + if (timestamp == entry.Key) + { + before = entry.Value; + after = entry.Value; + afterIndex = index; + t = Mathd.InverseLerp(entry.Key, entry.Key, timestamp); + return true; + } + + // did we check beyond timestamp? then return the previous two. + if (entry.Key > timestamp) + { + before = prev.Value; + after = entry.Value; + afterIndex = index; + t = Mathd.InverseLerp(prev.Key, entry.Key, timestamp); + return true; + } + + // remember the last + prev = entry; + index += 1; + } + + return false; + } + + // inserts a server state into the client's history. + // readjust the deltas of the states after the inserted one. + // returns the corrected final position. + public static T CorrectHistory( + SortedList stateHistory, + int stateHistoryLimit, + T corrected, // corrected state with timestamp + T before, // state in history before the correction + T after, // state in history after the correction + int afterIndex) // index of the 'after' value so we don't need to find it again here + where T: PredictedState + { + // respect the limit + // TODO unit test to check if it respects max size + if (stateHistory.Count >= stateHistoryLimit) + stateHistory.RemoveAt(0); + + // insert the corrected state into the history, or overwrite if already exists + stateHistory[corrected.timestamp] = corrected; + + // the entry behind the inserted one still has the delta from (before, after). + // we need to correct it to (corrected, after). + // + // for example: + // before: (t=1.0, delta=10, position=10) + // after: (t=3.0, delta=20, position=30) + // + // then we insert: + // corrected: (t=2.5, delta=__, position=25) + // + // previous delta was from t=1.0 to t=3.0 => 2.0 + // inserted delta is from t=2.5 to t=3.0 => 0.5 + // multiplier is 0.5 / 2.0 = 0.25 + // multiply 'after.delta(20)' by 0.25 to get the new 'after.delta(5) + // + // so the new history is: + // before: (t=1.0, delta=10, position=10) + // corrected: (t=2.5, delta=__, position=25) + // after: (t=3.0, delta= 5, position=__) + // + // so when we apply the correction, the new after.position would be: + // corrected.position(25) + after.delta(5) = 30 + // + double previousDeltaTime = after.timestamp - before.timestamp; // 3.0 - 1.0 = 2.0 + double correctedDeltaTime = after.timestamp - corrected.timestamp; // 3.0 - 2.5 = 0.5 + + // fix multiplier becoming NaN if previousDeltaTime is 0: + // double multiplier = correctedDeltaTime / previousDeltaTime; + double multiplier = previousDeltaTime != 0 ? correctedDeltaTime / previousDeltaTime : 0; // 0.5 / 2.0 = 0.25 + + // recalculate 'after.delta' with the multiplier + after.positionDelta = Vector3.Lerp(Vector3.zero, after.positionDelta, (float)multiplier); + after.velocityDelta = Vector3.Lerp(Vector3.zero, after.velocityDelta, (float)multiplier); + after.angularVelocityDelta = Vector3.Lerp(Vector3.zero, after.angularVelocityDelta, (float)multiplier); + // Quaternions always need to be normalized in order to be a valid rotation after operations + after.rotationDelta = Quaternion.Slerp(Quaternion.identity, after.rotationDelta, (float)multiplier).normalized; + + // changes aren't saved until we overwrite them in the history + stateHistory[after.timestamp] = after; + + // second step: readjust all absolute values by rewinding client's delta moves on top of it. + T last = corrected; + for (int i = afterIndex; i < stateHistory.Count; ++i) + { + double key = stateHistory.Keys[i]; + T entry = stateHistory.Values[i]; + + // correct absolute position based on last + delta. + entry.position = last.position + entry.positionDelta; + entry.velocity = last.velocity + entry.velocityDelta; + entry.angularVelocity = last.angularVelocity + entry.angularVelocityDelta; + // Quaternions always need to be normalized in order to be a valid rotation after operations + entry.rotation = (entry.rotationDelta * last.rotation).normalized; // quaternions add delta by multiplying in this order + + // save the corrected entry into history. + stateHistory[key] = entry; + + // save last + last = entry; + } + + // third step: return the final recomputed state. + return last; + } + } +} diff --git a/Assets/Mirror/Core/Prediction/Prediction.cs.meta b/Assets/Mirror/Core/Prediction/Prediction.cs.meta new file mode 100644 index 0000000..196bd46 --- /dev/null +++ b/Assets/Mirror/Core/Prediction/Prediction.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 216d494d910445ea8a7acc7c889212d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/RemoteCalls.cs b/Assets/Mirror/Core/RemoteCalls.cs new file mode 100644 index 0000000..5dbe52f --- /dev/null +++ b/Assets/Mirror/Core/RemoteCalls.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror.RemoteCalls +{ + // invoke type for Cmd/Rpc + public enum RemoteCallType { Command, ClientRpc } + + // remote call function delegate + public delegate void RemoteCallDelegate(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection); + + class Invoker + { + // GameObjects might have multiple components of TypeA.CommandA(). + // when invoking, we check if 'TypeA' is an instance of the type. + // the hash itself isn't enough because we wouldn't know which component + // to invoke it on if there are multiple of the same type. + public Type componentType; + public RemoteCallType callType; + public RemoteCallDelegate function; + public bool cmdRequiresAuthority; + + public bool AreEqual(Type componentType, RemoteCallType remoteCallType, RemoteCallDelegate invokeFunction) => + this.componentType == componentType && + this.callType == remoteCallType && + this.function == invokeFunction; + } + + /// Used to help manage remote calls for NetworkBehaviours + public static class RemoteProcedureCalls + { + public const string InvokeRpcPrefix = "InvokeUserCode_"; + + // one lookup for all remote calls. + // allows us to easily add more remote call types without duplicating code. + // note: do not clear those with [RuntimeInitializeOnLoad] + // + // IMPORTANT: cmd/rpc functions are identified via **HASHES**. + // an index would requires half the bandwidth, but introduces issues + // where static constructors are lazily called, so index order isn't + // guaranteed. keep hashes to avoid: + // https://github.com/vis2k/Mirror/pull/3135 + // https://github.com/vis2k/Mirror/issues/3138 + // BUT: 2 byte hash is enough if we check for collisions. that's what we + // do for NetworkMessage as well. + static readonly Dictionary remoteCallDelegates = new Dictionary(); + + static bool CheckIfDelegateExists(Type componentType, RemoteCallType remoteCallType, RemoteCallDelegate func, ushort functionHash) + { + if (remoteCallDelegates.ContainsKey(functionHash)) + { + // something already registered this hash. + // it's okay if it was the same function. + Invoker oldInvoker = remoteCallDelegates[functionHash]; + if (oldInvoker.AreEqual(componentType, remoteCallType, func)) + { + return true; + } + + // otherwise notify user. there is a rare chance of string + // hash collisions. + Debug.LogError($"Function {oldInvoker.componentType}.{oldInvoker.function.GetMethodName()} and {componentType}.{func.GetMethodName()} have the same hash. Please rename one of them. To save bandwidth, we only use 2 bytes for the hash, which has a small chance of collisions."); + } + + return false; + } + + // pass full function name to avoid ClassA.Func & ClassB.Func collisions + internal static ushort RegisterDelegate(Type componentType, string functionFullName, RemoteCallType remoteCallType, RemoteCallDelegate func, bool cmdRequiresAuthority = true) + { + // type+func so Inventory.RpcUse != Equipment.RpcUse + ushort hash = (ushort)(functionFullName.GetStableHashCode() & 0xFFFF); + + if (CheckIfDelegateExists(componentType, remoteCallType, func, hash)) + return hash; + + remoteCallDelegates[hash] = new Invoker + { + callType = remoteCallType, + componentType = componentType, + function = func, + cmdRequiresAuthority = cmdRequiresAuthority + }; + return hash; + } + + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + // need to pass componentType to support invoking on GameObjects with + // multiple components of same type with same remote call. + public static void RegisterCommand(Type componentType, string functionFullName, RemoteCallDelegate func, bool requiresAuthority) => + RegisterDelegate(componentType, functionFullName, RemoteCallType.Command, func, requiresAuthority); + + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + // need to pass componentType to support invoking on GameObjects with + // multiple components of same type with same remote call. + public static void RegisterRpc(Type componentType, string functionFullName, RemoteCallDelegate func) => + RegisterDelegate(componentType, functionFullName, RemoteCallType.ClientRpc, func); + + // to clean up tests + internal static void RemoveDelegate(ushort hash) => + remoteCallDelegates.Remove(hash); + + internal static bool GetFunctionMethodName(ushort functionHash, out string methodName) + { + if (remoteCallDelegates.TryGetValue(functionHash, out Invoker invoker)) + { + methodName = invoker.function.GetMethodName().Replace(InvokeRpcPrefix, ""); + return true; + } + methodName = ""; + return false; + } + + // note: no need to throw an error if not found. + // an attacker might just try to call a cmd with an rpc's hash etc. + // returning false is enough. + static bool GetInvokerForHash(ushort functionHash, RemoteCallType remoteCallType, out Invoker invoker) => + remoteCallDelegates.TryGetValue(functionHash, out invoker) && + invoker != null && + invoker.callType == remoteCallType; + + // InvokeCmd/Rpc Delegate can all use the same function here + internal static bool Invoke(ushort functionHash, RemoteCallType remoteCallType, NetworkReader reader, NetworkBehaviour component, NetworkConnectionToClient senderConnection = null) + { + // IMPORTANT: we check if the message's componentIndex component is + // actually of the right type. prevents attackers trying + // to invoke remote calls on wrong components. + if (GetInvokerForHash(functionHash, remoteCallType, out Invoker invoker) && + invoker.componentType.IsInstanceOfType(component)) + { + // invoke function on this component + invoker.function(component, reader, senderConnection); + return true; + } + return false; + } + + // check if the command 'requiresAuthority' which is set in the attribute + internal static bool CommandRequiresAuthority(ushort cmdHash) => + GetInvokerForHash(cmdHash, RemoteCallType.Command, out Invoker invoker) && + invoker.cmdRequiresAuthority; + + /// Gets the handler function by hash. Useful for profilers and debuggers. + public static RemoteCallDelegate GetDelegate(ushort functionHash) => + remoteCallDelegates.TryGetValue(functionHash, out Invoker invoker) + ? invoker.function + : null; + } +} + diff --git a/Assets/Mirror/Core/RemoteCalls.cs.meta b/Assets/Mirror/Core/RemoteCalls.cs.meta new file mode 100644 index 0000000..62b3288 --- /dev/null +++ b/Assets/Mirror/Core/RemoteCalls.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2cdbcbd1e377d6408a91acbec31ba16 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/SnapshotInterpolation.meta b/Assets/Mirror/Core/SnapshotInterpolation.meta new file mode 100644 index 0000000..85ac9a9 --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4468e736f87964eaebb9d55fc3e132f7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/SnapshotInterpolation/Snapshot.cs b/Assets/Mirror/Core/SnapshotInterpolation/Snapshot.cs new file mode 100644 index 0000000..6b8ba8a --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation/Snapshot.cs @@ -0,0 +1,17 @@ +// Snapshot interface so we can reuse it for all kinds of systems. +// for example, NetworkTransform, NetworkRigidbody, CharacterController etc. +// NOTE: we use '' and 'where T : Snapshot' to avoid boxing. +// List would cause allocations through boxing. +namespace Mirror +{ + public interface Snapshot + { + // the remote timestamp (when it was sent by the remote) + double remoteTime { get; set; } + + // the local timestamp (when it was received on our end) + // technically not needed for basic snapshot interpolation. + // only for dynamic buffer time adjustment. + double localTime { get; set; } + } +} diff --git a/Assets/Mirror/Core/SnapshotInterpolation/Snapshot.cs.meta b/Assets/Mirror/Core/SnapshotInterpolation/Snapshot.cs.meta new file mode 100644 index 0000000..24eedd7 --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation/Snapshot.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12afea28fdb94154868a0a3b7a9df55b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs new file mode 100644 index 0000000..2d1a2fc --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs @@ -0,0 +1,390 @@ +// snapshot interpolation V2 by mischa +// +// Unity independent to be engine agnostic & easy to test. +// boxing: in C#, uses does not box! passing the interface would box! +// +// credits: +// glenn fiedler: https://gafferongames.com/post/snapshot_interpolation/ +// fholm: netcode streams +// fakebyte: standard deviation for dynamic adjustment +// ninjakicka: math & debugging +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public static class SortedListExtensions + { + // removes the first 'amount' elements from the sorted list + public static void RemoveRange(this SortedList list, int amount) + { + // remove the first element 'amount' times. + // handles -1 and > count safely. + for (int i = 0; i < amount && i < list.Count; ++i) + list.RemoveAt(0); + } + } + + public static class SnapshotInterpolation + { + // calculate timescale for catch-up / slow-down + // note that negative threshold should be <0. + // caller should verify (i.e. Unity OnValidate). + // improves branch prediction. + public static double Timescale( + double drift, // how far we are off from bufferTime + double catchupSpeed, // in % [0,1] + double slowdownSpeed, // in % [0,1] + double absoluteCatchupNegativeThreshold, // in seconds (careful, we may run out of snapshots) + double absoluteCatchupPositiveThreshold) // in seconds + { + // if the drift time is too large, it means we are behind more time. + // so we need to speed up the timescale. + // note the threshold should be sendInterval * catchupThreshold. + if (drift > absoluteCatchupPositiveThreshold) + { + // localTimeline += 0.001; // too simple, this would ping pong + return 1 + catchupSpeed; // n% faster + } + + // if the drift time is too small, it means we are ahead of time. + // so we need to slow down the timescale. + // note the threshold should be sendInterval * catchupThreshold. + if (drift < absoluteCatchupNegativeThreshold) + { + // localTimeline -= 0.001; // too simple, this would ping pong + return 1 - slowdownSpeed; // n% slower + } + + // keep constant timescale while within threshold. + // this way we have perfectly smooth speed most of the time. + return 1; + } + + // calculate dynamic buffer time adjustment + public static double DynamicAdjustment( + double sendInterval, + double jitterStandardDeviation, + double dynamicAdjustmentTolerance) + { + // jitter is equal to delivery time standard variation. + // delivery time is made up of 'sendInterval+jitter'. + // .Average would be dampened by the constant sendInterval + // .StandardDeviation is the changes in 'jitter' that we want + // so add it to send interval again. + double intervalWithJitter = sendInterval + jitterStandardDeviation; + + // how many multiples of sendInterval is that? + // we want to convert to bufferTimeMultiplier later. + double multiples = intervalWithJitter / sendInterval; + + // add the tolerance + double safezone = multiples + dynamicAdjustmentTolerance; + // UnityEngine.Debug.Log($"sendInterval={sendInterval:F3} jitter std={jitterStandardDeviation:F3} => that is ~{multiples:F1} x sendInterval + {dynamicAdjustmentTolerance} => dynamic bufferTimeMultiplier={safezone}"); + return safezone; + } + + // helper function to insert a snapshot if it doesn't exist yet. + // extra function so we can use it for both cases: + // NetworkClient global timeline insertions & adjustments via Insert. + // NetworkBehaviour local insertion without any time adjustments. + public static bool InsertIfNotExists( + SortedList buffer, // snapshot buffer + int bufferLimit, // don't grow infinitely + T snapshot) // the newly received snapshot + where T : Snapshot + { + // slow clients may not be able to process incoming snapshots fast enough. + // infinitely growing snapshots would make it even worse. + // for example, run NetworkRigidbodyBenchmark while deep profiling client. + // the client just grows and reallocates the buffer forever. + if (buffer.Count >= bufferLimit) return false; + + // SortedList does not allow duplicates. + // we don't need to check ContainsKey (which is expensive). + // simply add and compare count before/after for the return value. + + //if (buffer.ContainsKey(snapshot.remoteTime)) return false; // too expensive + // buffer.Add(snapshot.remoteTime, snapshot); // throws if key exists + + int before = buffer.Count; + buffer[snapshot.remoteTime] = snapshot; // overwrites if key exists + return buffer.Count > before; + } + + // clamp timeline for cases where it gets too far behind. + // for example, a client app may go into the background and get updated + // with 1hz for a while. by the time it's back it's at least 30 frames + // behind, possibly more if the transport also queues up. In this + // scenario, at 1% catch up it took around 20+ seconds to finally catch + // up. For these kinds of scenarios it will be better to snap / clamp. + // + // to reproduce, try snapshot interpolation demo and press the button to + // simulate the client timeline at multiple seconds behind. it'll take + // a long time to catch up if the timeline is a long time behind. + public static double TimelineClamp( + double localTimeline, + double bufferTime, + double latestRemoteTime) + { + // we want local timeline to always be 'bufferTime' behind remote. + double targetTime = latestRemoteTime - bufferTime; + + // we define a boundary of 'bufferTime' around the target time. + // this is where catchup / slowdown will happen. + // outside of the area, we clamp. + double lowerBound = targetTime - bufferTime; // how far behind we can get + double upperBound = targetTime + bufferTime; // how far ahead we can get + return Mathd.Clamp(localTimeline, lowerBound, upperBound); + } + + // call this for every received snapshot. + // adds / inserts it to the list & initializes local time if needed. + public static void InsertAndAdjust( + SortedList buffer, // snapshot buffer + int bufferLimit, // don't grow infinitely + T snapshot, // the newly received snapshot + ref double localTimeline, // local interpolation time based on server time + ref double localTimescale, // timeline multiplier to apply catchup / slowdown over time + float sendInterval, // for debugging + double bufferTime, // offset for buffering + double catchupSpeed, // in % [0,1] + double slowdownSpeed, // in % [0,1] + ref ExponentialMovingAverage driftEma, // for catchup / slowdown + float catchupNegativeThreshold, // in % of sendInteral (careful, we may run out of snapshots) + float catchupPositiveThreshold, // in % of sendInterval + ref ExponentialMovingAverage deliveryTimeEma) // for dynamic buffer time adjustment + where T : Snapshot + { + // first snapshot? + // initialize local timeline. + // we want it to be behind by 'offset'. + // + // note that the first snapshot may be a lagging packet. + // so we would always be behind by that lag. + // this requires catchup later. + if (buffer.Count == 0) + localTimeline = snapshot.remoteTime - bufferTime; + + // insert into the buffer. + // + // note that we might insert it between our current interpolation + // which is fine, it adds another data point for accuracy. + // + // note that insert may be called twice for the same key. + // by default, this would throw. + // need to handle it silently. + if (InsertIfNotExists(buffer, bufferLimit, snapshot)) + { + // dynamic buffer adjustment needs delivery interval jitter + if (buffer.Count >= 2) + { + // note that this is not entirely accurate for scrambled inserts. + // + // we always use the last two, not what we just inserted + // even if we were to use the diff for what we just inserted, + // a scrambled insert would still not be 100% accurate: + // => assume a buffer of AC, with delivery time C-A + // => we then insert B, with delivery time B-A + // => but then technically the first C-A wasn't correct, + // as it would have to be C-B + // + // in practice, scramble is rare and won't make much difference + double previousLocalTime = buffer.Values[buffer.Count - 2].localTime; + double lastestLocalTime = buffer.Values[buffer.Count - 1].localTime; + + // this is the delivery time since last snapshot + double localDeliveryTime = lastestLocalTime - previousLocalTime; + + // feed the local delivery time to the EMA. + // this is what the original stream did too. + // our final dynamic buffer adjustment is different though. + // we use standard deviation instead of average. + deliveryTimeEma.Add(localDeliveryTime); + } + + // adjust timescale to catch up / slow down after each insertion + // because that is when we add new values to our EMA. + + // we want localTimeline to be about 'bufferTime' behind. + // for that, we need the delivery time EMA. + // snapshots may arrive out of order, we can not use last-timeline. + // we need to use the inserted snapshot's time - timeline. + double latestRemoteTime = snapshot.remoteTime; + + // ensure timeline stays within a reasonable bound behind/ahead. + localTimeline = TimelineClamp(localTimeline, bufferTime, latestRemoteTime); + + // calculate timediff after localTimeline override changes + double timeDiff = latestRemoteTime - localTimeline; + + // next, calculate average of a few seconds worth of timediffs. + // this gives smoother results. + // + // to calculate the average, we could simply loop through the + // last 'n' seconds worth of timediffs, but: + // - our buffer may only store a few snapshots (bufferTime) + // - looping through seconds worth of snapshots every time is + // expensive + // + // to solve this, we use an exponential moving average. + // https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average + // which is basically fancy math to do the same but faster. + // additionally, it allows us to look at more timeDiff values + // than we sould have access to in our buffer :) + driftEma.Add(timeDiff); + + // timescale depends on driftEma. + // driftEma only changes when inserting. + // therefore timescale only needs to be calculated when inserting. + // saves CPU cycles in Update. + + // next up, calculate how far we are currently away from bufferTime + double drift = driftEma.Value - bufferTime; + + // convert relative thresholds to absolute values based on sendInterval + double absoluteNegativeThreshold = sendInterval * catchupNegativeThreshold; + double absolutePositiveThreshold = sendInterval * catchupPositiveThreshold; + + // next, set localTimescale to catchup consistently in Update(). + // we quantize between default/catchup/slowdown, + // this way we have 'default' speed most of the time(!). + // and only catch up / slow down for a little bit occasionally. + // a consistent multiplier would never be exactly 1.0. + localTimescale = Timescale(drift, catchupSpeed, slowdownSpeed, absoluteNegativeThreshold, absolutePositiveThreshold); + + // debug logging + // UnityEngine.Debug.Log($"sendInterval={sendInterval:F3} bufferTime={bufferTime:F3} drift={drift:F3} driftEma={driftEma.Value:F3} timescale={localTimescale:F3} deliveryIntervalEma={deliveryTimeEma.Value:F3}"); + } + } + + // sample snapshot buffer to find the pair around the given time. + // returns indices so we can use it with RemoveRange to clear old snaps. + // make sure to use use buffer.Values[from/to], not buffer[from/to]. + // make sure to only call this is we have > 0 snapshots. + public static void Sample( + SortedList buffer, // snapshot buffer + double localTimeline, // local interpolation time based on server time + out int from, // the snapshot <= time + out int to, // the snapshot >= time + out double t) // interpolation factor + where T : Snapshot + { + from = -1; + to = -1; + t = 0; + + // sample from [0,count-1] so we always have two at 'i' and 'i+1'. + for (int i = 0; i < buffer.Count - 1; ++i) + { + // is local time between these two? + T first = buffer.Values[i]; + T second = buffer.Values[i + 1]; + if (localTimeline >= first.remoteTime && + localTimeline <= second.remoteTime) + { + // use these two snapshots + from = i; + to = i + 1; + t = Mathd.InverseLerp(first.remoteTime, second.remoteTime, localTimeline); + return; + } + } + + // didn't find two snapshots around local time. + // so pick either the first or last, depending on which is closer. + + // oldest snapshot ahead of local time? + if (buffer.Values[0].remoteTime > localTimeline) + { + from = to = 0; + t = 0; + } + // otherwise initialize both to the last one + else + { + from = to = buffer.Count - 1; + t = 0; + } + } + + // progress local timeline every update. + // + // ONLY CALL IF SNAPSHOTS.COUNT > 0! + // + // decoupled from Step for easier testing and so we can progress + // time only once in NetworkClient, while stepping for each component. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StepTime( + double deltaTime, // engine delta time (unscaled) + ref double localTimeline, // local interpolation time based on server time + double localTimescale) // catchup / slowdown is applied to time every update) + { + // move local forward in time, scaled with catchup / slowdown applied + localTimeline += deltaTime * localTimescale; + } + + // sample, clear old. + // call this every update. + // + // ONLY CALL IF SNAPSHOTS.COUNT > 0! + // + // returns true if there is anything to apply (requires at least 1 snap) + // from/to/t are out parameters instead of an interpolated 'computed'. + // this allows us to store from/to/t globally (i.e. in NetworkClient) + // and have each component apply the interpolation manually. + // besides, passing "Func Interpolate" would allocate anyway. + public static void StepInterpolation( + SortedList buffer, // snapshot buffer + double localTimeline, // local interpolation time based on server time + out T fromSnapshot, // we interpolate 'from' this snapshot + out T toSnapshot, // 'to' this snapshot + out double t) // at ratio 't' [0,1] + where T : Snapshot + { + // check this in caller: + // nothing to do if there are no snapshots at all yet + // if (buffer.Count == 0) return false; + + // sample snapshot buffer at local interpolation time + Sample(buffer, localTimeline, out int from, out int to, out t); + + // save from/to + fromSnapshot = buffer.Values[from]; + toSnapshot = buffer.Values[to]; + + // remove older snapshots that we definitely don't need anymore. + // after(!) using the indices. + // + // if we have 3 snapshots and we are between 2nd and 3rd: + // from = 1, to = 2 + // then we need to remove the first one, which is exactly 'from'. + // because 'from-1' = 0 would remove none. + buffer.RemoveRange(from); + } + + // update time, sample, clear old. + // call this every update. + // + // ONLY CALL IF SNAPSHOTS.COUNT > 0! + // + // returns true if there is anything to apply (requires at least 1 snap) + // from/to/t are out parameters instead of an interpolated 'computed'. + // this allows us to store from/to/t globally (i.e. in NetworkClient) + // and have each component apply the interpolation manually. + // besides, passing "Func Interpolate" would allocate anyway. + public static void Step( + SortedList buffer, // snapshot buffer + double deltaTime, // engine delta time (unscaled) + ref double localTimeline, // local interpolation time based on server time + double localTimescale, // catchup / slowdown is applied to time every update + out T fromSnapshot, // we interpolate 'from' this snapshot + out T toSnapshot, // 'to' this snapshot + out double t) // at ratio 't' [0,1] + where T : Snapshot + { + StepTime(deltaTime, ref localTimeline, localTimescale); + StepInterpolation(buffer, localTimeline, out fromSnapshot, out toSnapshot, out t); + } + } +} diff --git a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs.meta b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs.meta new file mode 100644 index 0000000..244c5fb --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 72c16070d85334011853813488ab1431 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs new file mode 100644 index 0000000..74feae4 --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs @@ -0,0 +1,70 @@ +// snapshot interpolation settings struct. +// can easily be exposed in Unity inspectors. +using System; +using UnityEngine; + +namespace Mirror +{ + // class so we can define defaults easily + [Serializable] + public class SnapshotInterpolationSettings + { + // decrease bufferTime at runtime to see the catchup effect. + // increase to see slowdown. + // 'double' so we can have very precise dynamic adjustment without rounding + [Header("Buffering")] + [Tooltip("Local simulation is behind by sendInterval * multiplier seconds.\n\nThis guarantees that we always have enough snapshots in the buffer to mitigate lags & jitter.\n\nIncrease this if the simulation isn't smooth. By default, it should be around 2.")] + public double bufferTimeMultiplier = 2; + + [Tooltip("If a client can't process snapshots fast enough, don't store too many.")] + public int bufferLimit = 32; + + // catchup ///////////////////////////////////////////////////////////// + // catchup thresholds in 'frames'. + // half a frame might be too aggressive. + [Header("Catchup / Slowdown")] + [Tooltip("Slowdown begins when the local timeline is moving too fast towards remote time. Threshold is in frames worth of snapshots.\n\nThis needs to be negative.\n\nDon't modify unless you know what you are doing.")] + public float catchupNegativeThreshold = -1; // careful, don't want to run out of snapshots + + [Tooltip("Catchup begins when the local timeline is moving too slow and getting too far away from remote time. Threshold is in frames worth of snapshots.\n\nThis needs to be positive.\n\nDon't modify unless you know what you are doing.")] + public float catchupPositiveThreshold = 1; + + [Tooltip("Local timeline acceleration in % while catching up.")] + [Range(0, 1)] + public double catchupSpeed = 0.02f; // see snap interp demo. 1% is too slow. + + [Tooltip("Local timeline slowdown in % while slowing down.")] + [Range(0, 1)] + public double slowdownSpeed = 0.04f; // slow down a little faster so we don't encounter empty buffer (= jitter) + + [Tooltip("Catchup/Slowdown is adjusted over n-second exponential moving average.")] + public int driftEmaDuration = 1; // shouldn't need to modify this, but expose it anyway + + // dynamic buffer time adjustment ////////////////////////////////////// + // dynamically adjusts bufferTimeMultiplier for smooth results. + // to understand how this works, try this manually: + // + // - disable dynamic adjustment + // - set jitter = 0.2 (20% is a lot!) + // - notice some stuttering + // - disable interpolation to see just how much jitter this really is(!) + // - enable interpolation again + // - manually increase bufferTimeMultiplier to 3-4 + // ... the cube slows down (blue) until it's smooth + // - with dynamic adjustment enabled, it will set 4 automatically + // ... the cube slows down (blue) until it's smooth as well + // + // note that 20% jitter is extreme. + // for this to be perfectly smooth, set the safety tolerance to '2'. + // but realistically this is not necessary, and '1' is enough. + [Header("Dynamic Adjustment")] + [Tooltip("Automatically adjust bufferTimeMultiplier for smooth results.\nSets a low multiplier on stable connections, and a high multiplier on jittery connections.")] + public bool dynamicAdjustment = true; + + [Tooltip("Safety buffer that is always added to the dynamic bufferTimeMultiplier adjustment.")] + public float dynamicAdjustmentTolerance = 1; // 1 is realistically just fine, 2 is very very safe even for 20% jitter. can be half a frame too. (see above comments) + + [Tooltip("Dynamic adjustment is computed over n-second exponential moving average standard deviation.")] + public int deliveryTimeEmaDuration = 2; // 1-2s recommended to capture average delivery time + } +} diff --git a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs.meta b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs.meta new file mode 100644 index 0000000..5cc16e4 --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f955b76b7956417088c03992b3622dc9 +timeCreated: 1678507210 \ No newline at end of file diff --git a/Assets/Mirror/Core/SnapshotInterpolation/TimeSnapshot.cs b/Assets/Mirror/Core/SnapshotInterpolation/TimeSnapshot.cs new file mode 100644 index 0000000..5bfdd3a --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation/TimeSnapshot.cs @@ -0,0 +1,15 @@ +namespace Mirror +{ + // empty snapshot that is only used to progress client's local timeline. + public struct TimeSnapshot : Snapshot + { + public double remoteTime { get; set; } + public double localTime { get; set; } + + public TimeSnapshot(double remoteTime, double localTime) + { + this.remoteTime = remoteTime; + this.localTime = localTime; + } + } +} diff --git a/Assets/Mirror/Core/SnapshotInterpolation/TimeSnapshot.cs.meta b/Assets/Mirror/Core/SnapshotInterpolation/TimeSnapshot.cs.meta new file mode 100644 index 0000000..5e37981 --- /dev/null +++ b/Assets/Mirror/Core/SnapshotInterpolation/TimeSnapshot.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afe2b5ed49634971a2aec720ad74e5cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/SyncDictionary.cs b/Assets/Mirror/Core/SyncDictionary.cs new file mode 100644 index 0000000..70ba9fd --- /dev/null +++ b/Assets/Mirror/Core/SyncDictionary.cs @@ -0,0 +1,326 @@ +using System.Collections; +using System.Collections.Generic; + +namespace Mirror +{ + public class SyncIDictionary : SyncObject, IDictionary, IReadOnlyDictionary + { + public delegate void SyncDictionaryChanged(Operation op, TKey key, TValue item); + + protected readonly IDictionary objects; + + public int Count => objects.Count; + public bool IsReadOnly => !IsWritable(); + public event SyncDictionaryChanged Callback; + + public enum Operation : byte + { + OP_ADD, + OP_CLEAR, + OP_REMOVE, + OP_SET + } + + struct Change + { + internal Operation operation; + internal TKey key; + internal TValue item; + } + + // list of changes. + // -> insert/delete/clear is only ONE change + // -> changing the same slot 10x causes 10 changes. + // -> note that this grows until next sync(!) + // TODO Dictionary to avoid ever growing changes / redundant changes! + readonly List changes = new List(); + + // how many changes we need to ignore + // this is needed because when we initialize the list, + // we might later receive changes that have already been applied + // so we need to skip them + int changesAhead; + + public override void Reset() + { + changes.Clear(); + changesAhead = 0; + objects.Clear(); + } + + public ICollection Keys => objects.Keys; + + public ICollection Values => objects.Values; + + IEnumerable IReadOnlyDictionary.Keys => objects.Keys; + + IEnumerable IReadOnlyDictionary.Values => objects.Values; + + // throw away all the changes + // this should be called after a successful sync + public override void ClearChanges() => changes.Clear(); + + public SyncIDictionary(IDictionary objects) + { + this.objects = objects; + } + + void AddOperation(Operation op, TKey key, TValue item, bool checkAccess) + { + if (checkAccess && IsReadOnly) + { + throw new System.InvalidOperationException("SyncDictionaries can only be modified by the owner."); + } + + Change change = new Change + { + operation = op, + key = key, + item = item + }; + + if (IsRecording()) + { + changes.Add(change); + OnDirty?.Invoke(); + } + + Callback?.Invoke(op, key, item); + } + + public override void OnSerializeAll(NetworkWriter writer) + { + // if init, write the full list content + writer.WriteUInt((uint)objects.Count); + + foreach (KeyValuePair syncItem in objects) + { + writer.Write(syncItem.Key); + writer.Write(syncItem.Value); + } + + // all changes have been applied already + // thus the client will need to skip all the pending changes + // or they would be applied again. + // So we write how many changes are pending + writer.WriteUInt((uint)changes.Count); + } + + public override void OnSerializeDelta(NetworkWriter writer) + { + // write all the queued up changes + writer.WriteUInt((uint)changes.Count); + + for (int i = 0; i < changes.Count; i++) + { + Change change = changes[i]; + writer.WriteByte((byte)change.operation); + + switch (change.operation) + { + case Operation.OP_ADD: + case Operation.OP_SET: + writer.Write(change.key); + writer.Write(change.item); + break; + case Operation.OP_REMOVE: + writer.Write(change.key); + break; + case Operation.OP_CLEAR: + break; + } + } + } + + public override void OnDeserializeAll(NetworkReader reader) + { + // if init, write the full list content + int count = (int)reader.ReadUInt(); + + objects.Clear(); + changes.Clear(); + + for (int i = 0; i < count; i++) + { + TKey key = reader.Read(); + TValue obj = reader.Read(); + objects.Add(key, obj); + } + + // We will need to skip all these changes + // the next time the list is synchronized + // because they have already been applied + changesAhead = (int)reader.ReadUInt(); + } + + public override void OnDeserializeDelta(NetworkReader reader) + { + int changesCount = (int)reader.ReadUInt(); + + for (int i = 0; i < changesCount; i++) + { + Operation operation = (Operation)reader.ReadByte(); + + // apply the operation only if it is a new change + // that we have not applied yet + bool apply = changesAhead == 0; + TKey key = default; + TValue item = default; + + switch (operation) + { + case Operation.OP_ADD: + case Operation.OP_SET: + key = reader.Read(); + item = reader.Read(); + if (apply) + { + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + if (ContainsKey(key)) + { + objects[key] = item; // assign after ContainsKey check + AddOperation(Operation.OP_SET, key, item, false); + } + else + { + objects[key] = item; // assign after ContainsKey check + AddOperation(Operation.OP_ADD, key, item, false); + } + } + break; + + case Operation.OP_CLEAR: + if (apply) + { + objects.Clear(); + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_CLEAR, default, default, false); + } + break; + + case Operation.OP_REMOVE: + key = reader.Read(); + if (apply) + { + if (objects.TryGetValue(key, out item)) + { + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + objects.Remove(key); + AddOperation(Operation.OP_REMOVE, key, item, false); + } + } + break; + } + + if (!apply) + { + // we just skipped this change + changesAhead--; + } + } + } + + public void Clear() + { + objects.Clear(); + AddOperation(Operation.OP_CLEAR, default, default, true); + } + + public bool ContainsKey(TKey key) => objects.ContainsKey(key); + + public bool Remove(TKey key) + { + if (objects.TryGetValue(key, out TValue item) && objects.Remove(key)) + { + AddOperation(Operation.OP_REMOVE, key, item, true); + return true; + } + return false; + } + + public TValue this[TKey i] + { + get => objects[i]; + set + { + if (ContainsKey(i)) + { + objects[i] = value; + AddOperation(Operation.OP_SET, i, value, true); + } + else + { + objects[i] = value; + AddOperation(Operation.OP_ADD, i, value, true); + } + } + } + + public bool TryGetValue(TKey key, out TValue value) => objects.TryGetValue(key, out value); + + public void Add(TKey key, TValue value) + { + objects.Add(key, value); + AddOperation(Operation.OP_ADD, key, value, true); + } + + public void Add(KeyValuePair item) => Add(item.Key, item.Value); + + public bool Contains(KeyValuePair item) + { + return TryGetValue(item.Key, out TValue val) && EqualityComparer.Default.Equals(val, item.Value); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (arrayIndex < 0 || arrayIndex > array.Length) + { + throw new System.ArgumentOutOfRangeException(nameof(arrayIndex), "Array Index Out of Range"); + } + if (array.Length - arrayIndex < Count) + { + throw new System.ArgumentException("The number of items in the SyncDictionary is greater than the available space from arrayIndex to the end of the destination array"); + } + + int i = arrayIndex; + foreach (KeyValuePair item in objects) + { + array[i] = item; + i++; + } + } + + public bool Remove(KeyValuePair item) + { + bool result = objects.Remove(item.Key); + if (result) + { + AddOperation(Operation.OP_REMOVE, item.Key, item.Value, true); + } + return result; + } + + public IEnumerator> GetEnumerator() => objects.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => objects.GetEnumerator(); + } + + public class SyncDictionary : SyncIDictionary + { + public SyncDictionary() : base(new Dictionary()) {} + public SyncDictionary(IEqualityComparer eq) : base(new Dictionary(eq)) {} + public SyncDictionary(IDictionary d) : base(new Dictionary(d)) {} + public new Dictionary.ValueCollection Values => ((Dictionary)objects).Values; + public new Dictionary.KeyCollection Keys => ((Dictionary)objects).Keys; + public new Dictionary.Enumerator GetEnumerator() => ((Dictionary)objects).GetEnumerator(); + } +} diff --git a/Assets/Mirror/Core/SyncDictionary.cs.meta b/Assets/Mirror/Core/SyncDictionary.cs.meta new file mode 100644 index 0000000..1c20b57 --- /dev/null +++ b/Assets/Mirror/Core/SyncDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b346c49cfdb668488a364c3023590e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/SyncList.cs b/Assets/Mirror/Core/SyncList.cs new file mode 100644 index 0000000..8b70eed --- /dev/null +++ b/Assets/Mirror/Core/SyncList.cs @@ -0,0 +1,420 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Mirror +{ + public class SyncList : SyncObject, IList, IReadOnlyList + { + public delegate void SyncListChanged(Operation op, int itemIndex, T oldItem, T newItem); + + readonly IList objects; + readonly IEqualityComparer comparer; + + public int Count => objects.Count; + public bool IsReadOnly => !IsWritable(); + public event SyncListChanged Callback; + + public enum Operation : byte + { + OP_ADD, + OP_CLEAR, + OP_INSERT, + OP_REMOVEAT, + OP_SET + } + + struct Change + { + internal Operation operation; + internal int index; + internal T item; + } + + // list of changes. + // -> insert/delete/clear is only ONE change + // -> changing the same slot 10x caues 10 changes. + // -> note that this grows until next sync(!) + readonly List changes = new List(); + + // how many changes we need to ignore + // this is needed because when we initialize the list, + // we might later receive changes that have already been applied + // so we need to skip them + int changesAhead; + + public SyncList() : this(EqualityComparer.Default) {} + + public SyncList(IEqualityComparer comparer) + { + this.comparer = comparer ?? EqualityComparer.Default; + objects = new List(); + } + + public SyncList(IList objects, IEqualityComparer comparer = null) + { + this.comparer = comparer ?? EqualityComparer.Default; + this.objects = objects; + } + + // throw away all the changes + // this should be called after a successful sync + public override void ClearChanges() => changes.Clear(); + + public override void Reset() + { + changes.Clear(); + changesAhead = 0; + objects.Clear(); + } + + void AddOperation(Operation op, int itemIndex, T oldItem, T newItem, bool checkAccess) + { + if (checkAccess && IsReadOnly) + { + throw new InvalidOperationException("Synclists can only be modified by the owner."); + } + + Change change = new Change + { + operation = op, + index = itemIndex, + item = newItem + }; + + if (IsRecording()) + { + changes.Add(change); + OnDirty?.Invoke(); + } + + Callback?.Invoke(op, itemIndex, oldItem, newItem); + } + + public override void OnSerializeAll(NetworkWriter writer) + { + // if init, write the full list content + writer.WriteUInt((uint)objects.Count); + + for (int i = 0; i < objects.Count; i++) + { + T obj = objects[i]; + writer.Write(obj); + } + + // all changes have been applied already + // thus the client will need to skip all the pending changes + // or they would be applied again. + // So we write how many changes are pending + writer.WriteUInt((uint)changes.Count); + } + + public override void OnSerializeDelta(NetworkWriter writer) + { + // write all the queued up changes + writer.WriteUInt((uint)changes.Count); + + for (int i = 0; i < changes.Count; i++) + { + Change change = changes[i]; + writer.WriteByte((byte)change.operation); + + switch (change.operation) + { + case Operation.OP_ADD: + writer.Write(change.item); + break; + + case Operation.OP_CLEAR: + break; + + case Operation.OP_REMOVEAT: + writer.WriteUInt((uint)change.index); + break; + + case Operation.OP_INSERT: + case Operation.OP_SET: + writer.WriteUInt((uint)change.index); + writer.Write(change.item); + break; + } + } + } + + public override void OnDeserializeAll(NetworkReader reader) + { + // if init, write the full list content + int count = (int)reader.ReadUInt(); + + objects.Clear(); + changes.Clear(); + + for (int i = 0; i < count; i++) + { + T obj = reader.Read(); + objects.Add(obj); + } + + // We will need to skip all these changes + // the next time the list is synchronized + // because they have already been applied + changesAhead = (int)reader.ReadUInt(); + } + + public override void OnDeserializeDelta(NetworkReader reader) + { + int changesCount = (int)reader.ReadUInt(); + + for (int i = 0; i < changesCount; i++) + { + Operation operation = (Operation)reader.ReadByte(); + + // apply the operation only if it is a new change + // that we have not applied yet + bool apply = changesAhead == 0; + int index = 0; + T oldItem = default; + T newItem = default; + + switch (operation) + { + case Operation.OP_ADD: + newItem = reader.Read(); + if (apply) + { + index = objects.Count; + objects.Add(newItem); + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_ADD, objects.Count - 1, default, newItem, false); + } + break; + + case Operation.OP_CLEAR: + if (apply) + { + objects.Clear(); + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_CLEAR, 0, default, default, false); + } + break; + + case Operation.OP_INSERT: + index = (int)reader.ReadUInt(); + newItem = reader.Read(); + if (apply) + { + objects.Insert(index, newItem); + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_INSERT, index, default, newItem, false); + } + break; + + case Operation.OP_REMOVEAT: + index = (int)reader.ReadUInt(); + if (apply) + { + oldItem = objects[index]; + objects.RemoveAt(index); + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_REMOVEAT, index, oldItem, default, false); + } + break; + + case Operation.OP_SET: + index = (int)reader.ReadUInt(); + newItem = reader.Read(); + if (apply) + { + oldItem = objects[index]; + objects[index] = newItem; + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_SET, index, oldItem, newItem, false); + } + break; + } + + if (!apply) + { + // we just skipped this change + changesAhead--; + } + } + } + + public void Add(T item) + { + objects.Add(item); + AddOperation(Operation.OP_ADD, objects.Count - 1, default, item, true); + } + + public void AddRange(IEnumerable range) + { + foreach (T entry in range) + { + Add(entry); + } + } + + public void Clear() + { + objects.Clear(); + AddOperation(Operation.OP_CLEAR, 0, default, default, true); + } + + public bool Contains(T item) => IndexOf(item) >= 0; + + public void CopyTo(T[] array, int index) => objects.CopyTo(array, index); + + public int IndexOf(T item) + { + for (int i = 0; i < objects.Count; ++i) + if (comparer.Equals(item, objects[i])) + return i; + return -1; + } + + public int FindIndex(Predicate match) + { + for (int i = 0; i < objects.Count; ++i) + if (match(objects[i])) + return i; + return -1; + } + + public T Find(Predicate match) + { + int i = FindIndex(match); + return (i != -1) ? objects[i] : default; + } + + public List FindAll(Predicate match) + { + List results = new List(); + for (int i = 0; i < objects.Count; ++i) + if (match(objects[i])) + results.Add(objects[i]); + return results; + } + + public void Insert(int index, T item) + { + objects.Insert(index, item); + AddOperation(Operation.OP_INSERT, index, default, item, true); + } + + public void InsertRange(int index, IEnumerable range) + { + foreach (T entry in range) + { + Insert(index, entry); + index++; + } + } + + public bool Remove(T item) + { + int index = IndexOf(item); + bool result = index >= 0; + if (result) + { + RemoveAt(index); + } + return result; + } + + public void RemoveAt(int index) + { + T oldItem = objects[index]; + objects.RemoveAt(index); + AddOperation(Operation.OP_REMOVEAT, index, oldItem, default, true); + } + + public int RemoveAll(Predicate match) + { + List toRemove = new List(); + for (int i = 0; i < objects.Count; ++i) + if (match(objects[i])) + toRemove.Add(objects[i]); + + foreach (T entry in toRemove) + { + Remove(entry); + } + + return toRemove.Count; + } + + public T this[int i] + { + get => objects[i]; + set + { + if (!comparer.Equals(objects[i], value)) + { + T oldItem = objects[i]; + objects[i] = value; + AddOperation(Operation.OP_SET, i, oldItem, value, true); + } + } + } + + public Enumerator GetEnumerator() => new Enumerator(this); + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); + + // default Enumerator allocates. we need a custom struct Enumerator to + // not allocate on the heap. + // (System.Collections.Generic.List source code does the same) + // + // benchmark: + // uMMORPG with 800 monsters, Skills.GetHealthBonus() which runs a + // foreach on skills SyncList: + // before: 81.2KB GC per frame + // after: 0KB GC per frame + // => this is extremely important for MMO scale networking + public struct Enumerator : IEnumerator + { + readonly SyncList list; + int index; + public T Current { get; private set; } + + public Enumerator(SyncList list) + { + this.list = list; + index = -1; + Current = default; + } + + public bool MoveNext() + { + if (++index >= list.Count) + { + return false; + } + Current = list[index]; + return true; + } + + public void Reset() => index = -1; + object IEnumerator.Current => Current; + public void Dispose() {} + } + } +} diff --git a/Assets/Mirror/Core/SyncList.cs.meta b/Assets/Mirror/Core/SyncList.cs.meta new file mode 100644 index 0000000..088ef1e --- /dev/null +++ b/Assets/Mirror/Core/SyncList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 744fc71f748fe40d5940e04bf42b29f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/SyncObject.cs b/Assets/Mirror/Core/SyncObject.cs new file mode 100644 index 0000000..405e240 --- /dev/null +++ b/Assets/Mirror/Core/SyncObject.cs @@ -0,0 +1,53 @@ +using System; + +namespace Mirror +{ + /// SyncObjects sync state between server and client. E.g. SyncLists. + // SyncObject should be a class (instead of an interface) for a few reasons: + // * NetworkBehaviour stores SyncObjects in a list. structs would be a copy + // and OnSerialize would use the copy instead of the original struct. + // * Obsolete functions like Flush() don't need to be defined by each type + // * OnDirty/IsRecording etc. default functions can be defined once here + // for example, handling 'OnDirty wasn't initialized' with a default + // function that throws an exception will be useful for SyncVar + public abstract class SyncObject + { + /// Used internally to set owner NetworkBehaviour's dirty mask bit when changed. + public Action OnDirty; + + /// Used internally to check if we are currently tracking changes. + // prevents ever growing .changes lists: + // if a monster has no observers but we keep modifying a SyncObject, + // then the changes would never be flushed and keep growing, + // because OnSerialize isn't called without observers. + // => Func so we can set it to () => observers.Count > 0 + // without depending on NetworkComponent/NetworkIdentity here. + // => virtual so it simply always records by default + public Func IsRecording = () => true; + + // SyncList/Set/etc. shouldn't be modifiable if not owned. + // otherwise they would silently get out of sync. + // need a lambda because InitSyncObject is called in ctor, when + // 'isClient' etc. aren't initialized yet. + public Func IsWritable = () => true; + + /// Discard all the queued changes + // Consider the object fully synchronized with clients + public abstract void ClearChanges(); + + /// Write a full copy of the object + public abstract void OnSerializeAll(NetworkWriter writer); + + /// Write the changes made to the object since last sync + public abstract void OnSerializeDelta(NetworkWriter writer); + + /// Reads a full copy of the object + public abstract void OnDeserializeAll(NetworkReader reader); + + /// Reads the changes made to the object since last sync + public abstract void OnDeserializeDelta(NetworkReader reader); + + /// Resets the SyncObject so that it can be re-used + public abstract void Reset(); + } +} diff --git a/Assets/Mirror/Core/SyncObject.cs.meta b/Assets/Mirror/Core/SyncObject.cs.meta new file mode 100644 index 0000000..736c651 --- /dev/null +++ b/Assets/Mirror/Core/SyncObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae226d17a0c844041aa24cc2c023dd49 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/SyncSet.cs b/Assets/Mirror/Core/SyncSet.cs new file mode 100644 index 0000000..13d4302 --- /dev/null +++ b/Assets/Mirror/Core/SyncSet.cs @@ -0,0 +1,352 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Mirror +{ + public class SyncSet : SyncObject, ISet + { + public delegate void SyncSetChanged(Operation op, T item); + + protected readonly ISet objects; + + public int Count => objects.Count; + public bool IsReadOnly => !IsWritable(); + public event SyncSetChanged Callback; + + public enum Operation : byte + { + OP_ADD, + OP_CLEAR, + OP_REMOVE + } + + struct Change + { + internal Operation operation; + internal T item; + } + + // list of changes. + // -> insert/delete/clear is only ONE change + // -> changing the same slot 10x caues 10 changes. + // -> note that this grows until next sync(!) + // TODO Dictionary to avoid ever growing changes / redundant changes! + readonly List changes = new List(); + + // how many changes we need to ignore + // this is needed because when we initialize the list, + // we might later receive changes that have already been applied + // so we need to skip them + int changesAhead; + + public SyncSet(ISet objects) + { + this.objects = objects; + } + + public override void Reset() + { + changes.Clear(); + changesAhead = 0; + objects.Clear(); + } + + // throw away all the changes + // this should be called after a successful sync + public override void ClearChanges() => changes.Clear(); + + void AddOperation(Operation op, T item, bool checkAccess) + { + if (checkAccess && IsReadOnly) + { + throw new InvalidOperationException("SyncSets can only be modified by the owner."); + } + + Change change = new Change + { + operation = op, + item = item + }; + + if (IsRecording()) + { + changes.Add(change); + OnDirty?.Invoke(); + } + + Callback?.Invoke(op, item); + } + + void AddOperation(Operation op, bool checkAccess) => AddOperation(op, default, checkAccess); + + public override void OnSerializeAll(NetworkWriter writer) + { + // if init, write the full list content + writer.WriteUInt((uint)objects.Count); + + foreach (T obj in objects) + { + writer.Write(obj); + } + + // all changes have been applied already + // thus the client will need to skip all the pending changes + // or they would be applied again. + // So we write how many changes are pending + writer.WriteUInt((uint)changes.Count); + } + + public override void OnSerializeDelta(NetworkWriter writer) + { + // write all the queued up changes + writer.WriteUInt((uint)changes.Count); + + for (int i = 0; i < changes.Count; i++) + { + Change change = changes[i]; + writer.WriteByte((byte)change.operation); + + switch (change.operation) + { + case Operation.OP_ADD: + writer.Write(change.item); + break; + + case Operation.OP_CLEAR: + break; + + case Operation.OP_REMOVE: + writer.Write(change.item); + break; + } + } + } + + public override void OnDeserializeAll(NetworkReader reader) + { + // if init, write the full list content + int count = (int)reader.ReadUInt(); + + objects.Clear(); + changes.Clear(); + + for (int i = 0; i < count; i++) + { + T obj = reader.Read(); + objects.Add(obj); + } + + // We will need to skip all these changes + // the next time the list is synchronized + // because they have already been applied + changesAhead = (int)reader.ReadUInt(); + } + + public override void OnDeserializeDelta(NetworkReader reader) + { + int changesCount = (int)reader.ReadUInt(); + + for (int i = 0; i < changesCount; i++) + { + Operation operation = (Operation)reader.ReadByte(); + + // apply the operation only if it is a new change + // that we have not applied yet + bool apply = changesAhead == 0; + T item = default; + + switch (operation) + { + case Operation.OP_ADD: + item = reader.Read(); + if (apply) + { + objects.Add(item); + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_ADD, item, false); + } + break; + + case Operation.OP_CLEAR: + if (apply) + { + objects.Clear(); + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_CLEAR, false); + } + break; + + case Operation.OP_REMOVE: + item = reader.Read(); + if (apply) + { + objects.Remove(item); + // add dirty + changes. + // ClientToServer needs to set dirty in server OnDeserialize. + // no access check: server OnDeserialize can always + // write, even for ClientToServer (for broadcasting). + AddOperation(Operation.OP_REMOVE, item, false); + } + break; + } + + if (!apply) + { + // we just skipped this change + changesAhead--; + } + } + } + + public bool Add(T item) + { + if (objects.Add(item)) + { + AddOperation(Operation.OP_ADD, item, true); + return true; + } + return false; + } + + void ICollection.Add(T item) + { + if (objects.Add(item)) + { + AddOperation(Operation.OP_ADD, item, true); + } + } + + public void Clear() + { + objects.Clear(); + AddOperation(Operation.OP_CLEAR, true); + } + + public bool Contains(T item) => objects.Contains(item); + + public void CopyTo(T[] array, int index) => objects.CopyTo(array, index); + + public bool Remove(T item) + { + if (objects.Remove(item)) + { + AddOperation(Operation.OP_REMOVE, item, true); + return true; + } + return false; + } + + public IEnumerator GetEnumerator() => objects.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public void ExceptWith(IEnumerable other) + { + if (other == this) + { + Clear(); + return; + } + + // remove every element in other from this + foreach (T element in other) + { + Remove(element); + } + } + + public void IntersectWith(IEnumerable other) + { + if (other is ISet otherSet) + { + IntersectWithSet(otherSet); + } + else + { + HashSet otherAsSet = new HashSet(other); + IntersectWithSet(otherAsSet); + } + } + + void IntersectWithSet(ISet otherSet) + { + List elements = new List(objects); + + foreach (T element in elements) + { + if (!otherSet.Contains(element)) + { + Remove(element); + } + } + } + + public bool IsProperSubsetOf(IEnumerable other) => objects.IsProperSubsetOf(other); + + public bool IsProperSupersetOf(IEnumerable other) => objects.IsProperSupersetOf(other); + + public bool IsSubsetOf(IEnumerable other) => objects.IsSubsetOf(other); + + public bool IsSupersetOf(IEnumerable other) => objects.IsSupersetOf(other); + + public bool Overlaps(IEnumerable other) => objects.Overlaps(other); + + public bool SetEquals(IEnumerable other) => objects.SetEquals(other); + + // custom implementation so we can do our own Clear/Add/Remove for delta + public void SymmetricExceptWith(IEnumerable other) + { + if (other == this) + { + Clear(); + } + else + { + foreach (T element in other) + { + if (!Remove(element)) + { + Add(element); + } + } + } + } + + // custom implementation so we can do our own Clear/Add/Remove for delta + public void UnionWith(IEnumerable other) + { + if (other != this) + { + foreach (T element in other) + { + Add(element); + } + } + } + } + + public class SyncHashSet : SyncSet + { + public SyncHashSet() : this(EqualityComparer.Default) {} + public SyncHashSet(IEqualityComparer comparer) : base(new HashSet(comparer ?? EqualityComparer.Default)) {} + + // allocation free enumerator + public new HashSet.Enumerator GetEnumerator() => ((HashSet)objects).GetEnumerator(); + } + + public class SyncSortedSet : SyncSet + { + public SyncSortedSet() : this(Comparer.Default) {} + public SyncSortedSet(IComparer comparer) : base(new SortedSet(comparer ?? Comparer.Default)) {} + + // allocation free enumerator + public new SortedSet.Enumerator GetEnumerator() => ((SortedSet)objects).GetEnumerator(); + } +} diff --git a/Assets/Mirror/Core/SyncSet.cs.meta b/Assets/Mirror/Core/SyncSet.cs.meta new file mode 100644 index 0000000..6eeef1c --- /dev/null +++ b/Assets/Mirror/Core/SyncSet.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8a31599d9f9dd4ef9999f7b9707c832c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Threading.meta b/Assets/Mirror/Core/Threading.meta new file mode 100644 index 0000000..037993e --- /dev/null +++ b/Assets/Mirror/Core/Threading.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 752fcafbee1ec45c9a43c0cf65da39de +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPool.cs b/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPool.cs new file mode 100644 index 0000000..c0bc926 --- /dev/null +++ b/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPool.cs @@ -0,0 +1,45 @@ +// API consistent with Microsoft's ObjectPool. +// thread safe. +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public static class ConcurrentNetworkWriterPool + { + // initial capacity to avoid allocations in the first few frames + // 1000 * 1200 bytes = around 1 MB. + public const int InitialCapacity = 1000; + + + // reuse ConcurrentPool + // we still wrap it in NetworkWriterPool.Get/Recycle so we can reset the + // position before reusing. + // this is also more consistent with NetworkReaderPool where we need to + // assign the internal buffer before reusing. + static readonly ConcurrentPool pool = + new ConcurrentPool( + // new object function + () => new ConcurrentNetworkWriterPooled(), + // initial capacity to avoid allocations in the first few frames + // 1000 * 1200 bytes = around 1 MB. + InitialCapacity + ); + + // pool size access for debugging & tests + public static int Count => pool.Count; + + public static ConcurrentNetworkWriterPooled Get() + { + // grab from pool & reset position + ConcurrentNetworkWriterPooled writer = pool.Get(); + writer.Position = 0; + return writer; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Return(ConcurrentNetworkWriterPooled writer) + { + pool.Return(writer); + } + } +} diff --git a/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPool.cs.meta b/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPool.cs.meta new file mode 100644 index 0000000..e973dad --- /dev/null +++ b/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fdf46e334f52400c854c9732f6fcf005 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPooled.cs b/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPooled.cs new file mode 100644 index 0000000..ccb1e47 --- /dev/null +++ b/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPooled.cs @@ -0,0 +1,11 @@ +using System; + +namespace Mirror +{ + /// Pooled (not threadsafe) NetworkWriter used from Concurrent pool (thread safe). Automatically returned to concurrent pool when using 'using' + // TODO make sealed again after removing obsolete NetworkWriterPooled! + public class ConcurrentNetworkWriterPooled : NetworkWriter, IDisposable + { + public void Dispose() => ConcurrentNetworkWriterPool.Return(this); + } +} diff --git a/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPooled.cs.meta b/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPooled.cs.meta new file mode 100644 index 0000000..52a333e --- /dev/null +++ b/Assets/Mirror/Core/Threading/ConcurrentNetworkWriterPooled.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9163d963b36b4e389318f312bfd8e488 +timeCreated: 1691485295 \ No newline at end of file diff --git a/Assets/Mirror/Core/Threading/ConcurrentPool.cs b/Assets/Mirror/Core/Threading/ConcurrentPool.cs new file mode 100644 index 0000000..eeac0cc --- /dev/null +++ b/Assets/Mirror/Core/Threading/ConcurrentPool.cs @@ -0,0 +1,44 @@ +// Pool to avoid allocations (from libuv2k) +// API consistent with Microsoft's ObjectPool. +// concurrent for thread safe access. +// +// currently not in use. keep it in case we need it again. +using System; +using System.Collections.Concurrent; +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public class ConcurrentPool + { + // Mirror is single threaded, no need for concurrent collections + // concurrent bag is for items who's order doesn't matter. + // just about right for our use case here. + readonly ConcurrentBag objects = new ConcurrentBag(); + + // some types might need additional parameters in their constructor, so + // we use a Func generator + readonly Func objectGenerator; + + public ConcurrentPool(Func objectGenerator, int initialCapacity) + { + this.objectGenerator = objectGenerator; + + // allocate an initial pool so we have fewer (if any) + // allocations in the first few frames (or seconds). + for (int i = 0; i < initialCapacity; ++i) + objects.Add(objectGenerator()); + } + + // take an element from the pool, or create a new one if empty + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T Get() => objects.TryTake(out T obj) ? obj : objectGenerator(); + + // return an element to the pool + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Return(T item) => objects.Add(item); + + // count to see how many objects are in the pool. useful for tests. + public int Count => objects.Count; + } +} diff --git a/Assets/Mirror/Core/Threading/ConcurrentPool.cs.meta b/Assets/Mirror/Core/Threading/ConcurrentPool.cs.meta new file mode 100644 index 0000000..40e966a --- /dev/null +++ b/Assets/Mirror/Core/Threading/ConcurrentPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed304bd790ff478ca37233f66d04d1c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Threading/ThreadLog.cs b/Assets/Mirror/Core/Threading/ThreadLog.cs new file mode 100644 index 0000000..36dca5f --- /dev/null +++ b/Assets/Mirror/Core/Threading/ThreadLog.cs @@ -0,0 +1,112 @@ +// threaded Debug.Log support (mischa 2022) +// +// Editor shows Debug.Logs from different threads. +// Builds don't show Debug.Logs from different threads. +// +// need to hook into logMessageReceivedThreaded to receive them in builds too. +using System.Collections.Concurrent; +using System.Threading; +using UnityEngine; + +namespace Mirror +{ + public static class ThreadLog + { + // queue log messages from threads + struct LogEntry + { + public int threadId; + public LogType type; + public string message; + public string stackTrace; + + public LogEntry(int threadId, LogType type, string message, string stackTrace) + { + this.threadId = threadId; + this.type = type; + this.message = message; + this.stackTrace = stackTrace; + } + } + + // ConcurrentQueue allocations are fine here. + // logs allocate anywway. + static readonly ConcurrentQueue logs = + new ConcurrentQueue(); + + // main thread id + static int mainThreadId; + +#if !UNITY_EDITOR + // Editor as of Unity 2021 does log threaded messages. + // only builds don't. + // do nothing in editor, otherwise we would log twice. + // before scene load ensures thread logs are all caught. + // otherwise some component's Awake may be called before we hooked it up. + // for example, ThreadedTransport's early logs wouldn't be caught. + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void Initialize() + { + + // set main thread id + mainThreadId = Thread.CurrentThread.ManagedThreadId; + + // receive threaded log calls + Application.logMessageReceivedThreaded -= OnLog; // remove old first. TODO unnecessary? + Application.logMessageReceivedThreaded += OnLog; + + // process logs on main thread Update + NetworkLoop.OnLateUpdate -= OnLateUpdate; // remove old first. TODO unnecessary? + NetworkLoop.OnLateUpdate += OnLateUpdate; + + // log for debugging + Debug.Log("ThreadLog initialized."); + } +#endif + + static bool IsMainThread() => + Thread.CurrentThread.ManagedThreadId == mainThreadId; + + // callback runs on the same thread where the Debug.Log is called. + // we can use this to buffer messages for main thread here. + static void OnLog(string message, string stackTrace, LogType type) + { + // only enqueue messages from other threads. + // otherwise OnLateUpdate main thread logging would be enqueued + // as well, causing deadlock. + if (IsMainThread()) return; + + // queue for logging from main thread later + logs.Enqueue(new LogEntry(Thread.CurrentThread.ManagedThreadId, type, message, stackTrace)); + } + + static void OnLateUpdate() + { + // process queued logs on main thread + while (logs.TryDequeue(out LogEntry entry)) + { + switch (entry.type) + { + // add [Thread#] prefix to make it super obvious where this log message comes from. + // some projects may see unexpected messages that were previously hidden, + // since Unity wouldn't log them without ThreadLog.cs. + case LogType.Log: + Debug.Log($"[Thread{entry.threadId}] {entry.message}\n{entry.stackTrace}"); + break; + case LogType.Warning: + Debug.LogWarning($"[Thread{entry.threadId}] {entry.message}\n{entry.stackTrace}"); + break; + case LogType.Error: + Debug.LogError($"[Thread{entry.threadId}] {entry.message}\n{entry.stackTrace}"); + break; + case LogType.Exception: + Debug.LogError($"[Thread{entry.threadId}] {entry.message}\n{entry.stackTrace}"); + break; + case LogType.Assert: + Debug.LogAssertion($"[Thread{entry.threadId}] {entry.message}\n{entry.stackTrace}"); + break; + } + } + } + } +} diff --git a/Assets/Mirror/Core/Threading/ThreadLog.cs.meta b/Assets/Mirror/Core/Threading/ThreadLog.cs.meta new file mode 100644 index 0000000..bd0d5dd --- /dev/null +++ b/Assets/Mirror/Core/Threading/ThreadLog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22360406b3844808b0a305486758a703 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Threading/WorkerThread.cs b/Assets/Mirror/Core/Threading/WorkerThread.cs new file mode 100644 index 0000000..4b037c0 --- /dev/null +++ b/Assets/Mirror/Core/Threading/WorkerThread.cs @@ -0,0 +1,165 @@ +// worker thread for Unity (mischa 2022) +// thread with proper exception handling, profling, init, cleanup, etc. for Unity. +// use this from main thread. +using System; +using System.Diagnostics; +using System.Threading; +using UnityEngine.Profiling; +using Debug = UnityEngine.Debug; + +namespace Mirror +{ + public class WorkerThread + { + readonly Thread thread; + + protected volatile bool active; + + // stopwatch so we don't need to use Unity's Time (engine independent) + readonly Stopwatch watch = new Stopwatch(); + + // callbacks need to be set after constructor. + // inheriting classes can't pass their member funcs to base ctor. + // don't set them while the thread is running! + public Action Init; + public Action Tick; + public Action Cleanup; + + public WorkerThread(string identifier) + { + // start the thread wrapped in safety guard + // if main application terminates, this thread needs to terminate too + thread = new Thread( + () => Guard(identifier) + ); + thread.IsBackground = true; + } + + public void Start() + { + // only if thread isn't already running + if (thread.IsAlive) + { + Debug.LogWarning("WorkerThread is still active, can't start it again."); + return; + } + + active = true; + thread.Start(); + } + + // signal the thread to stop gracefully. + // returns immediately, but the thread may take a while to stop. + // may be overwritten to clear more flags like 'computing' etc. + public virtual void SignalStop() => active = false; + + // wait for the thread to fully stop + public bool StopBlocking(float timeout) + { + // only if alive + if (!thread.IsAlive) return true; + + // double precision for long running servers. + watch.Restart(); + + // signal to stop + SignalStop(); + + // wait while thread is still alive + while (IsAlive) + { + // simply wait.. + Thread.Sleep(0); + + // deadlock detection + if (watch.Elapsed.TotalSeconds >= timeout) + { + // force kill all threads as last resort to stop them. + // return false to indicate deadlock. + Interrupt(); + return false; + } + } + return true; + } + + public bool IsAlive => thread.IsAlive; + + // signal an interrupt in the thread. + // this function is very safe to use. + // https://stackoverflow.com/questions/5950994/thread-abort-vs-thread-interrupt + // + // note this does not always kill the thread: + // "If this thread is not currently blocked in a wait, sleep, or join + // state, it will be interrupted when it next begins to block." + // https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.interrupt?view=net-6.0 + // + // in other words, "while (true) {}" wouldn't throw an interrupt exception. + // and that's _okay_. using interrupt is safe & best practice. + // => Unity still aborts deadlocked threads on script reload. + // => and we catch + warn on AbortException. + public void Interrupt() => thread.Interrupt(); + + // thread constructor needs callbacks. + // always define them, and make them call actions. + // those can be set at any time. + void OnInit() => Init?.Invoke(); + void OnTick() => Tick?.Invoke(); + void OnCleanup() => Cleanup?.Invoke(); + + // guarded wrapper for thread code. + // catches exceptions which would otherwise be silent. + // shows in Unity profiler. + // etc. + public void Guard(string identifier) + { + try + { + // log when work begins = thread starts. + // very important for debugging threads. + Debug.Log($"{identifier}: started."); + + // show this thread in Unity profiler + Profiler.BeginThreadProfiling("Mirror Worker Threads", $"{identifier}"); + + // run init once + OnInit(); + + // run thread func while active + while (active) + { + OnTick(); + } + } + // Thread.Interrupt() will gracefully raise a InterruptedException. + catch (ThreadInterruptedException) + { + Debug.Log($"{identifier}: interrupted. That's okay."); + } + // Unity domain reload will cause a ThreadAbortException. + // for example, when saving a changed script while in play mode. + catch (ThreadAbortException) + { + Debug.LogWarning($"{identifier}: aborted. This may happen after domain reload. That's okay."); + } + catch (Exception e) + { + Debug.LogException(e); + } + finally + { + // run cleanup (if any) + active = false; + OnCleanup(); + + // remove this thread from Unity profiler + Profiler.EndThreadProfiling(); + + // log when work ends = thread terminates. + // very important for debugging threads. + // 'finally' to log no matter what (even if exceptions) + Debug.Log($"{identifier}: ended."); + } + } + } +} diff --git a/Assets/Mirror/Core/Threading/WorkerThread.cs.meta b/Assets/Mirror/Core/Threading/WorkerThread.cs.meta new file mode 100644 index 0000000..7427cd4 --- /dev/null +++ b/Assets/Mirror/Core/Threading/WorkerThread.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 605fa1d7e32f40a08e5549bb43fc5c07 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools.meta b/Assets/Mirror/Core/Tools.meta new file mode 100644 index 0000000..8319cae --- /dev/null +++ b/Assets/Mirror/Core/Tools.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d9c73cc2749d43268600b80df0b55c4d +timeCreated: 1667486812 \ No newline at end of file diff --git a/Assets/Mirror/Core/Tools/AccurateInterval.cs b/Assets/Mirror/Core/Tools/AccurateInterval.cs new file mode 100644 index 0000000..9d2ce0e --- /dev/null +++ b/Assets/Mirror/Core/Tools/AccurateInterval.cs @@ -0,0 +1,86 @@ +// accurate interval from Mirror II. +// for sync / send intervals where it matters. +// does not(!) do catch-up. +// +// first, let's understand the problem. +// say we need an interval of 10 Hz, so every 100ms in Update we do: +// if (Time.time >= lastTime + interval) +// { +// lastTime = Time.time; +// ... +// } +// +// this seems fine, but actually Time.time will always be a few ms beyond +// the interval. but since lastTime is reset to Time.time, the remainder +// is always ignored away. +// with fixed tickRate servers (say 30 Hz), the remainder is significant! +// +// in practice if we have a 30 Hz tickRate server with a 30 Hz sendRate, +// the above way to measure the interval would result in a 18-19 Hz sendRate! +// => this is not just a little off. this is _way_ off, by almost half. +// => displaying actual + target tick/send rate will show this very easily. +// +// we need an accurate way to measure intervals for where it matters. +// and it needs to be testable to guarantee results. +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public static class AccurateInterval + { + // static func instead of storing interval + lastTime struct. + // + don't need to initialize struct ctor with interval in Awake + // + allows for interval changes at runtime too + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Elapsed(double time, double interval, ref double lastTime) + { + // enough time elapsed? + if (time < lastTime + interval) + return false; + + // naive implementation: + //lastTime = time; + + // accurate but doesn't handle heavy load situations: + //lastTime += interval; + + // heavy load edge case: + // * interval is 100ms + // * server is under heavy load, Updates slow down to 1/s + // * Elapsed(1.000) returns true. + // technically 10 intervals have elapsed. + // * server recovers to normal, Updates are every 10ms again + // * Elapsed(1.010) should return false again until 1.100. + // + // increasing lastTime by interval would require 10 more calls + // to ever catch up again: + // lastTime += interval + // + // as result, the next 10 calls to Elapsed would return true. + // Elapsed(1.001) => true + // Elapsed(1.002) => true + // Elapsed(1.003) => true + // ... + // even though technically the delta was not >= interval. + // + // this would keep the server under heavy load, and it may never + // catch-up. this is not ideal for large virtual worlds. + // + // instead, we want to skip multiples of 'interval' and only + // keep the remainder. + // + // see also: AccurateIntervalTests.Slowdown() + + // easy to understand: + //double elapsed = time - lastTime; + //double remainder = elapsed % interval; + //lastTime = time - remainder; + + // easier: set to rounded multiples of interval (fholm). + // long to match double time. + long multiplier = (long)(time / interval); + lastTime = multiplier * interval; + return true; + } + } +} diff --git a/Assets/Mirror/Core/Tools/AccurateInterval.cs.meta b/Assets/Mirror/Core/Tools/AccurateInterval.cs.meta new file mode 100644 index 0000000..a58184d --- /dev/null +++ b/Assets/Mirror/Core/Tools/AccurateInterval.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c1b18064e25046f28b88db65a4012ec1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/Compression.cs b/Assets/Mirror/Core/Tools/Compression.cs new file mode 100644 index 0000000..d04b566 --- /dev/null +++ b/Assets/Mirror/Core/Tools/Compression.cs @@ -0,0 +1,556 @@ +// Quaternion compression from DOTSNET +using System; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Mirror +{ + /// Functions to Compress Quaternions and Floats + public static class Compression + { + // divide by precision (functions backported from Mirror II) + // for example, 0.1 cm precision converts '5.0f' float to '50' long. + // + // 'long' instead of 'int' to allow for large enough worlds. + // value / precision exceeds int.max range too easily. + // Convert.ToInt32/64 would throw. + // https://github.com/vis2k/DOTSNET/issues/59 + // + // 'long' and 'int' will result in the same bandwidth though. + // for example, ScaleToLong(10.5, 0.1) = 105. + // int: 0x00000069 + // long: 0x0000000000000069 + // delta compression will reduce both to 1 byte. + // + // returns + // 'true' if scaling was possible within 'long' bounds. + // 'false' if clamping was necessary. + // never throws. checking result is optional. + public static bool ScaleToLong(float value, float precision, out long result) + { + // user might try to pass precision = 0 to disable rounding. + // this is not supported. + // throw to make the user fix this immediately. + // otherwise we would have to reinterpret-cast if ==0 etc. + // this function should be kept simple. + // if rounding isn't wanted, this function shouldn't be called. + if (precision == 0) throw new DivideByZeroException($"ScaleToLong: precision=0 would cause null division. If rounding isn't wanted, don't call this function."); + + // catch OverflowException if value/precision > long.max. + // attackers should never be able to throw exceptions. + try + { + result = Convert.ToInt64(value / precision); + return true; + } + // clamp to .max/.min. + // returning '0' would make far away entities reset to origin. + // returning 'max' would keep them stuck at the end of the world. + // the latter is much easier to debug. + catch (OverflowException) + { + result = value > 0 ? long.MaxValue : long.MinValue; + return false; + } + } + + // returns + // 'true' if scaling was possible within 'long' bounds. + // 'false' if clamping was necessary. + // never throws. checking result is optional. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ScaleToLong(Vector3 value, float precision, out long x, out long y, out long z) + { + // attempt to convert every component. + // do not return early if one conversion returned 'false'. + // the return value is optional. always attempt to convert all. + bool result = true; + result &= ScaleToLong(value.x, precision, out x); + result &= ScaleToLong(value.y, precision, out y); + result &= ScaleToLong(value.z, precision, out z); + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ScaleToLong(Vector3 value, float precision, out Vector3Long quantized) + { + quantized = Vector3Long.zero; + return ScaleToLong(value, precision, out quantized.x, out quantized.y, out quantized.z); + } + + // multiple by precision. + // for example, 0.1 cm precision converts '50' long to '5.0f' float. + public static float ScaleToFloat(long value, float precision) + { + // user might try to pass precision = 0 to disable rounding. + // this is not supported. + // throw to make the user fix this immediately. + // otherwise we would have to reinterpret-cast if ==0 etc. + // this function should be kept simple. + // if rounding isn't wanted, this function shouldn't be called. + if (precision == 0) throw new DivideByZeroException($"ScaleToLong: precision=0 would cause null division. If rounding isn't wanted, don't call this function."); + + return value * precision; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 ScaleToFloat(long x, long y, long z, float precision) + { + Vector3 v; + v.x = ScaleToFloat(x, precision); + v.y = ScaleToFloat(y, precision); + v.z = ScaleToFloat(z, precision); + return v; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 ScaleToFloat(Vector3Long value, float precision) => + ScaleToFloat(value.x, value.y, value.z, precision); + + // scale a float within min/max range to an ushort between min/max range + // note: can also use this for byte range from byte.MinValue to byte.MaxValue + public static ushort ScaleFloatToUShort(float value, float minValue, float maxValue, ushort minTarget, ushort maxTarget) + { + // note: C# ushort - ushort => int, hence so many casts + // max ushort - min ushort only fits into something bigger + int targetRange = maxTarget - minTarget; + float valueRange = maxValue - minValue; + float valueRelative = value - minValue; + return (ushort)(minTarget + (ushort)(valueRelative / valueRange * targetRange)); + } + + // scale an ushort within min/max range to a float between min/max range + // note: can also use this for byte range from byte.MinValue to byte.MaxValue + public static float ScaleUShortToFloat(ushort value, ushort minValue, ushort maxValue, float minTarget, float maxTarget) + { + // note: C# ushort - ushort => int, hence so many casts + float targetRange = maxTarget - minTarget; + ushort valueRange = (ushort)(maxValue - minValue); + ushort valueRelative = (ushort)(value - minValue); + return minTarget + (valueRelative / (float)valueRange * targetRange); + } + + // quaternion compression ////////////////////////////////////////////// + // smallest three: https://gafferongames.com/post/snapshot_compression/ + // compresses 16 bytes quaternion into 4 bytes + + // helper function to find largest absolute element + // returns the index of the largest one + public static int LargestAbsoluteComponentIndex(Vector4 value, out float largestAbs, out Vector3 withoutLargest) + { + // convert to abs + Vector4 abs = new Vector4(Mathf.Abs(value.x), Mathf.Abs(value.y), Mathf.Abs(value.z), Mathf.Abs(value.w)); + + // set largest to first abs (x) + largestAbs = abs.x; + withoutLargest = new Vector3(value.y, value.z, value.w); + int largestIndex = 0; + + // compare to the others, starting at second value + // performance for 100k calls + // for-loop: 25ms + // manual checks: 22ms + if (abs.y > largestAbs) + { + largestIndex = 1; + largestAbs = abs.y; + withoutLargest = new Vector3(value.x, value.z, value.w); + } + if (abs.z > largestAbs) + { + largestIndex = 2; + largestAbs = abs.z; + withoutLargest = new Vector3(value.x, value.y, value.w); + } + if (abs.w > largestAbs) + { + largestIndex = 3; + largestAbs = abs.w; + withoutLargest = new Vector3(value.x, value.y, value.z); + } + + return largestIndex; + } + + const float QuaternionMinRange = -0.707107f; + const float QuaternionMaxRange = 0.707107f; + const ushort TenBitsMax = 0b11_1111_1111; + + // note: assumes normalized quaternions + public static uint CompressQuaternion(Quaternion q) + { + // note: assuming normalized quaternions is enough. no need to force + // normalize here. we already normalize when decompressing. + + // find the largest component index [0,3] + value + int largestIndex = LargestAbsoluteComponentIndex(new Vector4(q.x, q.y, q.z, q.w), out float _, out Vector3 withoutLargest); + + // from here on, we work with the 3 components without largest! + + // "You might think you need to send a sign bit for [largest] in + // case it is negative, but you don’t, because you can make + // [largest] always positive by negating the entire quaternion if + // [largest] is negative. in quaternion space (x,y,z,w) and + // (-x,-y,-z,-w) represent the same rotation." + if (q[largestIndex] < 0) + withoutLargest = -withoutLargest; + + // put index & three floats into one integer. + // => index is 2 bits (4 values require 2 bits to store them) + // => the three floats are between [-0.707107,+0.707107] because: + // "If v is the absolute value of the largest quaternion + // component, the next largest possible component value occurs + // when two components have the same absolute value and the + // other two components are zero. The length of that quaternion + // (v,v,0,0) is 1, therefore v^2 + v^2 = 1, 2v^2 = 1, + // v = 1/sqrt(2). This means you can encode the smallest three + // components in [-0.707107,+0.707107] instead of [-1,+1] giving + // you more precision with the same number of bits." + // => the article recommends storing each float in 9 bits + // => our uint has 32 bits, so we might as well store in (32-2)/3=10 + // 10 bits max value: 1023=0x3FF (use OSX calc to flip 10 bits) + ushort aScaled = ScaleFloatToUShort(withoutLargest.x, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax); + ushort bScaled = ScaleFloatToUShort(withoutLargest.y, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax); + ushort cScaled = ScaleFloatToUShort(withoutLargest.z, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax); + + // now we just need to pack them into one integer + // -> index is 2 bit and needs to be shifted to 31..32 + // -> a is 10 bit and needs to be shifted 20..30 + // -> b is 10 bit and needs to be shifted 10..20 + // -> c is 10 bit and needs to be at 0..10 + return (uint)(largestIndex << 30 | aScaled << 20 | bScaled << 10 | cScaled); + } + + // Quaternion normalizeSAFE from ECS math.normalizesafe() + // => useful to produce valid quaternions even if client sends invalid + // data + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static Quaternion QuaternionNormalizeSafe(Quaternion value) + { + // The smallest positive normal number representable in a float. + const float FLT_MIN_NORMAL = 1.175494351e-38F; + + Vector4 v = new Vector4(value.x, value.y, value.z, value.w); + float length = Vector4.Dot(v, v); + return length > FLT_MIN_NORMAL + ? value.normalized + : Quaternion.identity; + } + + // note: gives normalized quaternions + public static Quaternion DecompressQuaternion(uint data) + { + // get cScaled which is at 0..10 and ignore the rest + ushort cScaled = (ushort)(data & TenBitsMax); + + // get bScaled which is at 10..20 and ignore the rest + ushort bScaled = (ushort)((data >> 10) & TenBitsMax); + + // get aScaled which is at 20..30 and ignore the rest + ushort aScaled = (ushort)((data >> 20) & TenBitsMax); + + // get 2 bit largest index, which is at 31..32 + int largestIndex = (int)(data >> 30); + + // scale back to floats + float a = ScaleUShortToFloat(aScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange); + float b = ScaleUShortToFloat(bScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange); + float c = ScaleUShortToFloat(cScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange); + + // calculate the omitted component based on a²+b²+c²+d²=1 + float d = Mathf.Sqrt(1 - a*a - b*b - c*c); + + // reconstruct based on largest index + Vector4 value; + switch (largestIndex) + { + case 0: value = new Vector4(d, a, b, c); break; + case 1: value = new Vector4(a, d, b, c); break; + case 2: value = new Vector4(a, b, d, c); break; + default: value = new Vector4(a, b, c, d); break; + } + + // ECS Rotation only works with normalized quaternions. + // make sure that's always the case here to avoid ECS bugs where + // everything stops moving if the quaternion isn't normalized. + // => NormalizeSafe returns a normalized quaternion even if we pass + // in NaN from deserializing invalid values! + return QuaternionNormalizeSafe(new Quaternion(value.x, value.y, value.z, value.w)); + } + + // varint compression ////////////////////////////////////////////////// + // helper function to predict varint size for a given number. + // useful when checking if a message + size header will fit, etc. + public static int VarUIntSize(ulong value) + { + if (value <= 240) + return 1; + if (value <= 2287) + return 2; + if (value <= 67823) + return 3; + if (value <= 16777215) + return 4; + if (value <= 4294967295) + return 5; + if (value <= 1099511627775) + return 6; + if (value <= 281474976710655) + return 7; + if (value <= 72057594037927935) + return 8; + return 9; + } + + // helper function to predict varint size for a given number. + // useful when checking if a message + size header will fit, etc. + public static int VarIntSize(long value) + { + // CompressVarInt zigzags it first + ulong zigzagged = (ulong)((value >> 63) ^ (value << 1)); + return VarUIntSize(zigzagged); + } + + // compress ulong varint. + // same result for ulong, uint, ushort and byte. only need one function. + // NOT an extension. otherwise weaver might accidentally use it. + public static void CompressVarUInt(NetworkWriter writer, ulong value) + { + // straight forward implementation: + // keep this for understanding & debugging. + /* + if (value <= 240) + { + writer.WriteByte((byte)value); + return; + } + if (value <= 2287) + { + writer.WriteByte((byte)(((value - 240) >> 8) + 241)); + writer.WriteByte((byte)((value - 240) & 0xFF)); + return; + } + if (value <= 67823) + { + writer.WriteByte((byte)249); + writer.WriteByte((byte)((value - 2288) >> 8)); + writer.WriteByte((byte)((value - 2288) & 0xFF)); + return; + } + if (value <= 16777215) + { + writer.WriteByte((byte)250); + writer.WriteByte((byte)(value & 0xFF)); + writer.WriteByte((byte)((value >> 8) & 0xFF)); + writer.WriteByte((byte)((value >> 16) & 0xFF)); + return; + } + if (value <= 4294967295) + { + writer.WriteByte((byte)251); + writer.WriteByte((byte)(value & 0xFF)); + writer.WriteByte((byte)((value >> 8) & 0xFF)); + writer.WriteByte((byte)((value >> 16) & 0xFF)); + writer.WriteByte((byte)((value >> 24) & 0xFF)); + return; + } + if (value <= 1099511627775) + { + writer.WriteByte((byte)252); + writer.WriteByte((byte)(value & 0xFF)); + writer.WriteByte((byte)((value >> 8) & 0xFF)); + writer.WriteByte((byte)((value >> 16) & 0xFF)); + writer.WriteByte((byte)((value >> 24) & 0xFF)); + writer.WriteByte((byte)((value >> 32) & 0xFF)); + return; + } + if (value <= 281474976710655) + { + writer.WriteByte((byte)253); + writer.WriteByte((byte)(value & 0xFF)); + writer.WriteByte((byte)((value >> 8) & 0xFF)); + writer.WriteByte((byte)((value >> 16) & 0xFF)); + writer.WriteByte((byte)((value >> 24) & 0xFF)); + writer.WriteByte((byte)((value >> 32) & 0xFF)); + writer.WriteByte((byte)((value >> 40) & 0xFF)); + return; + } + if (value <= 72057594037927935) + { + writer.WriteByte((byte)254); + writer.WriteByte((byte)(value & 0xFF)); + writer.WriteByte((byte)((value >> 8) & 0xFF)); + writer.WriteByte((byte)((value >> 16) & 0xFF)); + writer.WriteByte((byte)((value >> 24) & 0xFF)); + writer.WriteByte((byte)((value >> 32) & 0xFF)); + writer.WriteByte((byte)((value >> 40) & 0xFF)); + writer.WriteByte((byte)((value >> 48) & 0xFF)); + return; + } + + // all others + { + writer.WriteByte((byte)255); + writer.WriteByte((byte)(value & 0xFF)); + writer.WriteByte((byte)((value >> 8) & 0xFF)); + writer.WriteByte((byte)((value >> 16) & 0xFF)); + writer.WriteByte((byte)((value >> 24) & 0xFF)); + writer.WriteByte((byte)((value >> 32) & 0xFF)); + writer.WriteByte((byte)((value >> 40) & 0xFF)); + writer.WriteByte((byte)((value >> 48) & 0xFF)); + writer.WriteByte((byte)((value >> 56) & 0xFF)); + } + */ + + // faster implementation writes multiple bytes at once. + // avoids extra Space, WriteBlittable overhead. + // VarInt is in hot path, performance matters here. + if (value <= 240) + { + byte a = (byte)value; + writer.WriteByte(a); + return; + } + if (value <= 2287) + { + byte a = (byte)(((value - 240) >> 8) + 241); + byte b = (byte)((value - 240) & 0xFF); + writer.WriteUShort((ushort)(b << 8 | a)); + return; + } + if (value <= 67823) + { + byte a = (byte)249; + byte b = (byte)((value - 2288) >> 8); + byte c = (byte)((value - 2288) & 0xFF); + writer.WriteByte(a); + writer.WriteUShort((ushort)(c << 8 | b)); + return; + } + if (value <= 16777215) + { + byte a = (byte)250; + uint b = (uint)(value << 8); + writer.WriteUInt(b | a); + return; + } + if (value <= 4294967295) + { + byte a = (byte)251; + uint b = (uint)value; + writer.WriteByte(a); + writer.WriteUInt(b); + return; + } + if (value <= 1099511627775) + { + byte a = (byte)252; + byte b = (byte)(value & 0xFF); + uint c = (uint)(value >> 8); + writer.WriteUShort((ushort)(b << 8 | a)); + writer.WriteUInt(c); + return; + } + if (value <= 281474976710655) + { + byte a = (byte)253; + byte b = (byte)(value & 0xFF); + byte c = (byte)((value >> 8) & 0xFF); + uint d = (uint)(value >> 16); + writer.WriteByte(a); + writer.WriteUShort((ushort)(c << 8 | b)); + writer.WriteUInt(d); + return; + } + if (value <= 72057594037927935) + { + byte a = 254; + ulong b = value << 8; + writer.WriteULong(b | a); + return; + } + + // all others + { + writer.WriteByte(255); + writer.WriteULong(value); + } + } + + // zigzag encoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CompressVarInt(NetworkWriter writer, long i) + { + ulong zigzagged = (ulong)((i >> 63) ^ (i << 1)); + CompressVarUInt(writer, zigzagged); + } + + // NOT an extension. otherwise weaver might accidentally use it. + public static ulong DecompressVarUInt(NetworkReader reader) + { + byte a0 = reader.ReadByte(); + if (a0 < 241) + { + return a0; + } + + byte a1 = reader.ReadByte(); + if (a0 <= 248) + { + return 240 + ((a0 - (ulong)241) << 8) + a1; + } + + byte a2 = reader.ReadByte(); + if (a0 == 249) + { + return 2288 + ((ulong)a1 << 8) + a2; + } + + byte a3 = reader.ReadByte(); + if (a0 == 250) + { + return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16); + } + + byte a4 = reader.ReadByte(); + if (a0 == 251) + { + return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24); + } + + byte a5 = reader.ReadByte(); + if (a0 == 252) + { + return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32); + } + + byte a6 = reader.ReadByte(); + if (a0 == 253) + { + return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40); + } + + byte a7 = reader.ReadByte(); + if (a0 == 254) + { + return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48); + } + + byte a8 = reader.ReadByte(); + if (a0 == 255) + { + return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48) + (((ulong)a8) << 56); + } + + throw new IndexOutOfRangeException($"DecompressVarInt failure: {a0}"); + } + + // zigzag decoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long DecompressVarInt(NetworkReader reader) + { + ulong data = DecompressVarUInt(reader); + return ((long)(data >> 1)) ^ -((long)data & 1); + } + } +} diff --git a/Assets/Mirror/Core/Tools/Compression.cs.meta b/Assets/Mirror/Core/Tools/Compression.cs.meta new file mode 100644 index 0000000..e35474b --- /dev/null +++ b/Assets/Mirror/Core/Tools/Compression.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c28963f9c4b97e418252a55500fb91e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/DeltaCompression.cs b/Assets/Mirror/Core/Tools/DeltaCompression.cs new file mode 100644 index 0000000..a59370a --- /dev/null +++ b/Assets/Mirror/Core/Tools/DeltaCompression.cs @@ -0,0 +1,38 @@ +// manual delta compression for some types. +// varint(b-a) +// Mirror can't use Mirror II's bit-tree delta compression. +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public static class DeltaCompression + { + // delta (usually small), then zigzag varint to support +- changes + // parameter order: (last, current) makes most sense (Q3 does this too). + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Compress(NetworkWriter writer, long last, long current) => + Compression.CompressVarInt(writer, current - last); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Decompress(NetworkReader reader, long last) => + last + Compression.DecompressVarInt(reader); + + // delta (usually small), then zigzag varint to support +- changes + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Compress(NetworkWriter writer, Vector3Long last, Vector3Long current) + { + Compress(writer, last.x, current.x); + Compress(writer, last.y, current.y); + Compress(writer, last.z, current.z); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3Long Decompress(NetworkReader reader, Vector3Long last) + { + long x = Decompress(reader, last.x); + long y = Decompress(reader, last.y); + long z = Decompress(reader, last.z); + return new Vector3Long(x, y, z); + } + } +} diff --git a/Assets/Mirror/Core/Tools/DeltaCompression.cs.meta b/Assets/Mirror/Core/Tools/DeltaCompression.cs.meta new file mode 100644 index 0000000..a7b2c8b --- /dev/null +++ b/Assets/Mirror/Core/Tools/DeltaCompression.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b8f3fffcb4754c15bc5ed4c33e2497b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/ExponentialMovingAverage.cs b/Assets/Mirror/Core/Tools/ExponentialMovingAverage.cs new file mode 100644 index 0000000..674abb8 --- /dev/null +++ b/Assets/Mirror/Core/Tools/ExponentialMovingAverage.cs @@ -0,0 +1,53 @@ +// N-day EMA implementation from Mirror with a few changes (struct etc.) +// it calculates an exponential moving average roughly equivalent to the last n observations +// https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average +using System; + +namespace Mirror +{ + public struct ExponentialMovingAverage + { + readonly double alpha; + bool initialized; + + public double Value; + public double Variance; + public double StandardDeviation; // absolute value, see test + + public ExponentialMovingAverage(int n) + { + // standard N-day EMA alpha calculation + alpha = 2.0 / (n + 1); + initialized = false; + Value = 0; + Variance = 0; + StandardDeviation = 0; + } + + public void Add(double newValue) + { + // simple algorithm for EMA described here: + // https://en.wikipedia.org/wiki/Moving_average#Exponentially_weighted_moving_variance_and_standard_deviation + if (initialized) + { + double delta = newValue - Value; + Value += alpha * delta; + Variance = (1 - alpha) * (Variance + alpha * delta * delta); + StandardDeviation = Math.Sqrt(Variance); + } + else + { + Value = newValue; + initialized = true; + } + } + + public void Reset() + { + initialized = false; + Value = 0; + Variance = 0; + StandardDeviation = 0; + } + } +} diff --git a/Assets/Mirror/Core/Tools/ExponentialMovingAverage.cs.meta b/Assets/Mirror/Core/Tools/ExponentialMovingAverage.cs.meta new file mode 100644 index 0000000..d0d8210 --- /dev/null +++ b/Assets/Mirror/Core/Tools/ExponentialMovingAverage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 05e858cbaa54b4ce4a48c8c7f50c1914 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/Extensions.cs b/Assets/Mirror/Core/Tools/Extensions.cs new file mode 100644 index 0000000..196be4b --- /dev/null +++ b/Assets/Mirror/Core/Tools/Extensions.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Mirror +{ + public static class Extensions + { + public static string ToHexString(this ArraySegment segment) => + BitConverter.ToString(segment.Array, segment.Offset, segment.Count); + + // string.GetHashCode is not guaranteed to be the same on all + // machines, but we need one that is the same on all machines. + // Uses fnv1a as hash function for more uniform distribution http://www.isthe.com/chongo/tech/comp/fnv/ + // Tests: https://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed + // NOTE: Do not call this from hot path because it's slow O(N) for long method names. + // - As of 2012-02-16 There are 2 design-time callers (weaver) and 1 runtime caller that caches. + public static int GetStableHashCode(this string text) + { + unchecked + { + uint hash = 0x811c9dc5; + uint prime = 0x1000193; + + for (int i = 0; i < text.Length; ++i) + { + byte value = (byte)text[i]; + hash = hash ^ value; + hash *= prime; + } + + //UnityEngine.Debug.Log($"Created stable hash {(ushort)hash} for {text}"); + return (int)hash; + } + } + + // smaller version of our GetStableHashCode. + // careful, this significantly increases chance of collisions. + public static ushort GetStableHashCode16(this string text) + { + // deterministic hash + int hash = GetStableHashCode(text); + + // Gets the 32bit fnv1a hash + // To get it down to 16bit but still reduce hash collisions we cant just cast it to ushort + // Instead we take the highest 16bits of the 32bit hash and fold them with xor into the lower 16bits + // This will create a more uniform 16bit hash, the method is described in: + // http://www.isthe.com/chongo/tech/comp/fnv/ in section "Changing the FNV hash size - xor-folding" + return (ushort)((hash >> 16) ^ hash); + } + + // previously in DotnetCompatibility.cs + // leftover from the UNET days. supposedly for windows store? + internal static string GetMethodName(this Delegate func) + { +#if NETFX_CORE + return func.GetMethodInfo().Name; +#else + return func.Method.Name; +#endif + } + + // helper function to copy to List + // C# only provides CopyTo(T[]) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this IEnumerable source, List destination) + { + // foreach allocates. use AddRange. + destination.AddRange(source); + } + +#if !UNITY_2021_OR_NEWER + // Unity 2020 and earlier don't have Queue.TryDequeue which we need for batching. + public static bool TryDequeue(this Queue source, out T element) + { + if (source.Count > 0) + { + element = source.Dequeue(); + return true; + } + + element = default; + return false; + } +#endif + +#if !UNITY_2021_OR_NEWER + // Unity 2020 and earlier don't have ConcurrentQueue.Clear which we need for ThreadedTransport. + public static void Clear(this ConcurrentQueue source) + { + // while count > 0 risks deadlock if other thread write at the same time. + // our safest solution is a best-effort approach to clear 'Count' once. + int count = source.Count; // get it only once + for (int i = 0; i < count; ++i) + { + source.TryDequeue(out _); + } + } +#endif + +#if !UNITY_2021_3_OR_NEWER + // Unity 2021.2 and earlier don't have transform.GetPositionAndRotation which we use for performance in some places + public static void GetPositionAndRotation(this Transform transform, out Vector3 position, out Quaternion rotation) + { + position = transform.position; + rotation = transform.rotation; + } +#endif + } +} diff --git a/Assets/Mirror/Core/Tools/Extensions.cs.meta b/Assets/Mirror/Core/Tools/Extensions.cs.meta new file mode 100644 index 0000000..c2a18b7 --- /dev/null +++ b/Assets/Mirror/Core/Tools/Extensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: decf32fd053744d18f35712b7a6f5116 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/Mathd.cs b/Assets/Mirror/Core/Tools/Mathd.cs new file mode 100644 index 0000000..374471a --- /dev/null +++ b/Assets/Mirror/Core/Tools/Mathd.cs @@ -0,0 +1,32 @@ +// 'double' precision variants for some of Unity's Mathf functions. +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public static class Mathd + { + // Unity 2020 doesn't have Math.Clamp yet. + /// Clamps value between 0 and 1 and returns value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Clamp(double value, double min, double max) + { + if (value < min) return min; + if (value > max) return max; + return value; + } + + /// Clamps value between 0 and 1 and returns value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Clamp01(double value) => Clamp(value, 0, 1); + + /// Calculates the linear parameter t that produces the interpolant value within the range [a, b]. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double InverseLerp(double a, double b, double value) => + a != b ? Clamp01((value - a) / (b - a)) : 0; + + /// Linearly interpolates between a and b by t with no limit to t. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double LerpUnclamped(double a, double b, double t) => + a + (b - a) * t; + } +} diff --git a/Assets/Mirror/Core/Tools/Mathd.cs.meta b/Assets/Mirror/Core/Tools/Mathd.cs.meta new file mode 100644 index 0000000..927c55a --- /dev/null +++ b/Assets/Mirror/Core/Tools/Mathd.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5f74084b91c74df2839b426c4a381373 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/Pool.cs b/Assets/Mirror/Core/Tools/Pool.cs new file mode 100644 index 0000000..e204575 --- /dev/null +++ b/Assets/Mirror/Core/Tools/Pool.cs @@ -0,0 +1,40 @@ +// Pool to avoid allocations (from libuv2k) +// API consistent with Microsoft's ObjectPool. +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public class Pool + { + // Mirror is single threaded, no need for concurrent collections. + // stack increases the chance that a reused writer remains in cache. + readonly Stack objects = new Stack(); + + // some types might need additional parameters in their constructor, so + // we use a Func generator + readonly Func objectGenerator; + + public Pool(Func objectGenerator, int initialCapacity) + { + this.objectGenerator = objectGenerator; + + // allocate an initial pool so we have fewer (if any) + // allocations in the first few frames (or seconds). + for (int i = 0; i < initialCapacity; ++i) + objects.Push(objectGenerator()); + } + + // take an element from the pool, or create a new one if empty + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T Get() => objects.Count > 0 ? objects.Pop() : objectGenerator(); + + // return an element to the pool + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Return(T item) => objects.Push(item); + + // count to see how many objects are in the pool. useful for tests. + public int Count => objects.Count; + } +} diff --git a/Assets/Mirror/Core/Tools/Pool.cs.meta b/Assets/Mirror/Core/Tools/Pool.cs.meta new file mode 100644 index 0000000..7d12a20 --- /dev/null +++ b/Assets/Mirror/Core/Tools/Pool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 845bb05fa349344c3811022f4f15dfbc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/Readme.txt b/Assets/Mirror/Core/Tools/Readme.txt new file mode 100644 index 0000000..09bd920 --- /dev/null +++ b/Assets/Mirror/Core/Tools/Readme.txt @@ -0,0 +1 @@ +Standalone algorithms & structs to help build Mirror. \ No newline at end of file diff --git a/Assets/Mirror/Core/Tools/Readme.txt.meta b/Assets/Mirror/Core/Tools/Readme.txt.meta new file mode 100644 index 0000000..5536ca7 --- /dev/null +++ b/Assets/Mirror/Core/Tools/Readme.txt.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: da033671de7d49e0838223a997c56bf1 +timeCreated: 1667486850 \ No newline at end of file diff --git a/Assets/Mirror/Core/Tools/TimeSample.cs b/Assets/Mirror/Core/Tools/TimeSample.cs new file mode 100644 index 0000000..111e971 --- /dev/null +++ b/Assets/Mirror/Core/Tools/TimeSample.cs @@ -0,0 +1,61 @@ +// TimeSample from Mirror II. +// simple profiling sample, averaged for display in statistics. +// usable in builds without unitiy profiler overhead etc. +// +// .average may safely be called from main thread while Begin/End is in another. +// i.e. worker threads, transport, etc. +using System.Diagnostics; +using System.Threading; + +namespace Mirror +{ + public struct TimeSample + { + // UnityEngine.Time isn't thread safe. use stopwatch instead. + readonly Stopwatch watch; + + // remember when Begin was called + double beginTime; + + // keep accumulating times over the given interval. + // (not readonly. we modify its contents.) + ExponentialMovingAverage ema; + + // average in seconds. + // code often runs in sub-millisecond time. float is more precise. + // + // set with Interlocked for thread safety. + // can be read from main thread while sampling happens in other thread. + public double average; // THREAD SAFE + + // average over N begin/end captures + public TimeSample(int n) + { + watch = new Stopwatch(); + watch.Start(); + ema = new ExponentialMovingAverage(n); + beginTime = 0; + average = 0; + } + + // begin is called before the code to be sampled + public void Begin() + { + // remember when Begin was called. + // keep StopWatch running so we can average over the given interval. + beginTime = watch.Elapsed.TotalSeconds; + // Debug.Log($"Begin @ {beginTime:F4}"); + } + + // end is called after the code to be sampled + public void End() + { + // add duration in seconds to accumulated durations + double elapsed = watch.Elapsed.TotalSeconds - beginTime; + ema.Add(elapsed); + + // expose new average thread safely + Interlocked.Exchange(ref average, ema.Value); + } + } +} diff --git a/Assets/Mirror/Core/Tools/TimeSample.cs.meta b/Assets/Mirror/Core/Tools/TimeSample.cs.meta new file mode 100644 index 0000000..83e5ede --- /dev/null +++ b/Assets/Mirror/Core/Tools/TimeSample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26c32f6429554546a88d800c846c74ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/Utils.cs b/Assets/Mirror/Core/Tools/Utils.cs new file mode 100644 index 0000000..406484f --- /dev/null +++ b/Assets/Mirror/Core/Tools/Utils.cs @@ -0,0 +1,222 @@ +using System; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.SceneManagement; + +namespace Mirror +{ + // Handles network messages on client and server + public delegate void NetworkMessageDelegate(NetworkConnection conn, NetworkReader reader, int channelId); + + // Handles requests to spawn objects on the client + public delegate GameObject SpawnDelegate(Vector3 position, uint assetId); + + public delegate GameObject SpawnHandlerDelegate(SpawnMessage msg); + + // Handles requests to unspawn objects on the client + public delegate void UnSpawnDelegate(GameObject spawned); + + // channels are const ints instead of an enum so people can add their own + // channels (can't extend an enum otherwise). + // + // note that Mirror is slowly moving towards quake style networking which + // will only require reliable for handshake, and unreliable for the rest. + // so eventually we can change this to an Enum and transports shouldn't + // add custom channels anymore. + public static class Channels + { + public const int Reliable = 0; // ordered + public const int Unreliable = 1; // unordered + } + + public static class Utils + { + // detect headless / dedicated server mode + // SystemInfo.graphicsDeviceType is never null in the editor. + // UNITY_SERVER works in builds for all Unity versions 2019 LTS and later. + // For Unity 2019 / 2020, there is no way to detect Server Build checkbox + // state in Build Settings, so they never auto-start headless server / client. + // UNITY_SERVER works in the editor in Unity 2021 LTS and later + // because that's when Dedicated Server platform was added. + // It is intentional for editor play mode to auto-start headless server / client + // when Dedicated Server platform is selected in the editor so that editor + // acts like a headless build to every extent possible for testing / debugging. + public static bool IsHeadless() => +#if UNITY_SERVER + true; +#else + SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null; +#endif + + // detect WebGL mode + public const bool IsWebGL = +#if UNITY_WEBGL + true; +#else + false; +#endif + + // detect Debug mode + public const bool IsDebug = +#if DEBUG + true; +#else + false; +#endif + + public static uint GetTrueRandomUInt() + { + // use Crypto RNG to avoid having time based duplicates + using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) + { + byte[] bytes = new byte[4]; + rng.GetBytes(bytes); + return BitConverter.ToUInt32(bytes, 0); + } + } + + public static bool IsPrefab(GameObject obj) + { +#if UNITY_EDITOR + return UnityEditor.PrefabUtility.IsPartOfPrefabAsset(obj); +#else + return false; +#endif + } + + // simplified IsSceneObject check from Mirror II + public static bool IsSceneObject(NetworkIdentity identity) + { + // original UNET / Mirror still had the IsPersistent check. + // it never fires though. even for Prefabs dragged to the Scene. + // (see Scene Objects example scene.) + // #if UNITY_EDITOR + // if (UnityEditor.EditorUtility.IsPersistent(identity.gameObject)) + // return false; + // #endif + + return identity.gameObject.hideFlags != HideFlags.NotEditable && + identity.gameObject.hideFlags != HideFlags.HideAndDontSave && + identity.sceneId != 0; + } + + public static bool IsSceneObjectWithPrefabParent(GameObject gameObject, out GameObject prefab) + { + prefab = null; + +#if UNITY_EDITOR + if (!UnityEditor.PrefabUtility.IsPartOfPrefabInstance(gameObject)) + { + return false; + } + prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(gameObject); +#endif + + if (prefab == null) + { + Debug.LogError($"Failed to find prefab parent for scene object [name:{gameObject.name}]"); + return false; + } + return true; + } + + // is a 2D point in screen? (from ummorpg) + // (if width = 1024, then indices from 0..1023 are valid (=1024 indices) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsPointInScreen(Vector2 point) => + 0 <= point.x && point.x < Screen.width && + 0 <= point.y && point.y < Screen.height; + + // pretty print bytes as KB/MB/GB/etc. from DOTSNET + // long to support > 2GB + // divides by floats to return "2.5MB" etc. + public static string PrettyBytes(long bytes) + { + // bytes + if (bytes < 1024) + return $"{bytes} B"; + // kilobytes + else if (bytes < 1024L * 1024L) + return $"{(bytes / 1024f):F2} KB"; + // megabytes + else if (bytes < 1024 * 1024L * 1024L) + return $"{(bytes / (1024f * 1024f)):F2} MB"; + // gigabytes + return $"{(bytes / (1024f * 1024f * 1024f)):F2} GB"; + } + + // pretty print seconds as hours:minutes:seconds(.milliseconds/100)s. + // double for long running servers. + public static string PrettySeconds(double seconds) + { + TimeSpan t = TimeSpan.FromSeconds(seconds); + string res = ""; + if (t.Days > 0) res += $"{t.Days}d"; + if (t.Hours > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Hours}h"; + if (t.Minutes > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Minutes}m"; + // 0.5s, 1.5s etc. if any milliseconds. 1s, 2s etc. if any seconds + if (t.Milliseconds > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Seconds}.{(t.Milliseconds / 100)}s"; + else if (t.Seconds > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Seconds}s"; + // if the string is still empty because the value was '0', then at least + // return the seconds instead of returning an empty string + return res != "" ? res : "0s"; + } + + // universal .spawned function + public static NetworkIdentity GetSpawnedInServerOrClient(uint netId) + { + // server / host mode: use the one from server. + // host mode has access to all spawned. + if (NetworkServer.active) + { + NetworkServer.spawned.TryGetValue(netId, out NetworkIdentity entry); + return entry; + } + + // client + if (NetworkClient.active) + { + NetworkClient.spawned.TryGetValue(netId, out NetworkIdentity entry); + return entry; + } + + return null; + } + + // keep a GUI window in screen. + // for example. if it's at x=1000 and screen is resized to w=500, + // it won't get lost in the invisible area etc. + public static Rect KeepInScreen(Rect rect) + { + // ensure min + rect.x = Math.Max(rect.x, 0); + rect.y = Math.Max(rect.y, 0); + + // ensure max + rect.x = Math.Min(rect.x, Screen.width - rect.width); + rect.y = Math.Min(rect.y, Screen.width - rect.height); + + return rect; + } + + // create local connections pair and connect them + public static void CreateLocalConnections( + out LocalConnectionToClient connectionToClient, + out LocalConnectionToServer connectionToServer) + { + connectionToServer = new LocalConnectionToServer(); + connectionToClient = new LocalConnectionToClient(); + connectionToServer.connectionToClient = connectionToClient; + connectionToClient.connectionToServer = connectionToServer; + } + + public static bool IsSceneActive(string scene) + { + Scene activeScene = SceneManager.GetActiveScene(); + return activeScene.path == scene || + activeScene.name == scene; + } + } +} diff --git a/Assets/Mirror/Core/Tools/Utils.cs.meta b/Assets/Mirror/Core/Tools/Utils.cs.meta new file mode 100644 index 0000000..7cf1557 --- /dev/null +++ b/Assets/Mirror/Core/Tools/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b530ce39098b54374a29ad308c8e4554 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Tools/Vector3Long.cs b/Assets/Mirror/Core/Tools/Vector3Long.cs new file mode 100644 index 0000000..d54a46c --- /dev/null +++ b/Assets/Mirror/Core/Tools/Vector3Long.cs @@ -0,0 +1,125 @@ +#pragma warning disable CS0659 // 'Vector3Long' overrides Object.Equals(object o) but does not override Object.GetHashCode() +#pragma warning disable CS0661 // 'Vector3Long' defines operator == or operator != but does not override Object.GetHashCode() + +// Vector3Long by mischa (based on game engine project) +using System; +using System.Runtime.CompilerServices; + +namespace Mirror +{ + public struct Vector3Long + { + public long x; + public long y; + public long z; + + public static readonly Vector3Long zero = new Vector3Long(0, 0, 0); + public static readonly Vector3Long one = new Vector3Long(1, 1, 1); + public static readonly Vector3Long forward = new Vector3Long(0, 0, 1); + public static readonly Vector3Long back = new Vector3Long(0, 0, -1); + public static readonly Vector3Long left = new Vector3Long(-1, 0, 0); + public static readonly Vector3Long right = new Vector3Long(1, 0, 0); + public static readonly Vector3Long up = new Vector3Long(0, 1, 0); + public static readonly Vector3Long down = new Vector3Long(0, -1, 0); + + // constructor ///////////////////////////////////////////////////////// + public Vector3Long(long x, long y, long z) + { + this.x = x; + this.y = y; + this.z = z; + } + + // operators /////////////////////////////////////////////////////////// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3Long operator +(Vector3Long a, Vector3Long b) => + new Vector3Long(a.x + b.x, a.y + b.y, a.z + b.z); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3Long operator -(Vector3Long a, Vector3Long b) => + new Vector3Long(a.x - b.x, a.y - b.y, a.z - b.z); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3Long operator -(Vector3Long v) => + new Vector3Long(-v.x, -v.y, -v.z); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3Long operator *(Vector3Long a, long n) => + new Vector3Long(a.x * n, a.y * n, a.z * n); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3Long operator *(long n, Vector3Long a) => + new Vector3Long(a.x * n, a.y * n, a.z * n); + + // == returns true if approximately equal (with epsilon). + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(Vector3Long a, Vector3Long b) => + a.x == b.x && + a.y == b.y && + a.z == b.z; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(Vector3Long a, Vector3Long b) => !(a == b); + + // NO IMPLICIT System.Numerics.Vector3Long conversion because double<->float + // would silently lose precision in large worlds. + + // [i] component index. useful for iterating all components etc. + public long this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + switch (index) + { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new IndexOutOfRangeException($"Vector3Long[{index}] out of range."); + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + switch (index) + { + case 0: + x = value; + break; + case 1: + y = value; + break; + case 2: + z = value; + break; + default: throw new IndexOutOfRangeException($"Vector3Long[{index}] out of range."); + } + } + } + + // instance functions ////////////////////////////////////////////////// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override string ToString() => $"({x} {y} {z})"; + + // equality //////////////////////////////////////////////////////////// + // implement Equals & HashCode explicitly for performance. + // calling .Equals (instead of "==") checks for exact equality. + // (API compatibility) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(Vector3Long other) => + x == other.x && y == other.y && z == other.z; + + // Equals(object) can reuse Equals(Vector4) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool Equals(object other) => + other is Vector3Long vector4 && Equals(vector4); + +#if UNITY_2021_3_OR_NEWER + // Unity 2019/2020 don't have HashCode.Combine yet. + // this is only to avoid reflection. without defining, it works too. + // default generated by rider + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override int GetHashCode() => HashCode.Combine(x, y, z); +#endif + } +} diff --git a/Assets/Mirror/Core/Tools/Vector3Long.cs.meta b/Assets/Mirror/Core/Tools/Vector3Long.cs.meta new file mode 100644 index 0000000..2239765 --- /dev/null +++ b/Assets/Mirror/Core/Tools/Vector3Long.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18efa4e349254185ad257401dd24628b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/Transport.cs b/Assets/Mirror/Core/Transport.cs new file mode 100644 index 0000000..7e0716d --- /dev/null +++ b/Assets/Mirror/Core/Transport.cs @@ -0,0 +1,191 @@ +// For future reference, here is what Transports need to do in Mirror: +// +// Connecting: +// * Transports are responsible to call either OnConnected || OnDisconnected +// in a certain time after a Connect was called. It can not end in limbo. +// +// Disconnecting: +// * Connections might disconnect voluntarily by the other end. +// * Connections might be disconnect involuntarily by the server. +// * Either way, Transports need to detect it and call OnDisconnected. +// +// Timeouts: +// * Transports should expose a configurable timeout +// * Transports are responsible for calling OnDisconnected after a timeout +// +// Channels: +// * Default channel is Reliable, as in reliable ordered (OR DISCONNECT) +// * Where possible, Unreliable should be supported (unordered, no guarantee) +// +// Other: +// * Transports functions are all bound to the main thread. +// (Transports can use other threads in the background if they manage them) +// * Transports should only process messages while the component is enabled. +// +using System; +using UnityEngine; + +namespace Mirror +{ + /// Abstract transport layer component + public abstract class Transport : MonoBehaviour + { + /// The current transport used by Mirror. + public static Transport active; + + /// Is this transport available in the current platform? + public abstract bool Available(); + + // client ////////////////////////////////////////////////////////////// + /// Called by Transport when the client connected to the server. + public Action OnClientConnected; + + /// Called by Transport when the client received a message from the server. + public Action, int> OnClientDataReceived; + + /// Called by Transport when the client sent a message to the server. + // Transports are responsible for calling it because: + // - groups it together with OnReceived responsibility + // - allows transports to decide if anything was sent or not + // - allows transports to decide the actual used channel (i.e. tcp always sending reliable) + public Action, int> OnClientDataSent; + + /// Called by Transport when the client encountered an error. + public Action OnClientError; + + /// Called by Transport when the client disconnected from the server. + public Action OnClientDisconnected; + + // server ////////////////////////////////////////////////////////////// + /// Called by Transport when a new client connected to the server. + public Action OnServerConnected; + + /// Called by Transport when the server received a message from a client. + public Action, int> OnServerDataReceived; + + /// Called by Transport when the server sent a message to a client. + // Transports are responsible for calling it because: + // - groups it together with OnReceived responsibility + // - allows transports to decide if anything was sent or not + // - allows transports to decide the actual used channel (i.e. tcp always sending reliable) + public Action, int> OnServerDataSent; + + /// Called by Transport when a server's connection encountered a problem. + /// If a Disconnect will also be raised, raise the Error first. + public Action OnServerError; + + /// Called by Transport when a client disconnected from the server. + public Action OnServerDisconnected; + + // client functions //////////////////////////////////////////////////// + /// True if the client is currently connected to the server. + public abstract bool ClientConnected(); + + /// Connects the client to the server at the address. + public abstract void ClientConnect(string address); + + /// Connects the client to the server at the Uri. + public virtual void ClientConnect(Uri uri) + { + // By default, to keep backwards compatibility, just connect to the host + // in the uri + ClientConnect(uri.Host); + } + + /// Sends a message to the server over the given channel. + // The ArraySegment is only valid until returning. Copy if needed. + public abstract void ClientSend(ArraySegment segment, int channelId = Channels.Reliable); + + /// Disconnects the client from the server + public abstract void ClientDisconnect(); + + // server functions //////////////////////////////////////////////////// + /// Returns server address as Uri. + // Useful for NetworkDiscovery. + public abstract Uri ServerUri(); + + /// True if the server is currently listening for connections. + public abstract bool ServerActive(); + + /// Start listening for connections. + public abstract void ServerStart(); + + /// Send a message to a client over the given channel. + public abstract void ServerSend(int connectionId, ArraySegment segment, int channelId = Channels.Reliable); + + /// Disconnect a client from the server. + public abstract void ServerDisconnect(int connectionId); + + /// Get a client's address on the server. + // Can be useful for Game Master IP bans etc. + public abstract string ServerGetClientAddress(int connectionId); + + /// Stop listening and disconnect all connections. + public abstract void ServerStop(); + + /// Maximum message size for the given channel. + // Different channels often have different sizes, ranging from MTU to + // several megabytes. + // + // Needs to return a value at all times, even if the Transport isn't + // running or available because it's needed for initializations. + public abstract int GetMaxPacketSize(int channelId = Channels.Reliable); + + /// Recommended Batching threshold for this transport. + // Uses GetMaxPacketSize by default. + // Some transports like kcp support large max packet sizes which should + // not be used for batching all the time because they end up being too + // slow (head of line blocking etc.). + public virtual int GetBatchThreshold(int channelId = Channels.Reliable) + { + return GetMaxPacketSize(channelId); + } + + // block Update & LateUpdate to show warnings if Transports still use + // them instead of using + // Client/ServerEarlyUpdate: to process incoming messages + // Client/ServerLateUpdate: to process outgoing messages + // those are called by NetworkClient/Server at the right time. + // + // allows transports to implement the proper network update order of: + // process_incoming() + // update_world() + // process_outgoing() + // + // => see NetworkLoop.cs for detailed explanations! +#pragma warning disable UNT0001 // Empty Unity message + public void Update() {} + public void LateUpdate() {} +#pragma warning restore UNT0001 // Empty Unity message + + /// + /// NetworkLoop NetworkEarly/LateUpdate were added for a proper network + /// update order. the goal is to: + /// process_incoming() + /// update_world() + /// process_outgoing() + /// in order to avoid unnecessary latency and data races. + /// + // => split into client and server parts so that we can cleanly call + // them from NetworkClient/Server + // => VIRTUAL for now so we can take our time to convert transports + // without breaking anything. + public virtual void ClientEarlyUpdate() {} + public virtual void ServerEarlyUpdate() {} + public virtual void ClientLateUpdate() {} + public virtual void ServerLateUpdate() {} + + /// Shut down the transport, both as client and server + public abstract void Shutdown(); + + /// Called by Unity when quitting. Inheriting Transports should call base for proper Shutdown. + public virtual void OnApplicationQuit() + { + // stop transport (e.g. to shut down threads) + // (when pressing Stop in the Editor, Unity keeps threads alive + // until we press Start again. so if Transports use threads, we + // really want them to end now and not after next start) + Shutdown(); + } + } +} diff --git a/Assets/Mirror/Core/Transport.cs.meta b/Assets/Mirror/Core/Transport.cs.meta new file mode 100644 index 0000000..55072e1 --- /dev/null +++ b/Assets/Mirror/Core/Transport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cfffcac25d6d64ced9de620159e221b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/TransportError.cs b/Assets/Mirror/Core/TransportError.cs new file mode 100644 index 0000000..b452015 --- /dev/null +++ b/Assets/Mirror/Core/TransportError.cs @@ -0,0 +1,17 @@ +// Mirror transport error code enum. +// most transport implementations should use a subset of this, +// and then translate the transport error codes to mirror error codes. +namespace Mirror +{ + public enum TransportError : byte + { + DnsResolve, // failed to resolve a host name + Refused, // connection refused by other end. server full etc. + Timeout, // ping timeout or dead link + Congestion, // more messages than transport / network can process + InvalidReceive, // recv invalid packet (possibly intentional attack) + InvalidSend, // user tried to send invalid data + ConnectionClosed, // connection closed voluntarily or lost involuntarily + Unexpected // unexpected error / exception, requires fix. + } +} diff --git a/Assets/Mirror/Core/TransportError.cs.meta b/Assets/Mirror/Core/TransportError.cs.meta new file mode 100644 index 0000000..d1d0fa0 --- /dev/null +++ b/Assets/Mirror/Core/TransportError.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ce162bdedd704db9b8c35d163f0c1d54 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Core/WeaverFuse.cs b/Assets/Mirror/Core/WeaverFuse.cs new file mode 100644 index 0000000..f850323 --- /dev/null +++ b/Assets/Mirror/Core/WeaverFuse.cs @@ -0,0 +1,22 @@ +// safety fuse for weaver to flip. +// runtime can check this to ensure weaving succeded. +// otherwise running server/client would give lots of random 'writer not found' etc. errors. +// this is much cleaner. +// +// note that ILPostProcessor errors already block entering playmode. +// however, issues could still stop the weaving from running at all. +// WeaverFuse can check if it actually ran. +namespace Mirror +{ + public static class WeaverFuse + { + // this trick only works for ILPostProcessor. + // CompilationFinishedHook can't weaver Mirror.dll. + public static bool Weaved() => +#if UNITY_2020_3_OR_NEWER + false; +#else + true; +#endif + } +} diff --git a/Assets/Mirror/Core/WeaverFuse.cs.meta b/Assets/Mirror/Core/WeaverFuse.cs.meta new file mode 100644 index 0000000..c5a9e7b --- /dev/null +++ b/Assets/Mirror/Core/WeaverFuse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4de3dfbcbd2e41fcac947c04bcac52c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor.meta b/Assets/Mirror/Editor.meta new file mode 100644 index 0000000..f679511 --- /dev/null +++ b/Assets/Mirror/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2539267b6934a4026a505690a1e1eda2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/AndroidManifestHelper.cs b/Assets/Mirror/Editor/AndroidManifestHelper.cs new file mode 100644 index 0000000..c76359a --- /dev/null +++ b/Assets/Mirror/Editor/AndroidManifestHelper.cs @@ -0,0 +1,113 @@ +// Android NetworkDiscovery Multicast fix +// https://github.com/vis2k/Mirror/pull/2887 +using UnityEditor; +using UnityEngine; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +using System.Xml; +using System.IO; +#if UNITY_ANDROID +using UnityEditor.Android; +#endif + + +[InitializeOnLoad] +public class AndroidManifestHelper : IPreprocessBuildWithReport, IPostprocessBuildWithReport +#if UNITY_ANDROID + , IPostGenerateGradleAndroidProject +#endif +{ + public int callbackOrder { get { return 99999; } } + +#if UNITY_ANDROID + public void OnPostGenerateGradleAndroidProject(string path) + { + string manifestFolder = Path.Combine(path, "src/main"); + string sourceFile = manifestFolder + "/AndroidManifest.xml"; + // Load android manifest file + XmlDocument doc = new XmlDocument(); + doc.Load(sourceFile); + + string androidNamepsaceURI; + XmlElement element = (XmlElement)doc.SelectSingleNode("/manifest"); + if (element == null) + { + UnityEngine.Debug.LogError("Could not find manifest tag in android manifest."); + return; + } + + // Get android namespace URI from the manifest + androidNamepsaceURI = element.GetAttribute("xmlns:android"); + if (string.IsNullOrEmpty(androidNamepsaceURI)) + { + UnityEngine.Debug.LogError("Could not find Android Namespace in manifest."); + return; + } + AddOrRemoveTag(doc, + androidNamepsaceURI, + "/manifest", + "uses-permission", + "android.permission.CHANGE_WIFI_MULTICAST_STATE", + true, + false); + AddOrRemoveTag(doc, + androidNamepsaceURI, + "/manifest", + "uses-permission", + "android.permission.INTERNET", + true, + false); + doc.Save(sourceFile); + } +#endif + + static void AddOrRemoveTag(XmlDocument doc, string @namespace, string path, string elementName, string name, bool required, bool modifyIfFound, params string[] attrs) // name, value pairs + { + var nodes = doc.SelectNodes(path + "/" + elementName); + XmlElement element = null; + foreach (XmlElement e in nodes) + { + if (name == null || name == e.GetAttribute("name", @namespace)) + { + element = e; + break; + } + } + + if (required) + { + if (element == null) + { + var parent = doc.SelectSingleNode(path); + element = doc.CreateElement(elementName); + element.SetAttribute("name", @namespace, name); + parent.AppendChild(element); + } + + for (int i = 0; i < attrs.Length; i += 2) + { + if (modifyIfFound || string.IsNullOrEmpty(element.GetAttribute(attrs[i], @namespace))) + { + if (attrs[i + 1] != null) + { + element.SetAttribute(attrs[i], @namespace, attrs[i + 1]); + } + else + { + element.RemoveAttribute(attrs[i], @namespace); + } + } + } + } + else + { + if (element != null && modifyIfFound) + { + element.ParentNode.RemoveChild(element); + } + } + } + + public void OnPostprocessBuild(BuildReport report) {} + public void OnPreprocessBuild(BuildReport report) {} +} diff --git a/Assets/Mirror/Editor/AndroidManifestHelper.cs.meta b/Assets/Mirror/Editor/AndroidManifestHelper.cs.meta new file mode 100644 index 0000000..1281aea --- /dev/null +++ b/Assets/Mirror/Editor/AndroidManifestHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 80cc70189403d7444bbffd185ca28462 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/EditorHelper.cs b/Assets/Mirror/Editor/EditorHelper.cs new file mode 100644 index 0000000..c3551ab --- /dev/null +++ b/Assets/Mirror/Editor/EditorHelper.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace Mirror +{ + public static class EditorHelper + { + public static string FindPath() + { + string typeName = typeof(T).Name; + + string[] guidsFound = AssetDatabase.FindAssets($"t:Script {typeName}"); + if (guidsFound.Length >= 1 && !string.IsNullOrWhiteSpace(guidsFound[0])) + { + if (guidsFound.Length > 1) + { + Debug.LogWarning($"Found more than one{typeName}"); + } + + string path = AssetDatabase.GUIDToAssetPath(guidsFound[0]); + return Path.GetDirectoryName(path); + } + else + { + Debug.LogError($"Could not find path of {typeName}"); + return string.Empty; + } + } + + + public static IEnumerable IterateOverProject(string filter) + { + foreach (string guid in AssetDatabase.FindAssets(filter)) + { + yield return AssetDatabase.GUIDToAssetPath(guid); + } + } + } +} diff --git a/Assets/Mirror/Editor/EditorHelper.cs.meta b/Assets/Mirror/Editor/EditorHelper.cs.meta new file mode 100644 index 0000000..a1cd814 --- /dev/null +++ b/Assets/Mirror/Editor/EditorHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dba787f167ff29c4288532af1ec3584c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Icon.meta b/Assets/Mirror/Editor/Icon.meta new file mode 100644 index 0000000..7338187 --- /dev/null +++ b/Assets/Mirror/Editor/Icon.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b5f1356ad059a1243910a4e82cd68c5f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Icon/MirrorIcon.png b/Assets/Mirror/Editor/Icon/MirrorIcon.png new file mode 100644 index 0000000..1be8961 Binary files /dev/null and b/Assets/Mirror/Editor/Icon/MirrorIcon.png differ diff --git a/Assets/Mirror/Editor/Icon/MirrorIcon.png.meta b/Assets/Mirror/Editor/Icon/MirrorIcon.png.meta new file mode 100644 index 0000000..8049382 --- /dev/null +++ b/Assets/Mirror/Editor/Icon/MirrorIcon.png.meta @@ -0,0 +1,110 @@ +fileFormatVersion: 2 +guid: 7453abfe9e8b2c04a8a47eb536fe21eb +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: WebGL + 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/Mirror/Editor/InspectorHelper.cs b/Assets/Mirror/Editor/InspectorHelper.cs new file mode 100644 index 0000000..80b3a06 --- /dev/null +++ b/Assets/Mirror/Editor/InspectorHelper.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; + +namespace Mirror +{ + public static class InspectorHelper + { + /// Gets all public and private fields for a type + // deepestBaseType: Stops at this base type (exclusive) + public static IEnumerable GetAllFields(Type type, Type deepestBaseType) + { + const BindingFlags publicFields = BindingFlags.Public | BindingFlags.Instance; + const BindingFlags privateFields = BindingFlags.NonPublic | BindingFlags.Instance; + + // get public fields (includes fields from base type) + FieldInfo[] allPublicFields = type.GetFields(publicFields); + foreach (FieldInfo field in allPublicFields) + { + yield return field; + } + + // get private fields in current type, then move to base type + while (type != null) + { + FieldInfo[] allPrivateFields = type.GetFields(privateFields); + foreach (FieldInfo field in allPrivateFields) + { + yield return field; + } + + type = type.BaseType; + + // stop early + if (type == deepestBaseType) + { + break; + } + } + } + + public static bool IsSyncVar(this FieldInfo field) + { + object[] fieldMarkers = field.GetCustomAttributes(typeof(SyncVarAttribute), true); + return fieldMarkers.Length > 0; + } + + public static bool IsSerializeField(this FieldInfo field) + { + object[] fieldMarkers = field.GetCustomAttributes(typeof(SerializeField), true); + return fieldMarkers.Length > 0; + } + + public static bool IsVisibleField(this FieldInfo field) + { + return field.IsPublic || IsSerializeField(field); + } + + public static bool ImplementsInterface(this FieldInfo field) + { + return typeof(T).IsAssignableFrom(field.FieldType); + } + + public static bool HasShowInInspector(this FieldInfo field) + { + object[] fieldMarkers = field.GetCustomAttributes(typeof(ShowInInspectorAttribute), true); + return fieldMarkers.Length > 0; + } + + // checks if SyncObject is public or has our custom [ShowInInspector] field + public static bool IsVisibleSyncObject(this FieldInfo field) + { + return field.IsPublic || HasShowInInspector(field); + } + } +} diff --git a/Assets/Mirror/Editor/InspectorHelper.cs.meta b/Assets/Mirror/Editor/InspectorHelper.cs.meta new file mode 100644 index 0000000..852ff71 --- /dev/null +++ b/Assets/Mirror/Editor/InspectorHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 047c894c2a5ccc1438b7e59302f62744 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Mirror.Editor.asmdef b/Assets/Mirror/Editor/Mirror.Editor.asmdef new file mode 100644 index 0000000..651b8fe --- /dev/null +++ b/Assets/Mirror/Editor/Mirror.Editor.asmdef @@ -0,0 +1,19 @@ +{ + "name": "Mirror.Editor", + "rootNamespace": "", + "references": [ + "GUID:30817c1a0e6d646d99c048fc403f5979", + "GUID:1d0b9d21c3ff546a4aa32399dfd33474" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Editor/Mirror.Editor.asmdef.meta b/Assets/Mirror/Editor/Mirror.Editor.asmdef.meta new file mode 100644 index 0000000..e2e6f2a --- /dev/null +++ b/Assets/Mirror/Editor/Mirror.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1c7c33eb5480dd24c9e29a8250c1a775 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/NetworkBehaviourInspector.cs b/Assets/Mirror/Editor/NetworkBehaviourInspector.cs new file mode 100644 index 0000000..52c56d6 --- /dev/null +++ b/Assets/Mirror/Editor/NetworkBehaviourInspector.cs @@ -0,0 +1,104 @@ +using System; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace Mirror +{ + [CustomEditor(typeof(NetworkBehaviour), true)] + [CanEditMultipleObjects] + public class NetworkBehaviourInspector : Editor + { + bool syncsAnything; + SyncObjectCollectionsDrawer syncObjectCollectionsDrawer; + + // does this type sync anything? otherwise we don't need to show syncInterval + bool SyncsAnything(Type scriptClass) + { + // check for all SyncVar fields, they don't have to be visible + foreach (FieldInfo field in InspectorHelper.GetAllFields(scriptClass, typeof(NetworkBehaviour))) + { + if (field.IsSyncVar()) + { + return true; + } + } + + // has OnSerialize that is not in NetworkBehaviour? + // then it either has a syncvar or custom OnSerialize. either way + // this means we have something to sync. + MethodInfo method = scriptClass.GetMethod("OnSerialize"); + if (method != null && method.DeclaringType != typeof(NetworkBehaviour)) + { + return true; + } + + // SyncObjects are serialized in NetworkBehaviour.OnSerialize, which + // is always there even if we don't use SyncObjects. so we need to + // search for SyncObjects manually. + // Any SyncObject should be added to syncObjects when unity creates an + // object so we can check length of list so see if sync objects exists + return ((NetworkBehaviour)serializedObject.targetObject).HasSyncObjects(); + } + + void OnEnable() + { + // sometimes target is null. just return early. + if (target == null) return; + + // If target's base class is changed from NetworkBehaviour to MonoBehaviour + // then Unity temporarily keep using this Inspector causing things to break + if (!(target is NetworkBehaviour)) { return; } + + Type scriptClass = target.GetType(); + + syncObjectCollectionsDrawer = new SyncObjectCollectionsDrawer(serializedObject.targetObject); + + syncsAnything = SyncsAnything(scriptClass); + } + + public override void OnInspectorGUI() + { + DrawDefaultInspector(); + DrawSyncObjectCollections(); + DrawDefaultSyncSettings(); + } + + // Draws Sync Objects that are IEnumerable + protected void DrawSyncObjectCollections() + { + // Need this check in case OnEnable returns early + if (syncObjectCollectionsDrawer == null) return; + + syncObjectCollectionsDrawer.Draw(); + } + + // Draws SyncSettings if the NetworkBehaviour has anything to sync + protected void DrawDefaultSyncSettings() + { + // does it sync anything? then show extra properties + // (no need to show it if the class only has Cmds/Rpcs and no sync) + if (!syncsAnything) + { + return; + } + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Sync Settings", EditorStyles.boldLabel); + + // sync direction + SerializedProperty syncDirection = serializedObject.FindProperty("syncDirection"); + EditorGUILayout.PropertyField(syncDirection); + + // sync mdoe: only show for ServerToClient components + if (syncDirection.enumValueIndex == (int)SyncDirection.ServerToClient) + EditorGUILayout.PropertyField(serializedObject.FindProperty("syncMode")); + + // sync interval + EditorGUILayout.PropertyField(serializedObject.FindProperty("syncInterval")); + + // apply + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/Mirror/Editor/NetworkBehaviourInspector.cs.meta b/Assets/Mirror/Editor/NetworkBehaviourInspector.cs.meta new file mode 100644 index 0000000..78d9fa8 --- /dev/null +++ b/Assets/Mirror/Editor/NetworkBehaviourInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f02853db46b6346e4866594a96c3b0e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/NetworkInformationPreview.cs b/Assets/Mirror/Editor/NetworkInformationPreview.cs new file mode 100644 index 0000000..ec0a01e --- /dev/null +++ b/Assets/Mirror/Editor/NetworkInformationPreview.cs @@ -0,0 +1,305 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Mirror +{ + [CustomPreview(typeof(GameObject))] + class NetworkInformationPreview : ObjectPreview + { + struct NetworkIdentityInfo + { + public GUIContent name; + public GUIContent value; + } + + struct NetworkBehaviourInfo + { + // This is here just so we can check if it's enabled/disabled + public NetworkBehaviour behaviour; + public GUIContent name; + } + + class Styles + { + public GUIStyle labelStyle = new GUIStyle(EditorStyles.label); + public GUIStyle componentName = new GUIStyle(EditorStyles.boldLabel); + public GUIStyle disabledName = new GUIStyle(EditorStyles.miniLabel); + + public Styles() + { + Color fontColor = new Color(0.7f, 0.7f, 0.7f); + labelStyle.padding.right += 20; + labelStyle.normal.textColor = fontColor; + labelStyle.active.textColor = fontColor; + labelStyle.focused.textColor = fontColor; + labelStyle.hover.textColor = fontColor; + labelStyle.onNormal.textColor = fontColor; + labelStyle.onActive.textColor = fontColor; + labelStyle.onFocused.textColor = fontColor; + labelStyle.onHover.textColor = fontColor; + + componentName.normal.textColor = fontColor; + componentName.active.textColor = fontColor; + componentName.focused.textColor = fontColor; + componentName.hover.textColor = fontColor; + componentName.onNormal.textColor = fontColor; + componentName.onActive.textColor = fontColor; + componentName.onFocused.textColor = fontColor; + componentName.onHover.textColor = fontColor; + + disabledName.normal.textColor = fontColor; + disabledName.active.textColor = fontColor; + disabledName.focused.textColor = fontColor; + disabledName.hover.textColor = fontColor; + disabledName.onNormal.textColor = fontColor; + disabledName.onActive.textColor = fontColor; + disabledName.onFocused.textColor = fontColor; + disabledName.onHover.textColor = fontColor; + } + } + + GUIContent title; + Styles styles = new Styles(); + + public override GUIContent GetPreviewTitle() + { + if (title == null) + { + title = new GUIContent("Network Information"); + } + return title; + } + + public override bool HasPreviewGUI() + { + // need to check if target is null to stop MissingReferenceException + return target != null && target is GameObject gameObject && gameObject.GetComponent() != null; + } + + public override void OnPreviewGUI(Rect r, GUIStyle background) + { + if (Event.current.type != EventType.Repaint) + return; + + if (target == null) + return; + + GameObject targetGameObject = target as GameObject; + + if (targetGameObject == null) + return; + + NetworkIdentity identity = targetGameObject.GetComponent(); + + if (identity == null) + return; + + if (styles == null) + styles = new Styles(); + + + // padding + RectOffset previewPadding = new RectOffset(-5, -5, -5, -5); + Rect paddedr = previewPadding.Add(r); + + //Centering + float initialX = paddedr.x + 10; + float Y = paddedr.y + 10; + + Y = DrawNetworkIdentityInfo(identity, initialX, Y); + + Y = DrawNetworkBehaviors(identity, initialX, Y); + + Y = DrawObservers(identity, initialX, Y); + + _ = DrawOwner(identity, initialX, Y); + + } + + float DrawNetworkIdentityInfo(NetworkIdentity identity, float initialX, float Y) + { + IEnumerable infos = GetNetworkIdentityInfo(identity); + // Get required label size for the names of the information values we're going to show + // There are two columns, one with label for the name of the info and the next for the value + Vector2 maxNameLabelSize = new Vector2(140, 16); + Vector2 maxValueLabelSize = GetMaxNameLabelSize(infos); + + Rect labelRect = new Rect(initialX, Y, maxNameLabelSize.x, maxNameLabelSize.y); + Rect idLabelRect = new Rect(maxNameLabelSize.x, Y, maxValueLabelSize.x, maxValueLabelSize.y); + + foreach (NetworkIdentityInfo info in infos) + { + GUI.Label(labelRect, info.name, styles.labelStyle); + GUI.Label(idLabelRect, info.value, styles.componentName); + labelRect.y += labelRect.height; + labelRect.x = initialX; + idLabelRect.y += idLabelRect.height; + } + + return labelRect.y; + } + + float DrawNetworkBehaviors(NetworkIdentity identity, float initialX, float Y) + { + IEnumerable behavioursInfo = GetNetworkBehaviorInfo(identity); + + // Show behaviours list in a different way than the name/value pairs above + Vector2 maxBehaviourLabelSize = GetMaxBehaviourLabelSize(behavioursInfo); + Rect behaviourRect = new Rect(initialX, Y + 10, maxBehaviourLabelSize.x, maxBehaviourLabelSize.y); + + GUI.Label(behaviourRect, new GUIContent("Network Behaviours"), styles.labelStyle); + // indent names + behaviourRect.x += 20; + behaviourRect.y += behaviourRect.height; + + foreach (NetworkBehaviourInfo info in behavioursInfo) + { + if (info.behaviour == null) + { + // could be the case in the editor after existing play mode. + continue; + } + + GUI.Label(behaviourRect, info.name, info.behaviour.enabled ? styles.componentName : styles.disabledName); + behaviourRect.y += behaviourRect.height; + Y = behaviourRect.y; + } + + return Y; + } + + float DrawObservers(NetworkIdentity identity, float initialX, float Y) + { + if (identity.observers.Count > 0) + { + Rect observerRect = new Rect(initialX, Y + 10, 200, 20); + + GUI.Label(observerRect, new GUIContent("Network observers"), styles.labelStyle); + // indent names + observerRect.x += 20; + observerRect.y += observerRect.height; + + foreach (KeyValuePair kvp in identity.observers) + { + GUI.Label(observerRect, $"{kvp.Value.address}:{kvp.Value}", styles.componentName); + observerRect.y += observerRect.height; + Y = observerRect.y; + } + } + + return Y; + } + + float DrawOwner(NetworkIdentity identity, float initialX, float Y) + { + if (identity.connectionToClient != null) + { + Rect ownerRect = new Rect(initialX, Y + 10, 400, 20); + GUI.Label(ownerRect, new GUIContent($"Client Authority: {identity.connectionToClient}"), styles.labelStyle); + Y += ownerRect.height; + } + return Y; + } + + // Get the maximum size used by the value of information items + Vector2 GetMaxNameLabelSize(IEnumerable infos) + { + Vector2 maxLabelSize = Vector2.zero; + foreach (NetworkIdentityInfo info in infos) + { + Vector2 labelSize = styles.labelStyle.CalcSize(info.value); + if (maxLabelSize.x < labelSize.x) + { + maxLabelSize.x = labelSize.x; + } + if (maxLabelSize.y < labelSize.y) + { + maxLabelSize.y = labelSize.y; + } + } + return maxLabelSize; + } + + Vector2 GetMaxBehaviourLabelSize(IEnumerable behavioursInfo) + { + Vector2 maxLabelSize = Vector2.zero; + foreach (NetworkBehaviourInfo behaviour in behavioursInfo) + { + Vector2 labelSize = styles.labelStyle.CalcSize(behaviour.name); + if (maxLabelSize.x < labelSize.x) + { + maxLabelSize.x = labelSize.x; + } + if (maxLabelSize.y < labelSize.y) + { + maxLabelSize.y = labelSize.y; + } + } + return maxLabelSize; + } + + IEnumerable GetNetworkIdentityInfo(NetworkIdentity identity) + { + List infos = new List + { + GetAssetId(identity), + GetString("Scene ID", identity.sceneId.ToString("X")) + }; + + if (Application.isPlaying) + { + infos.Add(GetString("Network ID", identity.netId.ToString())); + infos.Add(GetBoolean("Is Client", identity.isClient)); + infos.Add(GetBoolean("Is Server", identity.isServer)); + infos.Add(GetBoolean("Is Owned", identity.isOwned)); + infos.Add(GetBoolean("Is Local Player", identity.isLocalPlayer)); + } + return infos; + } + + IEnumerable GetNetworkBehaviorInfo(NetworkIdentity identity) + { + List behaviourInfos = new List(); + + NetworkBehaviour[] behaviours = identity.GetComponents(); + foreach (NetworkBehaviour behaviour in behaviours) + { + behaviourInfos.Add(new NetworkBehaviourInfo + { + name = new GUIContent(behaviour.GetType().FullName), + behaviour = behaviour + }); + } + return behaviourInfos; + } + + NetworkIdentityInfo GetAssetId(NetworkIdentity identity) + { + string assetId = identity.assetId.ToString(); + if (string.IsNullOrWhiteSpace(assetId)) + { + assetId = ""; + } + return GetString("Asset ID", assetId); + } + + static NetworkIdentityInfo GetString(string name, string value) + { + return new NetworkIdentityInfo + { + name = new GUIContent(name), + value = new GUIContent(value) + }; + } + + static NetworkIdentityInfo GetBoolean(string name, bool value) + { + return new NetworkIdentityInfo + { + name = new GUIContent(name), + value = new GUIContent((value ? "Yes" : "No")) + }; + } + } +} diff --git a/Assets/Mirror/Editor/NetworkInformationPreview.cs.meta b/Assets/Mirror/Editor/NetworkInformationPreview.cs.meta new file mode 100644 index 0000000..9bf2de4 --- /dev/null +++ b/Assets/Mirror/Editor/NetworkInformationPreview.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 51a99294efe134232932c34606737356 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/NetworkManagerEditor.cs b/Assets/Mirror/Editor/NetworkManagerEditor.cs new file mode 100644 index 0000000..82b2b1b --- /dev/null +++ b/Assets/Mirror/Editor/NetworkManagerEditor.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; + +namespace Mirror +{ + [CustomEditor(typeof(NetworkManager), true)] + [CanEditMultipleObjects] + public class NetworkManagerEditor : Editor + { + SerializedProperty spawnListProperty; + ReorderableList spawnList; + protected NetworkManager networkManager; + + protected void Init() + { + if (spawnList == null) + { + networkManager = target as NetworkManager; + spawnListProperty = serializedObject.FindProperty("spawnPrefabs"); + spawnList = new ReorderableList(serializedObject, spawnListProperty) + { + drawHeaderCallback = DrawHeader, + drawElementCallback = DrawChild, + onReorderCallback = Changed, + onRemoveCallback = RemoveButton, + onChangedCallback = Changed, + onAddCallback = AddButton, + // this uses a 16x16 icon. other sizes make it stretch. + elementHeight = 16 + }; + } + } + + public override void OnInspectorGUI() + { + Init(); + DrawDefaultInspector(); + EditorGUI.BeginChangeCheck(); + spawnList.DoLayoutList(); + if (EditorGUI.EndChangeCheck()) + { + serializedObject.ApplyModifiedProperties(); + } + + if (GUILayout.Button("Populate Spawnable Prefabs")) + { + ScanForNetworkIdentities(); + } + } + + void ScanForNetworkIdentities() + { + List identities = new List(); + bool cancelled = false; + try + { + string[] paths = EditorHelper.IterateOverProject("t:prefab").ToArray(); + int count = 0; + foreach (string path in paths) + { + // ignore test & example prefabs. + // users sometimes keep the folders in their projects. + if (path.Contains("Mirror/Tests/") || + path.Contains("Mirror/Examples/")) + { + continue; + } + + if (EditorUtility.DisplayCancelableProgressBar("Searching for NetworkIdentities..", + $"Scanned {count}/{paths.Length} prefabs. Found {identities.Count} new ones", + count / (float)paths.Length)) + { + cancelled = true; + break; + } + + count++; + + NetworkIdentity ni = AssetDatabase.LoadAssetAtPath(path); + if (!ni) + { + continue; + } + + if (!networkManager.spawnPrefabs.Contains(ni.gameObject)) + { + identities.Add(ni.gameObject); + } + + } + } + finally + { + + EditorUtility.ClearProgressBar(); + if (!cancelled) + { + // RecordObject is needed for "*" to show up in Scene. + // however, this only saves List.Count without the entries. + Undo.RecordObject(networkManager, "NetworkManager: populated prefabs"); + + // add the entries + networkManager.spawnPrefabs.AddRange(identities); + + // sort alphabetically for better UX + networkManager.spawnPrefabs = networkManager.spawnPrefabs.OrderBy(go => go.name).ToList(); + + // SetDirty is required to save the individual entries properly. + EditorUtility.SetDirty(target); + } + // Loading assets might use a lot of memory, so try to unload them after + Resources.UnloadUnusedAssets(); + } + } + + static void DrawHeader(Rect headerRect) + { + GUI.Label(headerRect, "Registered Spawnable Prefabs:"); + } + + internal void DrawChild(Rect r, int index, bool isActive, bool isFocused) + { + SerializedProperty prefab = spawnListProperty.GetArrayElementAtIndex(index); + GameObject go = (GameObject)prefab.objectReferenceValue; + + GUIContent label; + if (go == null) + { + label = new GUIContent("Empty", "Drag a prefab with a NetworkIdentity here"); + } + else + { + NetworkIdentity identity = go.GetComponent(); + label = new GUIContent(go.name, identity != null ? $"AssetId: [{identity.assetId}]" : "No Network Identity"); + } + + GameObject newGameObject = (GameObject)EditorGUI.ObjectField(r, label, go, typeof(GameObject), false); + + if (newGameObject != go) + { + if (newGameObject != null && !newGameObject.GetComponent()) + { + Debug.LogError($"Prefab {newGameObject} cannot be added as spawnable as it doesn't have a NetworkIdentity."); + return; + } + prefab.objectReferenceValue = newGameObject; + } + } + + internal void Changed(ReorderableList list) + { + EditorUtility.SetDirty(target); + } + + internal void AddButton(ReorderableList list) + { + spawnListProperty.arraySize += 1; + list.index = spawnListProperty.arraySize - 1; + + SerializedProperty obj = spawnListProperty.GetArrayElementAtIndex(spawnListProperty.arraySize - 1); + obj.objectReferenceValue = null; + + spawnList.index = spawnList.count - 1; + + Changed(list); + } + + internal void RemoveButton(ReorderableList list) + { + spawnListProperty.DeleteArrayElementAtIndex(spawnList.index); + if (list.index >= spawnListProperty.arraySize) + { + list.index = spawnListProperty.arraySize - 1; + } + } + } +} diff --git a/Assets/Mirror/Editor/NetworkManagerEditor.cs.meta b/Assets/Mirror/Editor/NetworkManagerEditor.cs.meta new file mode 100644 index 0000000..7fe8dbc --- /dev/null +++ b/Assets/Mirror/Editor/NetworkManagerEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 519712eb07f7a44039df57664811c2c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/NetworkScenePostProcess.cs b/Assets/Mirror/Editor/NetworkScenePostProcess.cs new file mode 100644 index 0000000..2fa07d6 --- /dev/null +++ b/Assets/Mirror/Editor/NetworkScenePostProcess.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEngine; + +namespace Mirror +{ + public class NetworkScenePostProcess : MonoBehaviour + { + [PostProcessScene] + public static void OnPostProcessScene() + { + // find all NetworkIdentities in all scenes + // => can't limit it to GetActiveScene() because that wouldn't work + // for additive scene loads (the additively loaded scene is never + // the active scene) + // => ignore DontDestroyOnLoad scene! this avoids weird situations + // like in NetworkZones when we destroy the local player and + // load another scene afterwards, yet the local player is still + // in the FindObjectsOfType result with scene=DontDestroyOnLoad + // for some reason + // => OfTypeAll so disabled objects are included too + // => Unity 2019 returns prefabs here too, so filter them out. + IEnumerable identities = Resources.FindObjectsOfTypeAll() + .Where(identity => identity.gameObject.hideFlags != HideFlags.NotEditable && + identity.gameObject.hideFlags != HideFlags.HideAndDontSave && + identity.gameObject.scene.name != "DontDestroyOnLoad" && + !Utils.IsPrefab(identity.gameObject)); + + foreach (NetworkIdentity identity in identities) + { + // if we had a [ConflictComponent] attribute that would be better than this check. + // also there is no context about which scene this is in. + if (identity.GetComponent() != null) + Debug.LogError("NetworkManager has a NetworkIdentity component. This will cause the NetworkManager object to be disabled, so it is not recommended."); + + // not spawned before? + // OnPostProcessScene is called after additive scene loads too, + // and we don't want to set main scene's objects inactive again + if (!identity.isClient && !identity.isServer) + { + // valid scene object? + // otherwise it might be an unopened scene that still has null + // sceneIds. builds are interrupted if they contain 0 sceneIds, + // but it's still possible that we call LoadScene in Editor + // for a previously unopened scene. + // (and only do SetActive if this was actually a scene object) + if (identity.sceneId != 0) + { + PrepareSceneObject(identity); + } + // throwing an exception would only show it for one object + // because this function would return afterwards. + else + { + // there are two cases where sceneId == 0: + // * if we have a prefab open in the prefab scene + // * if an unopened scene needs resaving + // show a proper error message in both cases so the user + // knows what to do. + string path = identity.gameObject.scene.path; + if (string.IsNullOrWhiteSpace(path)) + Debug.LogError($"{identity.name} is currently open in Prefab Edit Mode. Please open the actual scene before launching Mirror."); + else + Debug.LogError($"Scene {path} needs to be opened and resaved, because the scene object {identity.name} has no valid sceneId yet."); + + // either way we shouldn't continue. nothing good will + // happen when trying to launch with invalid sceneIds. + EditorApplication.isPlaying = false; + } + } + } + } + + static void PrepareSceneObject(NetworkIdentity identity) + { + // set scene hash + identity.SetSceneIdSceneHashPartInternal(); + + // spawnable scene objects are force disabled on scene load to + // ensure Start/Update/etc. aren't called until actually spawned. + // + // note: NetworkIdentity.OnDisable adds itself to the + // spawnableObjects dictionary (only if sceneId != 0) + identity.gameObject.SetActive(false); + + // safety check for prefabs with more than one NetworkIdentity + GameObject prefabGO = PrefabUtility.GetCorrespondingObjectFromSource(identity.gameObject); + if (prefabGO) + { + GameObject prefabRootGO = prefabGO.transform.root.gameObject; + if (prefabRootGO != null && prefabRootGO.GetComponentsInChildren().Length > 1) + Debug.LogWarning($"Prefab {prefabRootGO.name} has several NetworkIdentity components attached to itself or its children, this is not supported."); + } + } + } +} diff --git a/Assets/Mirror/Editor/NetworkScenePostProcess.cs.meta b/Assets/Mirror/Editor/NetworkScenePostProcess.cs.meta new file mode 100644 index 0000000..b567cc9 --- /dev/null +++ b/Assets/Mirror/Editor/NetworkScenePostProcess.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3ec1c414d821444a9e77f18a2c130ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/ReadOnlyDrawer.cs b/Assets/Mirror/Editor/ReadOnlyDrawer.cs new file mode 100644 index 0000000..4a09707 --- /dev/null +++ b/Assets/Mirror/Editor/ReadOnlyDrawer.cs @@ -0,0 +1,19 @@ +using UnityEngine; +using UnityEditor; + +namespace Mirror +{ + [CustomPropertyDrawer(typeof(ReadOnlyAttribute))] + public class ReadOnlyDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // Cache the current GUI enabled state + bool prevGuiEnabledState = GUI.enabled; + + GUI.enabled = false; + EditorGUI.PropertyField(position, property, label, true); + GUI.enabled = prevGuiEnabledState; + } + } +} diff --git a/Assets/Mirror/Editor/ReadOnlyDrawer.cs.meta b/Assets/Mirror/Editor/ReadOnlyDrawer.cs.meta new file mode 100644 index 0000000..eb6eb0f --- /dev/null +++ b/Assets/Mirror/Editor/ReadOnlyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22f17bdd21f104c41bc175937fefbdec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/SceneDrawer.cs b/Assets/Mirror/Editor/SceneDrawer.cs new file mode 100644 index 0000000..f391684 --- /dev/null +++ b/Assets/Mirror/Editor/SceneDrawer.cs @@ -0,0 +1,47 @@ +using UnityEditor; +using UnityEngine; + +namespace Mirror +{ + [CustomPropertyDrawer(typeof(SceneAttribute))] + public class SceneDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + if (property.propertyType == SerializedPropertyType.String) + { + SceneAsset sceneObject = AssetDatabase.LoadAssetAtPath(property.stringValue); + + if (sceneObject == null && !string.IsNullOrWhiteSpace(property.stringValue)) + { + // try to load it from the build settings for legacy compatibility + sceneObject = GetBuildSettingsSceneObject(property.stringValue); + } + if (sceneObject == null && !string.IsNullOrWhiteSpace(property.stringValue)) + { + Debug.LogError($"Could not find scene {property.stringValue} in {property.propertyPath}, assign the proper scenes in your NetworkManager"); + } + SceneAsset scene = (SceneAsset)EditorGUI.ObjectField(position, label, sceneObject, typeof(SceneAsset), true); + + property.stringValue = AssetDatabase.GetAssetPath(scene); + } + else + { + EditorGUI.LabelField(position, label.text, "Use [Scene] with strings."); + } + } + + protected SceneAsset GetBuildSettingsSceneObject(string sceneName) + { + foreach (EditorBuildSettingsScene buildScene in EditorBuildSettings.scenes) + { + SceneAsset sceneAsset = AssetDatabase.LoadAssetAtPath(buildScene.path); + if (sceneAsset!= null && sceneAsset.name == sceneName) + { + return sceneAsset; + } + } + return null; + } + } +} diff --git a/Assets/Mirror/Editor/SceneDrawer.cs.meta b/Assets/Mirror/Editor/SceneDrawer.cs.meta new file mode 100644 index 0000000..6a996dc --- /dev/null +++ b/Assets/Mirror/Editor/SceneDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b24704a46211b4ea294aba8f58715cea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/SyncObjectCollectionsDrawer.cs b/Assets/Mirror/Editor/SyncObjectCollectionsDrawer.cs new file mode 100644 index 0000000..2c95bcf --- /dev/null +++ b/Assets/Mirror/Editor/SyncObjectCollectionsDrawer.cs @@ -0,0 +1,83 @@ +// helper class for NetworkBehaviourInspector to draw all enumerable SyncObjects +// (SyncList/Set/Dictionary) +// 'SyncObjectCollectionsDrawer' is a nicer name than 'IEnumerableSyncObjectsDrawer' +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEditor; + +namespace Mirror +{ + class SyncObjectCollectionField + { + public bool visible; + public readonly FieldInfo field; + public readonly string label; + + public SyncObjectCollectionField(FieldInfo field) + { + this.field = field; + visible = false; + label = $"{field.Name} [{field.FieldType.Name}]"; + } + } + + public class SyncObjectCollectionsDrawer + { + readonly UnityEngine.Object targetObject; + readonly List syncObjectCollectionFields; + + public SyncObjectCollectionsDrawer(UnityEngine.Object targetObject) + { + this.targetObject = targetObject; + syncObjectCollectionFields = new List(); + foreach (FieldInfo field in InspectorHelper.GetAllFields(targetObject.GetType(), typeof(NetworkBehaviour))) + { + // only draw SyncObjects that are IEnumerable (SyncList/Set/Dictionary) + if (field.IsVisibleSyncObject() && + field.ImplementsInterface() && + field.ImplementsInterface()) + { + syncObjectCollectionFields.Add(new SyncObjectCollectionField(field)); + } + } + } + + public void Draw() + { + if (syncObjectCollectionFields.Count == 0) { return; } + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Sync Collections", EditorStyles.boldLabel); + + for (int i = 0; i < syncObjectCollectionFields.Count; i++) + { + DrawSyncObjectCollection(syncObjectCollectionFields[i]); + } + } + + void DrawSyncObjectCollection(SyncObjectCollectionField syncObjectCollectionField) + { + syncObjectCollectionField.visible = EditorGUILayout.Foldout(syncObjectCollectionField.visible, syncObjectCollectionField.label); + if (syncObjectCollectionField.visible) + { + using (new EditorGUI.IndentLevelScope()) + { + object fieldValue = syncObjectCollectionField.field.GetValue(targetObject); + if (fieldValue is IEnumerable syncObject) + { + int index = 0; + foreach (object item in syncObject) + { + string itemValue = item != null ? item.ToString() : "NULL"; + string itemLabel = $"Element {index}"; + EditorGUILayout.LabelField(itemLabel, itemValue); + + index++; + } + } + } + } + } + } +} diff --git a/Assets/Mirror/Editor/SyncObjectCollectionsDrawer.cs.meta b/Assets/Mirror/Editor/SyncObjectCollectionsDrawer.cs.meta new file mode 100644 index 0000000..44ba75d --- /dev/null +++ b/Assets/Mirror/Editor/SyncObjectCollectionsDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6f90afab12e04f0e945d83e9d38308a3 +timeCreated: 1632556645 \ No newline at end of file diff --git a/Assets/Mirror/Editor/SyncVarAttributeDrawer.cs b/Assets/Mirror/Editor/SyncVarAttributeDrawer.cs new file mode 100644 index 0000000..2356a5e --- /dev/null +++ b/Assets/Mirror/Editor/SyncVarAttributeDrawer.cs @@ -0,0 +1,28 @@ +using UnityEditor; +using UnityEngine; + +namespace Mirror +{ + [CustomPropertyDrawer(typeof(SyncVarAttribute))] + public class SyncVarAttributeDrawer : PropertyDrawer + { + static readonly GUIContent syncVarIndicatorContent = new GUIContent("SyncVar", "This variable has been marked with the [SyncVar] attribute."); + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + Vector2 syncVarIndicatorRect = EditorStyles.miniLabel.CalcSize(syncVarIndicatorContent); + float valueWidth = position.width - syncVarIndicatorRect.x; + + Rect valueRect = new Rect(position.x, position.y, valueWidth, position.height); + Rect labelRect = new Rect(position.x + valueWidth, position.y, syncVarIndicatorRect.x, position.height); + + EditorGUI.PropertyField(valueRect, property, label, true); + GUI.Label(labelRect, syncVarIndicatorContent, EditorStyles.miniLabel); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + return EditorGUI.GetPropertyHeight(property); + } + } +} diff --git a/Assets/Mirror/Editor/SyncVarAttributeDrawer.cs.meta b/Assets/Mirror/Editor/SyncVarAttributeDrawer.cs.meta new file mode 100644 index 0000000..6311f1d --- /dev/null +++ b/Assets/Mirror/Editor/SyncVarAttributeDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 27821afc81c4d064d8348fbeb00c0ce8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver.meta b/Assets/Mirror/Editor/Weaver.meta new file mode 100644 index 0000000..121fbf4 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d9f8e6274119b4ce29e498cfb8aca8a4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/AssemblyInfo.cs b/Assets/Mirror/Editor/Weaver/AssemblyInfo.cs new file mode 100644 index 0000000..08b43f5 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Mirror.Tests")] diff --git a/Assets/Mirror/Editor/Weaver/AssemblyInfo.cs.meta b/Assets/Mirror/Editor/Weaver/AssemblyInfo.cs.meta new file mode 100644 index 0000000..d356af8 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 929924d95663264478d4238d4910d22e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/EntryPoint.meta b/Assets/Mirror/Editor/Weaver/EntryPoint.meta new file mode 100644 index 0000000..81827c5 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPoint.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 251338e67afb4cefa38da924f8c50a6e +timeCreated: 1628851818 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs new file mode 100644 index 0000000..b5db851 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs @@ -0,0 +1,188 @@ +// for Unity 2020+ we use ILPostProcessor. +// only automatically invoke it for older versions. +#if !UNITY_2020_3_OR_NEWER +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Mono.CecilX; +using UnityEditor; +using UnityEditor.Compilation; +using UnityEngine; +using UnityAssembly = UnityEditor.Compilation.Assembly; + +namespace Mirror.Weaver +{ + public static class CompilationFinishedHook + { + // needs to be the same as Weaver.MirrorAssemblyName! + const string MirrorRuntimeAssemblyName = "Mirror"; + const string MirrorWeaverAssemblyName = "Mirror.Weaver"; + + // global weaver define so that tests can use it + internal static Weaver weaver; + + // delegate for subscription to Weaver warning messages + public static Action OnWeaverWarning; + // delete for subscription to Weaver error messages + public static Action OnWeaverError; + + // controls whether Weaver errors are reported direct to the Unity console (tests enable this) + public static bool UnityLogEnabled = true; + + [InitializeOnLoadMethod] + public static void OnInitializeOnLoad() + { + CompilationPipeline.assemblyCompilationFinished += OnCompilationFinished; + + // We only need to run this once per session + // after that, all assemblies will be weaved by the event + if (!SessionState.GetBool("MIRROR_WEAVED", false)) + { + // reset session flag + SessionState.SetBool("MIRROR_WEAVED", true); + SessionState.SetBool("MIRROR_WEAVE_SUCCESS", true); + + WeaveExistingAssemblies(); + } + } + + public static void WeaveExistingAssemblies() + { + foreach (UnityAssembly assembly in CompilationPipeline.GetAssemblies()) + { + if (File.Exists(assembly.outputPath)) + { + OnCompilationFinished(assembly.outputPath, new CompilerMessage[0]); + } + } + + EditorUtility.RequestScriptReload(); + } + + static Assembly FindCompilationPipelineAssembly(string assemblyName) => + CompilationPipeline.GetAssemblies().First(assembly => assembly.name == assemblyName); + + static bool CompilerMessagesContainError(CompilerMessage[] messages) => + messages.Any(msg => msg.type == CompilerMessageType.Error); + + public static void OnCompilationFinished(string assemblyPath, CompilerMessage[] messages) + { + // Do nothing if there were compile errors on the target + if (CompilerMessagesContainError(messages)) + { + Debug.Log("Weaver: stop because compile errors on target"); + return; + } + + // Should not run on the editor only assemblies (test ones still need to be weaved) + if (assemblyPath.Contains("-Editor") || + (assemblyPath.Contains(".Editor") && !assemblyPath.Contains(".Tests"))) + { + return; + } + + // skip Mirror.dll because CompilationFinishedHook can't weave itself. + // this would cause a sharing violation. + // skip Mirror.Weaver.dll too. + string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); + if (assemblyName == MirrorRuntimeAssemblyName || assemblyName == MirrorWeaverAssemblyName) + { + return; + } + + // find Mirror.dll + Assembly mirrorAssembly = FindCompilationPipelineAssembly(MirrorRuntimeAssemblyName); + if (mirrorAssembly == null) + { + Debug.LogError("Failed to find Mirror runtime assembly"); + return; + } + + string mirrorRuntimeDll = mirrorAssembly.outputPath; + if (!File.Exists(mirrorRuntimeDll)) + { + // this is normal, it happens with any assembly that is built before mirror + // such as unity packages or your own assemblies + // those don't need to be weaved + // if any assembly depends on mirror, then it will be built after + return; + } + + // find UnityEngine.CoreModule.dll + string unityEngineCoreModuleDLL = UnityEditorInternal.InternalEditorUtility.GetEngineCoreModuleAssemblyPath(); + if (string.IsNullOrEmpty(unityEngineCoreModuleDLL)) + { + Debug.LogError("Failed to find UnityEngine assembly"); + return; + } + + HashSet dependencyPaths = GetDependencyPaths(assemblyPath); + dependencyPaths.Add(Path.GetDirectoryName(mirrorRuntimeDll)); + dependencyPaths.Add(Path.GetDirectoryName(unityEngineCoreModuleDLL)); + + if (!WeaveFromFile(assemblyPath, dependencyPaths.ToArray())) + { + // Set false...will be checked in \Editor\EnterPlayModeSettingsCheck.CheckSuccessfulWeave() + SessionState.SetBool("MIRROR_WEAVE_SUCCESS", false); + if (UnityLogEnabled) Debug.LogError($"Weaving failed for {assemblyPath}"); + } + } + + static HashSet GetDependencyPaths(string assemblyPath) + { + // build directory list for later asm/symbol resolving using CompilationPipeline refs + HashSet dependencyPaths = new HashSet + { + Path.GetDirectoryName(assemblyPath) + }; + foreach (Assembly assembly in CompilationPipeline.GetAssemblies()) + { + if (assembly.outputPath == assemblyPath) + { + foreach (string reference in assembly.compiledAssemblyReferences) + { + dependencyPaths.Add(Path.GetDirectoryName(reference)); + } + } + } + + return dependencyPaths; + } + // helper function to invoke Weaver with an AssemblyDefinition from a + // file path, with dependencies added. + static bool WeaveFromFile(string assemblyPath, string[] dependencies) + { + // resolve assembly from stream + using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver()) + using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters{ ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver })) + { + // add this assembly's path and unity's assembly path + asmResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath)); + asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName()); + + // add dependencies + if (dependencies != null) + { + foreach (string path in dependencies) + { + asmResolver.AddSearchDirectory(path); + } + } + + // create weaver with logger + weaver = new Weaver(new CompilationFinishedLogger()); + if (weaver.Weave(assembly, asmResolver, out bool modified)) + { + // write changes to file if modified + if (modified) + assembly.Write(new WriterParameters{WriteSymbols = true}); + + return true; + } + return false; + } + } + } +} +#endif diff --git a/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs.meta new file mode 100644 index 0000000..ed537ab --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedHook.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de2aeb2e8068f421a9a1febe408f7051 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedLogger.cs b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedLogger.cs new file mode 100644 index 0000000..e053404 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedLogger.cs @@ -0,0 +1,31 @@ +// logger for compilation finished hook. +// where we need a callback and Debug.Log. +// for Unity 2020+ we use ILPostProcessor. +#if !UNITY_2020_3_OR_NEWER +using Mono.CecilX; +using UnityEngine; + +namespace Mirror.Weaver +{ + public class CompilationFinishedLogger : Logger + { + public void Warning(string message) => Warning(message, null); + public void Warning(string message, MemberReference mr) + { + if (mr != null) message = $"{message} (at {mr})"; + + if (CompilationFinishedHook.UnityLogEnabled) Debug.LogWarning(message); + CompilationFinishedHook.OnWeaverWarning?.Invoke(message); + } + + public void Error(string message) => Error(message, null); + public void Error(string message, MemberReference mr) + { + if (mr != null) message = $"{message} (at {mr})"; + + if (CompilationFinishedHook.UnityLogEnabled) Debug.LogError(message); + CompilationFinishedHook.OnWeaverError?.Invoke(message); + } + } +} +#endif diff --git a/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedLogger.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedLogger.cs.meta new file mode 100644 index 0000000..f8c7139 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPoint/CompilationFinishedLogger.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 47026732f0fa475c94bd1dd41f1de559 +timeCreated: 1629379868 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPoint/EnterPlayModeHook.cs b/Assets/Mirror/Editor/Weaver/EntryPoint/EnterPlayModeHook.cs new file mode 100644 index 0000000..5dffa97 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPoint/EnterPlayModeHook.cs @@ -0,0 +1,44 @@ +#if !UNITY_2020_3_OR_NEWER +// make sure we weaved successfully when entering play mode. +using UnityEditor; +using UnityEngine; + +namespace Mirror +{ + public class EnterPlayModeSettingsCheck : MonoBehaviour + { + [InitializeOnLoadMethod] + static void OnInitializeOnLoad() + { + // Hook this event to see if we have a good weave every time + // user attempts to enter play mode or tries to do a build + EditorApplication.playModeStateChanged += OnPlayModeStateChanged; + } + + static void OnPlayModeStateChanged(PlayModeStateChange state) + { + // Per Unity docs, this fires "when exiting edit mode before the Editor is in play mode". + // This doesn't fire when closing the editor. + if (state == PlayModeStateChange.ExitingEditMode) + { + // Check if last weave result was successful + if (!SessionState.GetBool("MIRROR_WEAVE_SUCCESS", false)) + { + // Last weave result was a failure...try to weave again + // Faults will show in the console that may have been cleared by "Clear on Play" + SessionState.SetBool("MIRROR_WEAVE_SUCCESS", true); + Weaver.CompilationFinishedHook.WeaveExistingAssemblies(); + + // Did that clear things up for us? + if (!SessionState.GetBool("MIRROR_WEAVE_SUCCESS", false)) + { + // Nope, still failed, and console has the issues logged + Debug.LogError("Can't enter play mode until weaver issues are resolved."); + EditorApplication.isPlaying = false; + } + } + } + } + } +} +#endif diff --git a/Assets/Mirror/Editor/Weaver/EntryPoint/EnterPlayModeHook.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPoint/EnterPlayModeHook.cs.meta new file mode 100644 index 0000000..eca31e3 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPoint/EnterPlayModeHook.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b73d0f106ba84aa983baa5142b08a0a9 +timeCreated: 1628851346 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor.meta b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor.meta new file mode 100644 index 0000000..6ef7bf3 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 09082db63d1d48d9ab91320165c1b684 +timeCreated: 1628859005 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/CompiledAssemblyFromFile.cs b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/CompiledAssemblyFromFile.cs new file mode 100644 index 0000000..e4d9de2 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/CompiledAssemblyFromFile.cs @@ -0,0 +1,31 @@ +// tests use WeaveAssembler, which uses AssemblyBuilder to Build(). +// afterwards ILPostProcessor weaves the build. +// this works on windows, but build() does not run ILPP on mac atm. +// we need to manually invoke ILPP with an assembly from file. +// +// this is in Weaver folder becuase CompilationPipeline can only be accessed +// from assemblies with the name "Unity.*.CodeGen" +using System.IO; +using Unity.CompilationPipeline.Common.ILPostProcessing; + +namespace Mirror.Weaver +{ + public class CompiledAssemblyFromFile : ICompiledAssembly + { + readonly string assemblyPath; + + public string Name => Path.GetFileNameWithoutExtension(assemblyPath); + public string[] References { get; set; } + public string[] Defines { get; set; } + public InMemoryAssembly InMemoryAssembly { get; } + + public CompiledAssemblyFromFile(string assemblyPath) + { + this.assemblyPath = assemblyPath; + byte[] peData = File.ReadAllBytes(assemblyPath); + string pdbFileName = Path.GetFileNameWithoutExtension(assemblyPath) + ".pdb"; + byte[] pdbData = File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(assemblyPath), pdbFileName)); + InMemoryAssembly = new InMemoryAssembly(peData, pdbData); + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/CompiledAssemblyFromFile.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/CompiledAssemblyFromFile.cs.meta new file mode 100644 index 0000000..1e5091e --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/CompiledAssemblyFromFile.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9009d1db4ed44f6694a92bf8ad7738e9 +timeCreated: 1630129423 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorAssemblyResolver.cs b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorAssemblyResolver.cs new file mode 100644 index 0000000..2b6b325 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorAssemblyResolver.cs @@ -0,0 +1,199 @@ +// based on paul's resolver from +// https://github.com/MirageNet/Mirage/commit/def64cd1db525398738f057b3d1eb1fe8afc540c?branch=def64cd1db525398738f057b3d1eb1fe8afc540c&diff=split +// +// an assembly resolver's job is to open an assembly in case we want to resolve +// a type from it. +// +// for example, while weaving MyGame.dll: if we want to resolve ArraySegment, +// then we need to open and resolve from another assembly (CoreLib). +// +// using DefaultAssemblyResolver with ILPostProcessor throws Exceptions in +// WeaverTypes.cs when resolving anything, for example: +// ArraySegment in Mirror.Tests.Dll. +// +// we need a custom resolver for ILPostProcessor. +#if UNITY_2020_3_OR_NEWER +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Linq; +using System.Threading; +using Mono.CecilX; +using Unity.CompilationPipeline.Common.ILPostProcessing; + +namespace Mirror.Weaver +{ + class ILPostProcessorAssemblyResolver : IAssemblyResolver + { + readonly string[] assemblyReferences; + + // originally we used Dictionary + lock. + // Resolve() is called thousands of times for large projects. + // ILPostProcessor is multithreaded, so best to use ConcurrentDictionary without the lock here. + readonly ConcurrentDictionary assemblyCache = + new ConcurrentDictionary(); + + // Resolve() calls FindFile() every time. + // thousands of times for String => mscorlib alone in large projects. + // cache the results! ILPostProcessor is multithreaded, so use a ConcurrentDictionary here. + readonly ConcurrentDictionary fileNameCache = + new ConcurrentDictionary(); + + readonly ICompiledAssembly compiledAssembly; + AssemblyDefinition selfAssembly; + + readonly Logger Log; + + public ILPostProcessorAssemblyResolver(ICompiledAssembly compiledAssembly, Logger Log) + { + this.compiledAssembly = compiledAssembly; + assemblyReferences = compiledAssembly.References; + this.Log = Log; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + // Cleanup + } + + public AssemblyDefinition Resolve(AssemblyNameReference name) => + Resolve(name, new ReaderParameters(ReadingMode.Deferred)); + + // here is an example on when this is called: + // Player : NetworkBehaviour has a [SyncVar] of type String. + // Weaver's SyncObjectInitializer checks if ImplementsSyncObject() + // which needs to resolve the type 'String' from mscorlib. + // Resolve() lives in CecilX.MetadataResolver.Resolve() + // which calls assembly_resolver.Resolve(). + // which uses our ILPostProcessorAssemblyResolver here. + // + // for large projects, this is called thousands of times for mscorlib alone. + // initially ILPostProcessorAssemblyResolver took 30x longer than with CompilationFinishedHook. + // we need to cache and speed up everything we can here! + public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) + { + if (name.Name == compiledAssembly.Name) + return selfAssembly; + + // cache FindFile. + // in large projects, this is called thousands(!) of times for String=>mscorlib alone. + // reduces a single String=>mscorlib resolve from 0.771ms to 0.015ms. + // => 50x improvement in TypeReference.Resolve() speed! + // => 22x improvement in Weaver speed! + if (!fileNameCache.TryGetValue(name.Name, out string fileName)) + { + fileName = FindFile(name.Name); + fileNameCache.TryAdd(name.Name, fileName); + } + + if (fileName == null) + { + // returning null will throw exceptions in our weaver where. + // let's make it obvious why we returned null for easier debugging. + // NOTE: if this fails for "System.Private.CoreLib": + // ILPostProcessorReflectionImporter fixes it! + Log.Warning($"ILPostProcessorAssemblyResolver.Resolve: Failed to find file for {name}"); + return null; + } + + // try to get cached assembly by filename + writetime + DateTime lastWriteTime = File.GetLastWriteTime(fileName); + string cacheKey = fileName + lastWriteTime; + if (assemblyCache.TryGetValue(cacheKey, out AssemblyDefinition result)) + return result; + + // otherwise resolve and cache a new assembly + parameters.AssemblyResolver = this; + MemoryStream ms = MemoryStreamFor(fileName); + + string pdb = fileName + ".pdb"; + if (File.Exists(pdb)) + parameters.SymbolStream = MemoryStreamFor(pdb); + + AssemblyDefinition assemblyDefinition = AssemblyDefinition.ReadAssembly(ms, parameters); + assemblyCache.TryAdd(cacheKey, assemblyDefinition); + return assemblyDefinition; + } + + // find assemblyname in assembly's references + string FindFile(string name) + { + // perhaps the type comes from a .dll or .exe + // check both in one call without Linq instead of iterating twice like originally + foreach (string r in assemblyReferences) + { + if (Path.GetFileNameWithoutExtension(r) == name) + return r; + } + + // this is called thousands(!) of times. + // constructing strings only once saves ~0.1ms per call for mscorlib. + string dllName = name + ".dll"; + + // Unfortunately the current ICompiledAssembly API only provides direct references. + // It is very much possible that a postprocessor ends up investigating a type in a directly + // referenced assembly, that contains a field that is not in a directly referenced assembly. + // if we don't do anything special for that situation, it will fail to resolve. We should fix this + // in the ILPostProcessing API. As a workaround, we rely on the fact here that the indirect references + // are always located next to direct references, so we search in all directories of direct references we + // got passed, and if we find the file in there, we resolve to it. + foreach (string parentDir in assemblyReferences.Select(Path.GetDirectoryName).Distinct()) + { + string candidate = Path.Combine(parentDir, dllName); + if (File.Exists(candidate)) + return candidate; + } + + return null; + } + + // open file as MemoryStream. + // ILPostProcessor is multithreaded. + // retry a few times in case another thread is still accessing the file. + static MemoryStream MemoryStreamFor(string fileName) + { + return Retry(10, TimeSpan.FromSeconds(1), () => + { + byte[] byteArray; + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + byteArray = new byte[fs.Length]; + int readLength = fs.Read(byteArray, 0, (int)fs.Length); + if (readLength != fs.Length) + throw new InvalidOperationException("File read length is not full length of file."); + } + + return new MemoryStream(byteArray); + }); + } + + static MemoryStream Retry(int retryCount, TimeSpan waitTime, Func func) + { + try + { + return func(); + } + catch (IOException) + { + if (retryCount == 0) + throw; + Console.WriteLine($"Caught IO Exception, trying {retryCount} more times"); + Thread.Sleep(waitTime); + return Retry(retryCount - 1, waitTime, func); + } + } + + // if the CompiledAssembly's AssemblyDefinition is known, we can add it + public void SetAssemblyDefinitionForCompiledAssembly(AssemblyDefinition assemblyDefinition) + { + selfAssembly = assemblyDefinition; + } + } +} +#endif diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorAssemblyResolver.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorAssemblyResolver.cs.meta new file mode 100644 index 0000000..07289dd --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorAssemblyResolver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0b3e94696e22440ead0b3a42411bbe14 +timeCreated: 1629693784 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorFromFile.cs b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorFromFile.cs new file mode 100644 index 0000000..6a70641 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorFromFile.cs @@ -0,0 +1,53 @@ +// helper function to use ILPostProcessor for an assembly from file. +// we keep this in Weaver folder because we can access CompilationPipleine here. +// in tests folder we can't, unless we rename to "Unity.*.CodeGen", +// but then tests wouldn't be weaved anymore. +#if UNITY_2020_3_OR_NEWER +using System; +using System.IO; +using Unity.CompilationPipeline.Common.Diagnostics; +using Unity.CompilationPipeline.Common.ILPostProcessing; + +namespace Mirror.Weaver +{ + public static class ILPostProcessorFromFile + { + // read, weave, write file via ILPostProcessor + public static void ILPostProcessFile(string assemblyPath, string[] references, Action OnWarning, Action OnError) + { + // we COULD Weave() with a test logger manually. + // but for test result consistency on all platforms, + // let's invoke the ILPostProcessor here too. + CompiledAssemblyFromFile assembly = new CompiledAssemblyFromFile(assemblyPath); + assembly.References = references; + + // create ILPP and check WillProcess like Unity would. + ILPostProcessorHook ilpp = new ILPostProcessorHook(); + if (ilpp.WillProcess(assembly)) + { + //Debug.Log($"Will Process: {assembly.Name}"); + + // process it like Unity would + ILPostProcessResult result = ilpp.Process(assembly); + + // handle the error messages like Unity would + foreach (DiagnosticMessage message in result.Diagnostics) + { + if (message.DiagnosticType == DiagnosticType.Warning) + { + OnWarning(message.MessageData); + } + else if (message.DiagnosticType == DiagnosticType.Error) + { + OnError(message.MessageData); + } + } + + // save the weaved assembly to file. + // some tests open it and check for certain IL code. + File.WriteAllBytes(assemblyPath, result.InMemoryAssembly.PeData); + } + } + } +} +#endif diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorFromFile.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorFromFile.cs.meta new file mode 100644 index 0000000..e06dfa7 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorFromFile.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2a4b115486b74d27a9540f3c39ae2d46 +timeCreated: 1630152191 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorHook.cs b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorHook.cs new file mode 100644 index 0000000..0cfb433 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorHook.cs @@ -0,0 +1,143 @@ +// hook via ILPostProcessor from Unity 2020.3+ +// (2020.1 has errors https://github.com/vis2k/Mirror/issues/2912) +#if UNITY_2020_3_OR_NEWER +// Unity.CompilationPipeline reference is only resolved if assembly name is +// Unity.*.CodeGen: +// https://forum.unity.com/threads/how-does-unity-do-codegen-and-why-cant-i-do-it-myself.853867/#post-5646937 +using System.IO; +using System.Linq; +// to use Mono.CecilX here, we need to 'override references' in the +// Unity.Mirror.CodeGen assembly definition file in the Editor, and add CecilX. +// otherwise we get a reflection exception with 'file not found: CecilX'. +using Mono.CecilX; +using Mono.CecilX.Cil; +using Unity.CompilationPipeline.Common.ILPostProcessing; +// IMPORTANT: 'using UnityEngine' does not work in here. +// Unity gives "(0,0): error System.Security.SecurityException: ECall methods must be packaged into a system module." +//using UnityEngine; + +namespace Mirror.Weaver +{ + public class ILPostProcessorHook : ILPostProcessor + { + // from CompilationFinishedHook + const string MirrorRuntimeAssemblyName = "Mirror"; + + // ILPostProcessor is invoked by Unity. + // we can not tell it to ignore certain assemblies before processing. + // add a 'ignore' define for convenience. + // => WeaverTests/WeaverAssembler need it to avoid Unity running it + public const string IgnoreDefine = "ILPP_IGNORE"; + + // we can't use Debug.Log in ILPP, so we need a custom logger + ILPostProcessorLogger Log = new ILPostProcessorLogger(); + + // ??? + public override ILPostProcessor GetInstance() => this; + + // check if assembly has the 'ignore' define + static bool HasDefine(ICompiledAssembly assembly, string define) => + assembly.Defines != null && + assembly.Defines.Contains(define); + + // process Mirror, or anything that references Mirror + public override bool WillProcess(ICompiledAssembly compiledAssembly) + { + // compiledAssembly.References are file paths: + // Library/Bee/artifacts/200b0aE.dag/Mirror.CompilerSymbols.dll + // Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll + // /Applications/Unity/Hub/Editor/2021.2.0b6_apple_silicon/Unity.app/Contents/NetStandard/ref/2.1.0/netstandard.dll + // + // log them to see: + // foreach (string reference in compiledAssembly.References) + // LogDiagnostics($"{compiledAssembly.Name} references {reference}"); + bool relevant = compiledAssembly.Name == MirrorRuntimeAssemblyName || + compiledAssembly.References.Any(filePath => Path.GetFileNameWithoutExtension(filePath) == MirrorRuntimeAssemblyName); + bool ignore = HasDefine(compiledAssembly, IgnoreDefine); + return relevant && !ignore; + } + + public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) + { + //Log.Warning($"Processing {compiledAssembly.Name}"); + + // load the InMemoryAssembly peData into a MemoryStream + byte[] peData = compiledAssembly.InMemoryAssembly.PeData; + //LogDiagnostics($" peData.Length={peData.Length} bytes"); + using (MemoryStream stream = new MemoryStream(peData)) + using (ILPostProcessorAssemblyResolver asmResolver = new ILPostProcessorAssemblyResolver(compiledAssembly, Log)) + { + // we need to load symbols. otherwise we get: + // "(0,0): error Mono.CecilX.Cil.SymbolsNotFoundException: No symbol found for file: " + using (MemoryStream symbols = new MemoryStream(compiledAssembly.InMemoryAssembly.PdbData)) + { + ReaderParameters readerParameters = new ReaderParameters{ + SymbolStream = symbols, + ReadWrite = true, + ReadSymbols = true, + AssemblyResolver = asmResolver, + // custom reflection importer to fix System.Private.CoreLib + // not being found in custom assembly resolver above. + ReflectionImporterProvider = new ILPostProcessorReflectionImporterProvider() + }; + using (AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(stream, readerParameters)) + { + // resolving a Mirror.dll type like NetworkServer while + // weaving Mirror.dll does not work. it throws a + // NullReferenceException in WeaverTypes.ctor + // when Resolve() is called on the first Mirror type. + // need to add the AssemblyDefinition itself to use. + asmResolver.SetAssemblyDefinitionForCompiledAssembly(asmDef); + + // weave this assembly. + Weaver weaver = new Weaver(Log); + if (weaver.Weave(asmDef, asmResolver, out bool modified)) + { + //Log.Warning($"Weaving succeeded for: {compiledAssembly.Name}"); + + // write if modified + if (modified) + { + // when weaving Mirror.dll with ILPostProcessor, + // Weave() -> WeaverTypes -> resolving the first + // type in Mirror.dll adds a reference to + // Mirror.dll even though we are in Mirror.dll. + // -> this would throw an exception: + // "Mirror references itself" and not compile + // -> need to detect and fix manually here + if (asmDef.MainModule.AssemblyReferences.Any(r => r.Name == asmDef.Name.Name)) + { + asmDef.MainModule.AssemblyReferences.Remove(asmDef.MainModule.AssemblyReferences.First(r => r.Name == asmDef.Name.Name)); + //Log.Warning($"fixed self referencing Assembly: {asmDef.Name.Name}"); + } + + MemoryStream peOut = new MemoryStream(); + MemoryStream pdbOut = new MemoryStream(); + WriterParameters writerParameters = new WriterParameters + { + SymbolWriterProvider = new PortablePdbWriterProvider(), + SymbolStream = pdbOut, + WriteSymbols = true + }; + + asmDef.Write(peOut, writerParameters); + + InMemoryAssembly inMemory = new InMemoryAssembly(peOut.ToArray(), pdbOut.ToArray()); + return new ILPostProcessResult(inMemory, Log.Logs); + } + } + // if anything during Weave() fails, we log an error. + // don't need to indicate 'weaving failed' again. + // in fact, this would break tests only expecting certain errors. + //else Log.Error($"Weaving failed for: {compiledAssembly.Name}"); + } + } + } + + // always return an ILPostProcessResult with Logs. + // otherwise we won't see Logs if weaving failed. + return new ILPostProcessResult(compiledAssembly.InMemoryAssembly, Log.Logs); + } + } +} +#endif diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorHook.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorHook.cs.meta new file mode 100644 index 0000000..9d7e0a2 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorHook.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5f113eb695b348b5b28cd85358c8959a +timeCreated: 1628859074 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorLogger.cs b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorLogger.cs new file mode 100644 index 0000000..e8595fd --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorLogger.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using Mono.CecilX; +using Unity.CompilationPipeline.Common.Diagnostics; + +namespace Mirror.Weaver +{ + public class ILPostProcessorLogger : Logger + { + // can't Debug.Log in ILPostProcessor. need to add to this list. + internal List Logs = new List(); + + void Add(string message, DiagnosticType logType) + { + Logs.Add(new DiagnosticMessage + { + // TODO add file etc. for double click opening later? + DiagnosticType = logType, // doesn't have .Log + File = null, + Line = 0, + Column = 0, + MessageData = message + }); + } + + public void LogDiagnostics(string message, DiagnosticType logType = DiagnosticType.Warning) + { + // TODO IN-44868 FIX IS IN 2021.3.32f1, 2022.3.11f1, 2023.2.0b13 and 2023.3.0a8 + // DiagnosticMessage can't display \n for some reason. + // it just cuts it off and we don't see any stack trace. + // so let's replace all line breaks so we get the stack trace. + // (Unity 2021.2.0b6 apple silicon) + //message = message.Replace("\n", "/"); + + // lets break it into several messages instead so it's easier readable + string[] lines = message.Split('\n'); + + // if it's just one line, simply log it + if (lines.Length == 1) + { + // tests assume exact message log. + // don't include 'Weaver: ...' or similar. + Add($"{message}", logType); + } + // for multiple lines, log each line separately with start/end indicators + else + { + // first line with Weaver: ... first + Add("----------------------------------------------", logType); + foreach (string line in lines) Add(line, logType); + Add("----------------------------------------------", logType); + } + } + + public void Warning(string message) => Warning(message, null); + public void Warning(string message, MemberReference mr) + { + if (mr != null) message = $"{message} (at {mr})"; + LogDiagnostics(message, DiagnosticType.Warning); + } + + public void Error(string message) => Error(message, null); + public void Error(string message, MemberReference mr) + { + if (mr != null) message = $"{message} (at {mr})"; + LogDiagnostics(message, DiagnosticType.Error); + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorLogger.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorLogger.cs.meta new file mode 100644 index 0000000..8bb72e0 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorLogger.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e7b56e7826664e34a415e4b70d958f2a +timeCreated: 1629533154 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporter.cs b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporter.cs new file mode 100644 index 0000000..e15c103 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporter.cs @@ -0,0 +1,36 @@ +// based on paul's resolver from +// https://github.com/MirageNet/Mirage/commit/def64cd1db525398738f057b3d1eb1fe8afc540c?branch=def64cd1db525398738f057b3d1eb1fe8afc540c&diff=split +// +// ILPostProcessorAssemblyRESOLVER does not find the .dll file for: +// "System.Private.CoreLib" +// we need this custom reflection importer to fix that. +using System.Linq; +using System.Reflection; +using Mono.CecilX; + +namespace Mirror.Weaver +{ + internal class ILPostProcessorReflectionImporter : DefaultReflectionImporter + { + const string SystemPrivateCoreLib = "System.Private.CoreLib"; + readonly AssemblyNameReference fixedCoreLib; + + public ILPostProcessorReflectionImporter(ModuleDefinition module) : base(module) + { + // find the correct library for "System.Private.CoreLib". + // either mscorlib or netstandard. + // defaults to System.Private.CoreLib if not found. + fixedCoreLib = module.AssemblyReferences.FirstOrDefault(a => a.Name == "mscorlib" || a.Name == "netstandard" || a.Name == SystemPrivateCoreLib); + } + + public override AssemblyNameReference ImportReference(AssemblyName name) + { + // System.Private.CoreLib? + if (name.Name == SystemPrivateCoreLib && fixedCoreLib != null) + return fixedCoreLib; + + // otherwise import as usual + return base.ImportReference(name); + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporter.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporter.cs.meta new file mode 100644 index 0000000..d361e21 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6403a7e3b3ae4e009ae282f111d266e0 +timeCreated: 1629709256 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporterProvider.cs b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporterProvider.cs new file mode 100644 index 0000000..7358e1b --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporterProvider.cs @@ -0,0 +1,16 @@ +// based on paul's resolver from +// https://github.com/MirageNet/Mirage/commit/def64cd1db525398738f057b3d1eb1fe8afc540c?branch=def64cd1db525398738f057b3d1eb1fe8afc540c&diff=split +// +// ILPostProcessorAssemblyRESOLVER does not find the .dll file for: +// "System.Private.CoreLib" +// we need this custom reflection importer to fix that. +using Mono.CecilX; + +namespace Mirror.Weaver +{ + internal class ILPostProcessorReflectionImporterProvider : IReflectionImporterProvider + { + public IReflectionImporter GetReflectionImporter(ModuleDefinition module) => + new ILPostProcessorReflectionImporter(module); + } +} diff --git a/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporterProvider.cs.meta b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporterProvider.cs.meta new file mode 100644 index 0000000..d9b6f6b --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/EntryPointILPostProcessor/ILPostProcessorReflectionImporterProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a1003b568bad4e69b961c4c81d5afd96 +timeCreated: 1629709223 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/Extensions.cs b/Assets/Mirror/Editor/Weaver/Extensions.cs new file mode 100644 index 0000000..566a51a --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Extensions.cs @@ -0,0 +1,359 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Mono.CecilX; + +namespace Mirror.Weaver +{ + public static class Extensions + { + public static bool Is(this TypeReference td, Type type) => + type.IsGenericType + ? td.GetElementType().FullName == type.FullName + : td.FullName == type.FullName; + + // check if 'td' is exactly of type T. + // it does not check if any base type is of , only the specific type. + // for example: + // NetworkConnection Is NetworkConnection: true + // NetworkConnectionToClient Is NetworkConnection: false + public static bool Is(this TypeReference td) => Is(td, typeof(T)); + + // check if 'tr' is derived from T. + // it does not check if 'tr' is exactly T. + // for example: + // NetworkConnection IsDerivedFrom: false + // NetworkConnectionToClient IsDerivedFrom: true + public static bool IsDerivedFrom(this TypeReference tr) => IsDerivedFrom(tr, typeof(T)); + + public static bool IsDerivedFrom(this TypeReference tr, Type baseClass) + { + TypeDefinition td = tr.Resolve(); + if (!td.IsClass) + return false; + + // are ANY parent classes of baseClass? + TypeReference parent = td.BaseType; + + if (parent == null) + return false; + + if (parent.Is(baseClass)) + return true; + + if (parent.CanBeResolved()) + return IsDerivedFrom(parent.Resolve(), baseClass); + + return false; + } + + public static TypeReference GetEnumUnderlyingType(this TypeDefinition td) + { + foreach (FieldDefinition field in td.Fields) + { + if (!field.IsStatic) + return field.FieldType; + } + throw new ArgumentException($"Invalid enum {td.FullName}"); + } + + public static bool ImplementsInterface(this TypeDefinition td) + { + TypeDefinition typedef = td; + + while (typedef != null) + { + if (typedef.Interfaces.Any(iface => iface.InterfaceType.Is())) + return true; + + try + { + TypeReference parent = typedef.BaseType; + typedef = parent?.Resolve(); + } + catch (AssemblyResolutionException) + { + // this can happen for plugins. + //Console.WriteLine("AssemblyResolutionException: "+ ex.ToString()); + break; + } + } + + return false; + } + + public static bool IsMultidimensionalArray(this TypeReference tr) => + tr is ArrayType arrayType && arrayType.Rank > 1; + + // Does type use netId as backing field + public static bool IsNetworkIdentityField(this TypeReference tr) => + tr.Is() || + tr.Is() || + // handle both NetworkBehaviour and inheritors. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/2939 + tr.IsDerivedFrom() || + tr.Is(); + + public static bool CanBeResolved(this TypeReference parent) + { + while (parent != null) + { + if (parent.Scope.Name == "Windows") + { + return false; + } + + if (parent.Scope.Name == "mscorlib") + { + TypeDefinition resolved = parent.Resolve(); + return resolved != null; + } + + try + { + parent = parent.Resolve().BaseType; + } + catch + { + return false; + } + } + return true; + } + + // Makes T => Variable and imports function + public static MethodReference MakeGeneric(this MethodReference generic, ModuleDefinition module, TypeReference variableReference) + { + GenericInstanceMethod instance = new GenericInstanceMethod(generic); + instance.GenericArguments.Add(variableReference); + + MethodReference readFunc = module.ImportReference(instance); + return readFunc; + } + + // Given a method of a generic class such as ArraySegment`T.get_Count, + // and a generic instance such as ArraySegment`int + // Creates a reference to the specialized method ArraySegment`int`.get_Count + // Note that calling ArraySegment`T.get_Count directly gives an invalid IL error + public static MethodReference MakeHostInstanceGeneric(this MethodReference self, ModuleDefinition module, GenericInstanceType instanceType) + { + MethodReference reference = new MethodReference(self.Name, self.ReturnType, instanceType) + { + CallingConvention = self.CallingConvention, + HasThis = self.HasThis, + ExplicitThis = self.ExplicitThis + }; + + foreach (ParameterDefinition parameter in self.Parameters) + reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType)); + + foreach (GenericParameter generic_parameter in self.GenericParameters) + reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference)); + + return module.ImportReference(reference); + } + + // needed for NetworkBehaviour support + // https://github.com/vis2k/Mirror/pull/3073/ + public static FieldReference MakeHostInstanceGeneric(this FieldReference self) + { + var declaringType = new GenericInstanceType(self.DeclaringType); + foreach (var parameter in self.DeclaringType.GenericParameters) + { + declaringType.GenericArguments.Add(parameter); + } + return new FieldReference(self.Name, self.FieldType, declaringType); + } + + // Given a field of a generic class such as Writer.write, + // and a generic instance such as ArraySegment`int + // Creates a reference to the specialized method ArraySegment`int`.get_Count + // Note that calling ArraySegment`T.get_Count directly gives an invalid IL error + public static FieldReference SpecializeField(this FieldReference self, ModuleDefinition module, GenericInstanceType instanceType) + { + FieldReference reference = new FieldReference(self.Name, self.FieldType, instanceType); + return module.ImportReference(reference); + } + + public static CustomAttribute GetCustomAttribute(this ICustomAttributeProvider method) + { + return method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.Is()); + } + + public static bool HasCustomAttribute(this ICustomAttributeProvider attributeProvider) + { + return attributeProvider.CustomAttributes.Any(attr => attr.AttributeType.Is()); + } + + public static T GetField(this CustomAttribute ca, string field, T defaultValue) + { + foreach (CustomAttributeNamedArgument customField in ca.Fields) + if (customField.Name == field) + return (T)customField.Argument.Value; + return defaultValue; + } + + public static MethodDefinition GetMethod(this TypeDefinition td, string methodName) + { + return td.Methods.FirstOrDefault(method => method.Name == methodName); + } + + public static List GetMethods(this TypeDefinition td, string methodName) + { + return td.Methods.Where(method => method.Name == methodName).ToList(); + } + + public static MethodDefinition GetMethodInBaseType(this TypeDefinition td, string methodName) + { + TypeDefinition typedef = td; + while (typedef != null) + { + foreach (MethodDefinition md in typedef.Methods) + { + if (md.Name == methodName) + return md; + } + + try + { + TypeReference parent = typedef.BaseType; + typedef = parent?.Resolve(); + } + catch (AssemblyResolutionException) + { + // this can happen for plugins. + break; + } + } + + return null; + } + + // Finds public fields in type and base type + public static IEnumerable FindAllPublicFields(this TypeReference variable) + { + return FindAllPublicFields(variable.Resolve()); + } + + // Finds public fields in type and base type + public static IEnumerable FindAllPublicFields(this TypeDefinition typeDefinition) + { + while (typeDefinition != null) + { + foreach (FieldDefinition field in typeDefinition.Fields) + { + // ignore static, private, protected fields + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3485 + // credit: James Frowen + if (field.IsStatic || field.IsPrivate || field.IsFamily) + continue; + + // also ignore internal fields + // we dont want to create different writers for this type if they are in current dll or another dll + // so we have to ignore internal in all cases + if (field.IsAssembly) + continue; + + if (field.IsNotSerialized) + continue; + + yield return field; + } + + try + { + typeDefinition = typeDefinition.BaseType?.Resolve(); + } + catch (AssemblyResolutionException) + { + break; + } + } + } + + public static bool ContainsClass(this ModuleDefinition module, string nameSpace, string className) => + module.GetTypes().Any(td => td.Namespace == nameSpace && + td.Name == className); + + + public static AssemblyNameReference FindReference(this ModuleDefinition module, string referenceName) + { + foreach (AssemblyNameReference reference in module.AssemblyReferences) + { + if (reference.Name == referenceName) + return reference; + } + return null; + } + + // Takes generic arguments from child class and applies them to parent reference, if possible + // eg makes `Base` in Child : Base have `int` instead of `T` + // Originally by James-Frowen under MIT + // https://github.com/MirageNet/Mirage/commit/cf91e1d54796866d2cf87f8e919bb5c681977e45 + public static TypeReference ApplyGenericParameters(this TypeReference parentReference, + TypeReference childReference) + { + // If the parent is not generic, we got nothing to apply + if (!parentReference.IsGenericInstance) + return parentReference; + + GenericInstanceType parentGeneric = (GenericInstanceType)parentReference; + // make new type so we can replace the args on it + // resolve it so we have non-generic instance (eg just instance with instead of ) + // if we don't cecil will make it double generic (eg INVALID IL) + GenericInstanceType generic = new GenericInstanceType(parentReference.Resolve()); + foreach (TypeReference arg in parentGeneric.GenericArguments) + generic.GenericArguments.Add(arg); + + for (int i = 0; i < generic.GenericArguments.Count; i++) + { + // if arg is not generic + // eg List would be int so not generic. + // But List would be T so is generic + if (!generic.GenericArguments[i].IsGenericParameter) + continue; + + // get the generic name, eg T + string name = generic.GenericArguments[i].Name; + // find what type T is, eg turn it into `int` if `List` + TypeReference arg = FindMatchingGenericArgument(childReference, name); + + // import just to be safe + TypeReference imported = parentReference.Module.ImportReference(arg); + // set arg on generic, parent ref will be Base instead of just Base + generic.GenericArguments[i] = imported; + } + + return generic; + } + + // Finds the type reference for a generic parameter with the provided name in the child reference + // Originally by James-Frowen under MIT + // https://github.com/MirageNet/Mirage/commit/cf91e1d54796866d2cf87f8e919bb5c681977e45 + static TypeReference FindMatchingGenericArgument(TypeReference childReference, string paramName) + { + TypeDefinition def = childReference.Resolve(); + // child class must be generic if we are in this part of the code + // eg Child : Base <--- child must have generic if Base has T + // vs Child : Base <--- wont be here if Base has int (we check if T exists before calling this) + if (!def.HasGenericParameters) + throw new InvalidOperationException( + "Base class had generic parameters, but could not find them in child class"); + + // go through parameters in child class, and find the generic that matches the name + for (int i = 0; i < def.GenericParameters.Count; i++) + { + GenericParameter param = def.GenericParameters[i]; + if (param.Name == paramName) + { + GenericInstanceType generic = (GenericInstanceType)childReference; + // return generic arg with same index + return generic.GenericArguments[i]; + } + } + + // this should never happen, if it does it means that this code is bugged + throw new InvalidOperationException("Did not find matching generic"); + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Extensions.cs.meta b/Assets/Mirror/Editor/Weaver/Extensions.cs.meta new file mode 100644 index 0000000..78660f9 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Extensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 562a5cf0254cc45738e9aa549a7100b2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Helpers.cs b/Assets/Mirror/Editor/Weaver/Helpers.cs new file mode 100644 index 0000000..56b7385 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Helpers.cs @@ -0,0 +1,26 @@ +using System.IO; +using System.Linq; +using System.Reflection; +using Mono.CecilX; + +namespace Mirror.Weaver +{ + static class Helpers + { + // This code is taken from SerializationWeaver + public static string UnityEngineDllDirectoryName() + { + string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase); + return directoryName?.Replace(@"file:\", ""); + } + + public static bool IsEditorAssembly(AssemblyDefinition currentAssembly) + { + // we want to add the [InitializeOnLoad] attribute if it's available + // -> usually either 'UnityEditor' or 'UnityEditor.CoreModule' + return currentAssembly.MainModule.AssemblyReferences.Any(assemblyReference => + assemblyReference.Name.StartsWith(nameof(UnityEditor)) + ); + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Helpers.cs.meta b/Assets/Mirror/Editor/Weaver/Helpers.cs.meta new file mode 100644 index 0000000..231f539 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Helpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c4ed76daf48547c5abb7c58f8d20886 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Logger.cs b/Assets/Mirror/Editor/Weaver/Logger.cs new file mode 100644 index 0000000..8be978f --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Logger.cs @@ -0,0 +1,13 @@ +using Mono.CecilX; + +namespace Mirror.Weaver +{ + // not static, because ILPostProcessor is multithreaded + public interface Logger + { + void Warning(string message); + void Warning(string message, MemberReference mr); + void Error(string message); + void Error(string message, MemberReference mr); + } +} diff --git a/Assets/Mirror/Editor/Weaver/Logger.cs.meta b/Assets/Mirror/Editor/Weaver/Logger.cs.meta new file mode 100644 index 0000000..3f62978 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Logger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a21c60c40a4c4d679c2b71a7c40882e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors.meta b/Assets/Mirror/Editor/Weaver/Processors.meta new file mode 100644 index 0000000..eb719b4 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e538d627280d2471b8c72fdea822ca49 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs new file mode 100644 index 0000000..db2d5af --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs @@ -0,0 +1,130 @@ +using Mono.CecilX; +using Mono.CecilX.Cil; + +namespace Mirror.Weaver +{ + // Processes [Command] methods in NetworkBehaviour + public static class CommandProcessor + { + /* + // generates code like: + public void CmdThrust(float thrusting, int spin) + { + NetworkWriterPooled writer = NetworkWriterPool.Get(); + writer.Write(thrusting); + writer.WritePackedUInt32((uint)spin); + base.SendCommandInternal(cmdName, cmdHash, writer, channel); + NetworkWriterPool.Return(writer); + } + + public void CallCmdThrust(float thrusting, int spin) + { + // whatever the user was doing before + } + + Originally HLAPI put the send message code inside the Call function + and then proceeded to replace every call to CmdTrust with CallCmdTrust + + This method moves all the user's code into the "CallCmd" method + and replaces the body of the original method with the send message code. + This way we do not need to modify the code anywhere else, and this works + correctly in dependent assemblies + */ + public static MethodDefinition ProcessCommandCall(WeaverTypes weaverTypes, Writers writers, Logger Log, TypeDefinition td, MethodDefinition md, CustomAttribute commandAttr, ref bool WeavingFailed) + { + MethodDefinition cmd = MethodProcessor.SubstituteMethod(Log, td, md, ref WeavingFailed); + + ILProcessor worker = md.Body.GetILProcessor(); + + NetworkBehaviourProcessor.WriteSetupLocals(worker, weaverTypes); + + // NetworkWriter writer = new NetworkWriter(); + NetworkBehaviourProcessor.WriteGetWriter(worker, weaverTypes); + + // write all the arguments that the user passed to the Cmd call + if (!NetworkBehaviourProcessor.WriteArguments(worker, writers, Log, md, RemoteCallType.Command, ref WeavingFailed)) + return null; + + int channel = commandAttr.GetField("channel", 0); + bool requiresAuthority = commandAttr.GetField("requiresAuthority", true); + + // invoke internal send and return + // load 'base.' to call the SendCommand function with + worker.Emit(OpCodes.Ldarg_0); + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + worker.Emit(OpCodes.Ldstr, md.FullName); + // pass the function hash so we don't have to compute it at runtime + // otherwise each GetStableHash call requires O(N) complexity. + // noticeable for long function names: + // https://github.com/MirrorNetworking/Mirror/issues/3375 + worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode()); + // writer + worker.Emit(OpCodes.Ldloc_0); + worker.Emit(OpCodes.Ldc_I4, channel); + // requiresAuthority ? 1 : 0 + worker.Emit(requiresAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + worker.Emit(OpCodes.Call, weaverTypes.sendCommandInternal); + + NetworkBehaviourProcessor.WriteReturnWriter(worker, weaverTypes); + + worker.Emit(OpCodes.Ret); + return cmd; + } + + /* + // generates code like: + protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader reader, NetworkConnection senderConnection) + { + if (!NetworkServer.active) + { + return; + } + ((ShipControl)obj).CmdThrust(reader.ReadSingle(), (int)reader.ReadPackedUInt32()); + } + */ + public static MethodDefinition ProcessCommandInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition method, MethodDefinition cmdCallFunc, ref bool WeavingFailed) + { + string cmdName = Weaver.GenerateMethodName(RemoteCalls.RemoteProcedureCalls.InvokeRpcPrefix, method); + + MethodDefinition cmd = new MethodDefinition(cmdName, + MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, + weaverTypes.Import(typeof(void))); + + ILProcessor worker = cmd.Body.GetILProcessor(); + Instruction label = worker.Create(OpCodes.Nop); + + NetworkBehaviourProcessor.WriteServerActiveCheck(worker, weaverTypes, method.Name, label, "Command"); + + // setup for reader + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Castclass, td); + + if (!NetworkBehaviourProcessor.ReadArguments(method, readers, Log, worker, RemoteCallType.Command, ref WeavingFailed)) + return null; + + AddSenderConnection(method, worker); + + // invoke actual command function + worker.Emit(OpCodes.Callvirt, cmdCallFunc); + worker.Emit(OpCodes.Ret); + + NetworkBehaviourProcessor.AddInvokeParameters(weaverTypes, cmd.Parameters); + + td.Methods.Add(cmd); + return cmd; + } + + static void AddSenderConnection(MethodDefinition method, ILProcessor worker) + { + foreach (ParameterDefinition param in method.Parameters) + { + if (NetworkBehaviourProcessor.IsSenderConnection(param, RemoteCallType.Command)) + { + // NetworkConnection is 3nd arg (arg0 is "obj" not "this" because method is static) + // example: static void InvokeCmdCmdSendCommand(NetworkBehaviour obj, NetworkReader reader, NetworkConnection connection) + worker.Emit(OpCodes.Ldarg_2); + } + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs.meta new file mode 100644 index 0000000..20c3e15 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73f6c9cdbb9e54f65b3a0a35cc8e55c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs new file mode 100644 index 0000000..8a4c581 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs @@ -0,0 +1,139 @@ +using Mono.CecilX; +using Mono.CecilX.Cil; + +namespace Mirror.Weaver +{ + public static class MethodProcessor + { + const string RpcPrefix = "UserCode_"; + + // For a function like + // [ClientRpc] void RpcTest(int value), + // Weaver substitutes the method and moves the code to a new method: + // UserCode_RpcTest(int value) <- contains original code + // RpcTest(int value) <- serializes parameters, sends the message + // + // Note that all the calls to the method remain untouched. + // FixRemoteCallToBaseMethod replaces them afterwards. + public static MethodDefinition SubstituteMethod(Logger Log, TypeDefinition td, MethodDefinition md, ref bool WeavingFailed) + { + string newName = Weaver.GenerateMethodName(RpcPrefix, md); + + MethodDefinition cmd = new MethodDefinition(newName, md.Attributes, md.ReturnType); + + // force the substitute method to be protected. + // -> public would show in the Inspector for UnityEvents as + // User_CmdUsePotion() etc. but the user shouldn't use those. + // -> private would not allow inheriting classes to call it, see + // OverrideVirtualWithBaseCallsBothVirtualAndBase test. + // -> IL has no concept of 'protected', it's called IsFamily there. + cmd.IsPublic = false; + cmd.IsFamily = true; + + // add parameters + foreach (ParameterDefinition pd in md.Parameters) + { + cmd.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType)); + } + + // swap bodies + (cmd.Body, md.Body) = (md.Body, cmd.Body); + + // Move over all the debugging information + foreach (SequencePoint sequencePoint in md.DebugInformation.SequencePoints) + cmd.DebugInformation.SequencePoints.Add(sequencePoint); + md.DebugInformation.SequencePoints.Clear(); + + foreach (CustomDebugInformation customInfo in md.CustomDebugInformations) + cmd.CustomDebugInformations.Add(customInfo); + md.CustomDebugInformations.Clear(); + + (md.DebugInformation.Scope, cmd.DebugInformation.Scope) = (cmd.DebugInformation.Scope, md.DebugInformation.Scope); + + td.Methods.Add(cmd); + + FixRemoteCallToBaseMethod(Log, td, cmd, ref WeavingFailed); + return cmd; + } + + // For a function like + // [ClientRpc] void RpcTest(int value), + // Weaver substitutes the method and moves the code to a new method: + // UserCode_RpcTest(int value) <- contains original code + // RpcTest(int value) <- serializes parameters, sends the message + // + // FixRemoteCallToBaseMethod replaces all calls to + // RpcTest(value) + // with + // UserCode_RpcTest(value) + public static void FixRemoteCallToBaseMethod(Logger Log, TypeDefinition type, MethodDefinition method, ref bool WeavingFailed) + { + string callName = method.Name; + + // Cmd/rpc start with Weaver.RpcPrefix + // e.g. CallCmdDoSomething + if (!callName.StartsWith(RpcPrefix)) + return; + + // e.g. CmdDoSomething + string baseRemoteCallName = method.Name.Substring(RpcPrefix.Length); + + foreach (Instruction instruction in method.Body.Instructions) + { + // is this instruction a Call to a method? + // if yes, output the method so we can check it. + if (IsCallToMethod(instruction, out MethodDefinition calledMethod)) + { + // when considering if 'calledMethod' is a call to 'method', + // we originally compared .Name. + // + // to fix IL2CPP build bugs with overloaded Rpcs, we need to + // generated rpc names like + // RpcTest(string value) => RpcTestString(strig value) + // RpcTest(int value) => RpcTestInt(int value) + // to make them unique. + // + // calledMethod.Name is still "RpcTest", so we need to + // convert this to the generated name as well before comparing. + string calledMethodName_Generated = Weaver.GenerateMethodName("", calledMethod); + if (calledMethodName_Generated == baseRemoteCallName) + { + TypeDefinition baseType = type.BaseType.Resolve(); + MethodDefinition baseMethod = baseType.GetMethodInBaseType(callName); + + if (baseMethod == null) + { + Log.Error($"Could not find base method for {callName}", method); + WeavingFailed = true; + return; + } + + if (!baseMethod.IsVirtual) + { + Log.Error($"Could not find base method that was virtual {callName}", method); + WeavingFailed = true; + return; + } + + instruction.Operand = baseMethod; + } + } + } + } + + static bool IsCallToMethod(Instruction instruction, out MethodDefinition calledMethod) + { + if (instruction.OpCode == OpCodes.Call && + instruction.Operand is MethodDefinition method) + { + calledMethod = method; + return true; + } + else + { + calledMethod = null; + return false; + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs.meta new file mode 100644 index 0000000..3c81894 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 661e1af528e3441f79e1552fb5ec4e0e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs new file mode 100644 index 0000000..e88c5d6 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs @@ -0,0 +1,56 @@ +using Mono.CecilX; + +namespace Mirror.Weaver +{ + // only shows warnings in case we use SyncVars etc. for MonoBehaviour. + static class MonoBehaviourProcessor + { + public static void Process(Logger Log, TypeDefinition td, ref bool WeavingFailed) + { + ProcessSyncVars(Log, td, ref WeavingFailed); + ProcessMethods(Log, td, ref WeavingFailed); + } + + static void ProcessSyncVars(Logger Log, TypeDefinition td, ref bool WeavingFailed) + { + // find syncvars + foreach (FieldDefinition fd in td.Fields) + { + if (fd.HasCustomAttribute()) + { + Log.Error($"SyncVar {fd.Name} must be inside a NetworkBehaviour. {td.Name} is not a NetworkBehaviour", fd); + WeavingFailed = true; + } + + if (SyncObjectInitializer.ImplementsSyncObject(fd.FieldType)) + { + Log.Error($"{fd.Name} is a SyncObject and must be inside a NetworkBehaviour. {td.Name} is not a NetworkBehaviour", fd); + WeavingFailed = true; + } + } + } + + static void ProcessMethods(Logger Log, TypeDefinition td, ref bool WeavingFailed) + { + // find command and RPC functions + foreach (MethodDefinition md in td.Methods) + { + if (md.HasCustomAttribute()) + { + Log.Error($"Command {md.Name} must be declared inside a NetworkBehaviour", md); + WeavingFailed = true; + } + if (md.HasCustomAttribute()) + { + Log.Error($"ClientRpc {md.Name} must be declared inside a NetworkBehaviour", md); + WeavingFailed = true; + } + if (md.HasCustomAttribute()) + { + Log.Error($"TargetRpc {md.Name} must be declared inside a NetworkBehaviour", md); + WeavingFailed = true; + } + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs.meta new file mode 100644 index 0000000..ef3f5f4 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 35c16722912b64af894e4f6668f2e54c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs new file mode 100644 index 0000000..47f1b94 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs @@ -0,0 +1,1055 @@ +using System.Collections.Generic; +using Mono.CecilX; +using Mono.CecilX.Cil; + +namespace Mirror.Weaver +{ + public enum RemoteCallType + { + Command, + ClientRpc, + TargetRpc + } + + // processes SyncVars, Cmds, Rpcs, etc. of NetworkBehaviours + class NetworkBehaviourProcessor + { + AssemblyDefinition assembly; + WeaverTypes weaverTypes; + SyncVarAccessLists syncVarAccessLists; + SyncVarAttributeProcessor syncVarAttributeProcessor; + Writers writers; + Readers readers; + Logger Log; + + List syncVars = new List(); + List syncObjects = new List(); + // + Dictionary syncVarNetIds = new Dictionary(); + // - Every syncvar with a hook has a new field created to store the Action delegate so we don't allocate on every hook invocation + // This dictionary maps each syncvar field to the field that will store the hook method delegate instance, and the method from which the delegate instance is constructed from + Dictionary syncVarHookDelegates = new Dictionary(); + readonly List commands = new List(); + readonly List clientRpcs = new List(); + readonly List targetRpcs = new List(); + readonly List commandInvocationFuncs = new List(); + readonly List clientRpcInvocationFuncs = new List(); + readonly List targetRpcInvocationFuncs = new List(); + + readonly TypeDefinition netBehaviourSubclass; + + public struct CmdResult + { + public MethodDefinition method; + public bool requiresAuthority; + } + + public struct ClientRpcResult + { + public MethodDefinition method; + public bool includeOwner; + } + + public NetworkBehaviourProcessor(AssemblyDefinition assembly, WeaverTypes weaverTypes, SyncVarAccessLists syncVarAccessLists, Writers writers, Readers readers, Logger Log, TypeDefinition td) + { + this.assembly = assembly; + this.weaverTypes = weaverTypes; + this.syncVarAccessLists = syncVarAccessLists; + this.writers = writers; + this.readers = readers; + this.Log = Log; + syncVarAttributeProcessor = new SyncVarAttributeProcessor(assembly, weaverTypes, syncVarAccessLists, Log); + netBehaviourSubclass = td; + } + + // return true if modified + public bool Process(ref bool WeavingFailed) + { + // only process once + if (WasProcessed(netBehaviourSubclass)) + { + return false; + } + + MarkAsProcessed(netBehaviourSubclass); + + // deconstruct tuple and set fields + (syncVars, syncVarNetIds, syncVarHookDelegates) = syncVarAttributeProcessor.ProcessSyncVars(netBehaviourSubclass, ref WeavingFailed); + + syncObjects = SyncObjectProcessor.FindSyncObjectsFields(writers, readers, Log, netBehaviourSubclass, ref WeavingFailed); + + ProcessMethods(ref WeavingFailed); + if (WeavingFailed) + { + // originally Process returned true in every case, except if already processed. + // maybe return false here in the future. + return true; + } + + // inject initializations into static & instance constructor + InjectIntoStaticConstructor(ref WeavingFailed); + InjectIntoInstanceConstructor(ref WeavingFailed); + + GenerateSerialization(ref WeavingFailed); + if (WeavingFailed) + { + // originally Process returned true in every case, except if already processed. + // maybe return false here in the future. + return true; + } + + GenerateDeSerialization(ref WeavingFailed); + return true; + } + + /* + generates code like: + if (!NetworkClient.active) + Debug.LogError((object) "Command function CmdRespawn called on server."); + + which is used in InvokeCmd, InvokeRpc, etc. + */ + public static void WriteClientActiveCheck(ILProcessor worker, WeaverTypes weaverTypes, string mdName, Instruction label, string errString) + { + // client active check + worker.Emit(OpCodes.Call, weaverTypes.NetworkClientGetActive); + worker.Emit(OpCodes.Brtrue, label); + + worker.Emit(OpCodes.Ldstr, $"{errString} {mdName} called on server."); + worker.Emit(OpCodes.Call, weaverTypes.logErrorReference); + worker.Emit(OpCodes.Ret); + worker.Append(label); + } + /* + generates code like: + if (!NetworkServer.active) + Debug.LogError((object) "Command CmdMsgWhisper called on client."); + */ + public static void WriteServerActiveCheck(ILProcessor worker, WeaverTypes weaverTypes, string mdName, Instruction label, string errString) + { + // server active check + worker.Emit(OpCodes.Call, weaverTypes.NetworkServerGetActive); + worker.Emit(OpCodes.Brtrue, label); + + worker.Emit(OpCodes.Ldstr, $"{errString} {mdName} called on client."); + worker.Emit(OpCodes.Call, weaverTypes.logErrorReference); + worker.Emit(OpCodes.Ret); + worker.Append(label); + } + + public static void WriteSetupLocals(ILProcessor worker, WeaverTypes weaverTypes) + { + worker.Body.InitLocals = true; + worker.Body.Variables.Add(new VariableDefinition(weaverTypes.Import())); + } + + public static void WriteGetWriter(ILProcessor worker, WeaverTypes weaverTypes) + { + // create writer + worker.Emit(OpCodes.Call, weaverTypes.GetWriterReference); + worker.Emit(OpCodes.Stloc_0); + } + + public static void WriteReturnWriter(ILProcessor worker, WeaverTypes weaverTypes) + { + // NetworkWriterPool.Recycle(writer); + worker.Emit(OpCodes.Ldloc_0); + worker.Emit(OpCodes.Call, weaverTypes.ReturnWriterReference); + } + + public static bool WriteArguments(ILProcessor worker, Writers writers, Logger Log, MethodDefinition method, RemoteCallType callType, ref bool WeavingFailed) + { + // write each argument + // example result + /* + writer.WritePackedInt32(someNumber); + writer.WriteNetworkIdentity(someTarget); + */ + + bool skipFirst = callType == RemoteCallType.TargetRpc + && TargetRpcProcessor.HasNetworkConnectionParameter(method); + + // arg of calling function, arg 0 is "this" so start counting at 1 + int argNum = 1; + foreach (ParameterDefinition param in method.Parameters) + { + // NetworkConnection is not sent via the NetworkWriter so skip it here + // skip first for NetworkConnection in TargetRpc + if (argNum == 1 && skipFirst) + { + argNum += 1; + continue; + } + // skip SenderConnection in Command + if (IsSenderConnection(param, callType)) + { + argNum += 1; + continue; + } + + MethodReference writeFunc = writers.GetWriteFunc(param.ParameterType, ref WeavingFailed); + if (writeFunc == null) + { + Log.Error($"{method.Name} has invalid parameter {param}", method); + WeavingFailed = true; + return false; + } + + // use built-in writer func on writer object + // NetworkWriter object + worker.Emit(OpCodes.Ldloc_0); + // add argument to call + worker.Emit(OpCodes.Ldarg, argNum); + // call writer extension method + worker.Emit(OpCodes.Call, writeFunc); + argNum += 1; + } + return true; + } + + #region mark / check type as processed + public const string ProcessedFunctionName = "Weaved"; + + // check if the type has a "Weaved" function already + public static bool WasProcessed(TypeDefinition td) + { + return td.GetMethod(ProcessedFunctionName) != null; + } + + // add the Weaved() function which returns true. + // can be called at runtime and from tests to check if weaving succeeded. + public void MarkAsProcessed(TypeDefinition td) + { + if (!WasProcessed(td)) + { + // add a function: + // public override bool MirrorProcessed() { return true; } + // ReuseSlot means 'override'. + MethodDefinition versionMethod = new MethodDefinition( + ProcessedFunctionName, + MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, + weaverTypes.Import(typeof(bool))); + ILProcessor worker = versionMethod.Body.GetILProcessor(); + worker.Emit(OpCodes.Ldc_I4_1); + worker.Emit(OpCodes.Ret); + td.Methods.Add(versionMethod); + } + } + #endregion + + // helper function to remove 'Ret' from the end of the method if 'Ret' + // is the last instruction. + // returns false if there was an issue + static bool RemoveFinalRetInstruction(MethodDefinition method) + { + // remove the return opcode from end of function. will add our own later. + if (method.Body.Instructions.Count != 0) + { + Instruction retInstr = method.Body.Instructions[method.Body.Instructions.Count - 1]; + if (retInstr.OpCode == OpCodes.Ret) + { + method.Body.Instructions.RemoveAt(method.Body.Instructions.Count - 1); + return true; + } + return false; + } + + // we did nothing, but there was no error. + return true; + } + + // we need to inject several initializations into NetworkBehaviour cctor + void InjectIntoStaticConstructor(ref bool WeavingFailed) + { + if (commands.Count == 0 && clientRpcs.Count == 0 && targetRpcs.Count == 0) + return; + + // find static constructor + MethodDefinition cctor = netBehaviourSubclass.GetMethod(".cctor"); + bool cctorFound = cctor != null; + if (cctor != null) + { + // remove the return opcode from end of function. will add our own later. + if (!RemoveFinalRetInstruction(cctor)) + { + Log.Error($"{netBehaviourSubclass.Name} has invalid class constructor", cctor); + WeavingFailed = true; + return; + } + } + else + { + // make one! + cctor = new MethodDefinition(".cctor", MethodAttributes.Private | + MethodAttributes.HideBySig | + MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName | + MethodAttributes.Static, + weaverTypes.Import(typeof(void))); + } + + ILProcessor cctorWorker = cctor.Body.GetILProcessor(); + + // register all commands in cctor + for (int i = 0; i < commands.Count; ++i) + { + CmdResult cmdResult = commands[i]; + GenerateRegisterCommandDelegate(cctorWorker, weaverTypes.registerCommandReference, commandInvocationFuncs[i], cmdResult); + } + + // register all client rpcs in cctor + for (int i = 0; i < clientRpcs.Count; ++i) + { + ClientRpcResult clientRpcResult = clientRpcs[i]; + GenerateRegisterRemoteDelegate(cctorWorker, weaverTypes.registerRpcReference, clientRpcInvocationFuncs[i], clientRpcResult.method.FullName); + } + + // register all target rpcs in cctor + for (int i = 0; i < targetRpcs.Count; ++i) + { + GenerateRegisterRemoteDelegate(cctorWorker, weaverTypes.registerRpcReference, targetRpcInvocationFuncs[i], targetRpcs[i].FullName); + } + + // add final 'Ret' instruction to cctor + cctorWorker.Append(cctorWorker.Create(OpCodes.Ret)); + if (!cctorFound) + { + netBehaviourSubclass.Methods.Add(cctor); + } + + // in case class had no cctor, it might have BeforeFieldInit, so injected cctor would be called too late + netBehaviourSubclass.Attributes &= ~TypeAttributes.BeforeFieldInit; + } + + // we need to inject several initializations into NetworkBehaviour ctor + void InjectIntoInstanceConstructor(ref bool WeavingFailed) + { + if ((syncObjects.Count == 0) && (syncVarHookDelegates.Count == 0)) + return; + + // find instance constructor + MethodDefinition ctor = netBehaviourSubclass.GetMethod(".ctor"); + if (ctor == null) + { + Log.Error($"{netBehaviourSubclass.Name} has invalid constructor", netBehaviourSubclass); + WeavingFailed = true; + return; + } + + // remove the return opcode from end of function. will add our own later. + if (!RemoveFinalRetInstruction(ctor)) + { + Log.Error($"{netBehaviourSubclass.Name} has invalid constructor", ctor); + WeavingFailed = true; + return; + } + + ILProcessor ctorWorker = ctor.Body.GetILProcessor(); + + // initialize all sync objects in ctor + foreach (FieldDefinition fd in syncObjects) + { + SyncObjectInitializer.GenerateSyncObjectInitializer(ctorWorker, weaverTypes, fd); + } + + // initialize all delegate fields in ctor + foreach(KeyValuePair entry in syncVarHookDelegates) + { + FieldDefinition syncVarField = entry.Key; + (FieldDefinition hookDelegate, MethodDefinition hookMethod) = entry.Value; + syncVarAttributeProcessor.GenerateSyncVarHookDelegateInitializer(ctorWorker, syncVarField, hookDelegate, hookMethod); + } + + // add final 'Ret' instruction to ctor + ctorWorker.Append(ctorWorker.Create(OpCodes.Ret)); + } + + /* + // This generates code like: + NetworkBehaviour.RegisterCommandDelegate(base.GetType(), "CmdThrust", new NetworkBehaviour.CmdDelegate(ShipControl.InvokeCmdCmdThrust)); + */ + + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + void GenerateRegisterRemoteDelegate(ILProcessor worker, MethodReference registerMethod, MethodDefinition func, string functionFullName) + { + worker.Emit(OpCodes.Ldtoken, netBehaviourSubclass); + worker.Emit(OpCodes.Call, weaverTypes.getTypeFromHandleReference); + worker.Emit(OpCodes.Ldstr, functionFullName); + worker.Emit(OpCodes.Ldnull); + worker.Emit(OpCodes.Ldftn, func); + + worker.Emit(OpCodes.Newobj, weaverTypes.RemoteCallDelegateConstructor); + // + worker.Emit(OpCodes.Call, registerMethod); + } + + void GenerateRegisterCommandDelegate(ILProcessor worker, MethodReference registerMethod, MethodDefinition func, CmdResult cmdResult) + { + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + string cmdName = cmdResult.method.FullName; + bool requiresAuthority = cmdResult.requiresAuthority; + + worker.Emit(OpCodes.Ldtoken, netBehaviourSubclass); + worker.Emit(OpCodes.Call, weaverTypes.getTypeFromHandleReference); + worker.Emit(OpCodes.Ldstr, cmdName); + worker.Emit(OpCodes.Ldnull); + worker.Emit(OpCodes.Ldftn, func); + + worker.Emit(OpCodes.Newobj, weaverTypes.RemoteCallDelegateConstructor); + + // requiresAuthority ? 1 : 0 + worker.Emit(requiresAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + + worker.Emit(OpCodes.Call, registerMethod); + } + + void GenerateSerialization(ref bool WeavingFailed) + { + const string SerializeMethodName = "SerializeSyncVars"; + if (netBehaviourSubclass.GetMethod(SerializeMethodName) != null) + return; + + if (syncVars.Count == 0) + { + // no synvars, no need for custom OnSerialize + return; + } + + MethodDefinition serialize = new MethodDefinition(SerializeMethodName, + MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, + weaverTypes.Import(typeof(void))); + + serialize.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, weaverTypes.Import())); + serialize.Parameters.Add(new ParameterDefinition("forceAll", ParameterAttributes.None, weaverTypes.Import())); + ILProcessor worker = serialize.Body.GetILProcessor(); + + serialize.Body.InitLocals = true; + + // base.SerializeSyncVars(writer, forceAll); + MethodReference baseSerialize = Resolvers.TryResolveMethodInParents(netBehaviourSubclass.BaseType, assembly, SerializeMethodName); + if (baseSerialize != null) + { + // base + worker.Emit(OpCodes.Ldarg_0); + // writer + worker.Emit(OpCodes.Ldarg_1); + // forceAll + worker.Emit(OpCodes.Ldarg_2); + worker.Emit(OpCodes.Call, baseSerialize); + } + + // Generates: + // if (forceAll) + // { + // writer.WriteInt(health); + // ... + // } + Instruction initialStateLabel = worker.Create(OpCodes.Nop); + // forceAll + worker.Emit(OpCodes.Ldarg_2); // load 'forceAll' flag + worker.Emit(OpCodes.Brfalse, initialStateLabel); // start the 'if forceAll' branch + + // generates write.Write(syncVar) for each SyncVar in forceAll case + foreach (FieldDefinition syncVarDef in syncVars) + { + FieldReference syncVar = syncVarDef; + if (netBehaviourSubclass.HasGenericParameters) + { + syncVar = syncVarDef.MakeHostInstanceGeneric(); + } + // Generates a writer call for each sync variable + // writer + worker.Emit(OpCodes.Ldarg_1); + // this + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, syncVar); + MethodReference writeFunc; + // For NBs we always need to use the default NetworkBehaviour write func + // since the reader counter part uses that exact layout which is not easy to change + // without introducing more edge cases + // effectively this disallows custom NB-type writers/readers on SyncVars + // see: https://github.com/MirrorNetworking/Mirror/issues/2680 + if (syncVar.FieldType.IsDerivedFrom()) + { + writeFunc = writers.GetWriteFunc(weaverTypes.Import(), ref WeavingFailed); + } + else + { + writeFunc = writers.GetWriteFunc(syncVar.FieldType, ref WeavingFailed); + } + + if (writeFunc != null) + { + worker.Emit(OpCodes.Call, writeFunc); + } + else + { + Log.Error($"{syncVar.Name} has unsupported type. Use a supported Mirror type instead", syncVar); + WeavingFailed = true; + return; + } + } + + // if (forceAll) then always return at the end of the 'if' case + worker.Emit(OpCodes.Ret); + + // end the 'if' case for "if (forceAll)" + worker.Append(initialStateLabel); + + //////////////////////////////////////////////////////////////////// + + // write dirty bits before the data fields + // Generates: writer.WritePackedUInt64 (base.get_syncVarDirtyBits ()); + // writer + worker.Emit(OpCodes.Ldarg_1); + // base + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, weaverTypes.NetworkBehaviourDirtyBitsReference); + MethodReference writeUint64Func = writers.GetWriteFunc(weaverTypes.Import(), ref WeavingFailed); + worker.Emit(OpCodes.Call, writeUint64Func); + + // generate a writer call for any dirty variable in this class + + // start at number of syncvars in parent + int dirtyBit = syncVarAccessLists.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName); + foreach (FieldDefinition syncVarDef in syncVars) + { + FieldReference syncVar = syncVarDef; + if (netBehaviourSubclass.HasGenericParameters) + { + syncVar = syncVarDef.MakeHostInstanceGeneric(); + } + Instruction varLabel = worker.Create(OpCodes.Nop); + + // Generates: if ((base.get_syncVarDirtyBits() & 1uL) != 0uL) + // base + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, weaverTypes.NetworkBehaviourDirtyBitsReference); + // 8 bytes = long + worker.Emit(OpCodes.Ldc_I8, 1L << dirtyBit); + worker.Emit(OpCodes.And); + worker.Emit(OpCodes.Brfalse, varLabel); + + // Generates a call to the writer for that field + // writer + worker.Emit(OpCodes.Ldarg_1); + // base + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, syncVar); + + MethodReference writeFunc; + // For NBs we always need to use the default NetworkBehaviour write func + // since the reader counter part uses that exact layout which is not easy to change + // without introducing more edge cases + // effectively this disallows custom NB-type writers/readers on SyncVars + // see: https://github.com/MirrorNetworking/Mirror/issues/2680 + if (syncVar.FieldType.IsDerivedFrom()) + { + writeFunc = writers.GetWriteFunc(weaverTypes.Import(), ref WeavingFailed); + } + else + { + writeFunc = writers.GetWriteFunc(syncVar.FieldType, ref WeavingFailed); + } + + if (writeFunc != null) + { + worker.Emit(OpCodes.Call, writeFunc); + } + else + { + Log.Error($"{syncVar.Name} has unsupported type. Use a supported Mirror type instead", syncVar); + WeavingFailed = true; + return; + } + + worker.Append(varLabel); + dirtyBit += 1; + } + + // add a log message if needed for debugging + //worker.Emit(OpCodes.Ldstr, $"Injected Serialize {netBehaviourSubclass.Name}"); + //worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference); + + // generate: return + worker.Emit(OpCodes.Ret); + netBehaviourSubclass.Methods.Add(serialize); + } + + void DeserializeField(FieldDefinition syncVar, ILProcessor worker, ref bool WeavingFailed) + { + // put 'this.' onto stack for 'this.syncvar' below + worker.Append(worker.Create(OpCodes.Ldarg_0)); + + // push 'ref T this.field' + worker.Emit(OpCodes.Ldarg_0); + // if the netbehaviour class is generic, we need to make the field reference generic as well for correct IL + if (netBehaviourSubclass.HasGenericParameters) + { + worker.Emit(OpCodes.Ldflda, syncVar.MakeHostInstanceGeneric()); + } + else + { + worker.Emit(OpCodes.Ldflda, syncVar); + } + + // If a hook exists, then we need to load the hook delegate on the stack + // The hook delegate is created once in the constructor and stored in an instance field + // We load the delegate from this instance field to avoid instantiating a new delegate instance every time (drastically reduces allocations) + if(syncVarHookDelegates.TryGetValue(syncVar, out (FieldDefinition hookDelegateField, MethodDefinition) value)) + { + // A hook exists. Push this.hookDelegateField onto the stack + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, value.hookDelegateField); + } + else + { + // No hook exists. Push 'null' as hook + worker.Emit(OpCodes.Ldnull); + } + + // call GeneratedSyncVarDeserialize. + // special cases for GameObject/NetworkIdentity/NetworkBehaviour + // passing netId too for persistence. + if (syncVar.FieldType.Is()) + { + // reader + worker.Emit(OpCodes.Ldarg_1); + + // GameObject setter needs one more parameter: netId field ref + FieldDefinition netIdField = syncVarNetIds[syncVar]; + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, netIdField); + worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarDeserialize_GameObject); + } + else if (syncVar.FieldType.Is()) + { + // reader + worker.Emit(OpCodes.Ldarg_1); + + // NetworkIdentity deserialize needs one more parameter: netId field ref + FieldDefinition netIdField = syncVarNetIds[syncVar]; + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, netIdField); + worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarDeserialize_NetworkIdentity); + } + // handle both NetworkBehaviour and inheritors. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/2939 + else if (syncVar.FieldType.IsDerivedFrom() || syncVar.FieldType.Is()) + { + // reader + worker.Emit(OpCodes.Ldarg_1); + + // NetworkIdentity deserialize needs one more parameter: netId field ref + // (actually its a NetworkBehaviourSyncVar type) + FieldDefinition netIdField = syncVarNetIds[syncVar]; + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, netIdField); + // make generic version of GeneratedSyncVarSetter_NetworkBehaviour + MethodReference getFunc = weaverTypes.generatedSyncVarDeserialize_NetworkBehaviour_T.MakeGeneric(assembly.MainModule, syncVar.FieldType); + worker.Emit(OpCodes.Call, getFunc); + } + else + { + // T value = reader.ReadT(); + // this is still in IL because otherwise weaver generated + // readers/writers don't seem to work in tests. + // besides, this also avoids reader.Read overhead. + MethodReference readFunc = readers.GetReadFunc(syncVar.FieldType, ref WeavingFailed); + if (readFunc == null) + { + Log.Error($"{syncVar.Name} has unsupported type. Use a supported Mirror type instead", syncVar); + WeavingFailed = true; + return; + } + // reader. for 'reader.Read()' below + worker.Emit(OpCodes.Ldarg_1); + // reader.Read() + worker.Emit(OpCodes.Call, readFunc); + + // make generic version of GeneratedSyncVarDeserialize + MethodReference generic = weaverTypes.generatedSyncVarDeserialize.MakeGeneric(assembly.MainModule, syncVar.FieldType); + worker.Emit(OpCodes.Call, generic); + } + } + + void GenerateDeSerialization(ref bool WeavingFailed) + { + const string DeserializeMethodName = "DeserializeSyncVars"; + if (netBehaviourSubclass.GetMethod(DeserializeMethodName) != null) + return; + + if (syncVars.Count == 0) + { + // no synvars, no need for custom OnDeserialize + return; + } + + MethodDefinition serialize = new MethodDefinition(DeserializeMethodName, + MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, + weaverTypes.Import(typeof(void))); + + serialize.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, weaverTypes.Import())); + serialize.Parameters.Add(new ParameterDefinition("initialState", ParameterAttributes.None, weaverTypes.Import())); + ILProcessor serWorker = serialize.Body.GetILProcessor(); + // setup local for dirty bits + serialize.Body.InitLocals = true; + VariableDefinition dirtyBitsLocal = new VariableDefinition(weaverTypes.Import()); + serialize.Body.Variables.Add(dirtyBitsLocal); + + MethodReference baseDeserialize = Resolvers.TryResolveMethodInParents(netBehaviourSubclass.BaseType, assembly, DeserializeMethodName); + if (baseDeserialize != null) + { + // base + serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); + // reader + serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); + // initialState + serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); + serWorker.Append(serWorker.Create(OpCodes.Call, baseDeserialize)); + } + + // Generates: if (initialState); + Instruction initialStateLabel = serWorker.Create(OpCodes.Nop); + + serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); + serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel)); + + foreach (FieldDefinition syncVar in syncVars) + { + DeserializeField(syncVar, serWorker, ref WeavingFailed); + } + + serWorker.Append(serWorker.Create(OpCodes.Ret)); + + // Generates: end if (initialState); + serWorker.Append(initialStateLabel); + + // get dirty bits + serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); + serWorker.Append(serWorker.Create(OpCodes.Call, readers.GetReadFunc(weaverTypes.Import(), ref WeavingFailed))); + serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); + + // conditionally read each syncvar + // start at number of syncvars in parent + int dirtyBit = syncVarAccessLists.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName); + foreach (FieldDefinition syncVar in syncVars) + { + Instruction varLabel = serWorker.Create(OpCodes.Nop); + + // check if dirty bit is set + serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); + serWorker.Append(serWorker.Create(OpCodes.Ldc_I8, 1L << dirtyBit)); + serWorker.Append(serWorker.Create(OpCodes.And)); + serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel)); + + DeserializeField(syncVar, serWorker, ref WeavingFailed); + + serWorker.Append(varLabel); + dirtyBit += 1; + } + + // add a log message if needed for debugging + //serWorker.Append(serWorker.Create(OpCodes.Ldstr, $"Injected Deserialize {netBehaviourSubclass.Name}")); + //serWorker.Append(serWorker.Create(OpCodes.Call, WeaverTypes.logErrorReference)); + + serWorker.Append(serWorker.Create(OpCodes.Ret)); + netBehaviourSubclass.Methods.Add(serialize); + } + + public static bool ReadArguments(MethodDefinition method, Readers readers, Logger Log, ILProcessor worker, RemoteCallType callType, ref bool WeavingFailed) + { + // read each argument + // example result + /* + CallCmdDoSomething(reader.ReadPackedInt32(), reader.ReadNetworkIdentity()); + */ + + bool skipFirst = callType == RemoteCallType.TargetRpc + && TargetRpcProcessor.HasNetworkConnectionParameter(method); + + // arg of calling function, arg 0 is "this" so start counting at 1 + int argNum = 1; + foreach (ParameterDefinition param in method.Parameters) + { + // NetworkConnection is not sent via the NetworkWriter so skip it here + // skip first for NetworkConnection in TargetRpc + if (argNum == 1 && skipFirst) + { + argNum += 1; + continue; + } + // skip SenderConnection in Command + if (IsSenderConnection(param, callType)) + { + argNum += 1; + continue; + } + + + MethodReference readFunc = readers.GetReadFunc(param.ParameterType, ref WeavingFailed); + + if (readFunc == null) + { + Log.Error($"{method.Name} has invalid parameter {param}. Unsupported type {param.ParameterType}, use a supported Mirror type instead", method); + WeavingFailed = true; + return false; + } + + worker.Emit(OpCodes.Ldarg_1); + worker.Emit(OpCodes.Call, readFunc); + + // conversion.. is this needed? + if (param.ParameterType.Is()) + { + worker.Emit(OpCodes.Conv_R4); + } + else if (param.ParameterType.Is()) + { + worker.Emit(OpCodes.Conv_R8); + } + } + return true; + } + + public static void AddInvokeParameters(WeaverTypes weaverTypes, ICollection collection) + { + collection.Add(new ParameterDefinition("obj", ParameterAttributes.None, weaverTypes.Import())); + collection.Add(new ParameterDefinition("reader", ParameterAttributes.None, weaverTypes.Import())); + // senderConnection is only used for commands but NetworkBehaviour.CmdDelegate is used for all remote calls + collection.Add(new ParameterDefinition("senderConnection", ParameterAttributes.None, weaverTypes.Import())); + } + + // check if a Command/TargetRpc/Rpc function & parameters are valid for weaving + public bool ValidateRemoteCallAndParameters(MethodDefinition method, RemoteCallType callType, ref bool WeavingFailed) + { + if (method.IsStatic) + { + Log.Error($"{method.Name} must not be static", method); + WeavingFailed = true; + return false; + } + + return ValidateFunction(method, ref WeavingFailed) && + ValidateParameters(method, callType, ref WeavingFailed); + } + + // check if a Command/TargetRpc/Rpc function is valid for weaving + bool ValidateFunction(MethodReference md, ref bool WeavingFailed) + { + if (md.ReturnType.Is()) + { + Log.Error($"{md.Name} cannot be a coroutine", md); + WeavingFailed = true; + return false; + } + if (!md.ReturnType.Is(typeof(void))) + { + Log.Error($"{md.Name} cannot return a value. Make it void instead", md); + WeavingFailed = true; + return false; + } + if (md.HasGenericParameters) + { + Log.Error($"{md.Name} cannot have generic parameters", md); + WeavingFailed = true; + return false; + } + return true; + } + + // check if all Command/TargetRpc/Rpc function's parameters are valid for weaving + bool ValidateParameters(MethodReference method, RemoteCallType callType, ref bool WeavingFailed) + { + for (int i = 0; i < method.Parameters.Count; ++i) + { + ParameterDefinition param = method.Parameters[i]; + if (!ValidateParameter(method, param, callType, i == 0, ref WeavingFailed)) + { + return false; + } + } + return true; + } + + // validate parameters for a remote function call like Rpc/Cmd + bool ValidateParameter(MethodReference method, ParameterDefinition param, RemoteCallType callType, bool firstParam, ref bool WeavingFailed) + { + // need to check this before any type lookups since those will fail since generic types don't resolve + if (param.ParameterType.IsGenericParameter) + { + Log.Error($"{method.Name} cannot have generic parameters", method); + WeavingFailed = true; + return false; + } + + bool isNetworkConnection = param.ParameterType.Is(); + bool isSenderConnection = IsSenderConnection(param, callType); + + if (param.IsOut) + { + Log.Error($"{method.Name} cannot have out parameters", method); + WeavingFailed = true; + return false; + } + + // if not SenderConnection And not TargetRpc NetworkConnection first param + if (!isSenderConnection && isNetworkConnection && !(callType == RemoteCallType.TargetRpc && firstParam)) + { + if (callType == RemoteCallType.Command) + { + Log.Error($"{method.Name} has invalid parameter {param}, Cannot pass NetworkConnections. Instead use 'NetworkConnectionToClient conn = null' to get the sender's connection on the server", method); + } + else + { + Log.Error($"{method.Name} has invalid parameter {param}. Cannot pass NetworkConnections", method); + } + WeavingFailed = true; + return false; + } + + // sender connection can be optional + if (param.IsOptional && !isSenderConnection) + { + Log.Error($"{method.Name} cannot have optional parameters", method); + WeavingFailed = true; + return false; + } + + return true; + } + + public static bool IsSenderConnection(ParameterDefinition param, RemoteCallType callType) + { + if (callType != RemoteCallType.Command) + { + return false; + } + + TypeReference type = param.ParameterType; + + return type.Is() + || type.Resolve().IsDerivedFrom(); + } + + void ProcessMethods(ref bool WeavingFailed) + { + HashSet names = new HashSet(); + + // copy the list of methods because we will be adding methods in the loop + List methods = new List(netBehaviourSubclass.Methods); + // find command and RPC functions + foreach (MethodDefinition md in methods) + { + foreach (CustomAttribute ca in md.CustomAttributes) + { + if (ca.AttributeType.Is()) + { + ProcessCommand(names, md, ca, ref WeavingFailed); + break; + } + + if (ca.AttributeType.Is()) + { + ProcessTargetRpc(names, md, ca, ref WeavingFailed); + break; + } + + if (ca.AttributeType.Is()) + { + ProcessClientRpc(names, md, ca, ref WeavingFailed); + break; + } + } + } + } + + void ProcessClientRpc(HashSet names, MethodDefinition md, CustomAttribute clientRpcAttr, ref bool WeavingFailed) + { + if (md.IsAbstract) + { + Log.Error("Abstract ClientRpc are currently not supported, use virtual method instead", md); + WeavingFailed = true; + return; + } + + if (!ValidateRemoteCallAndParameters(md, RemoteCallType.ClientRpc, ref WeavingFailed)) + { + return; + } + + bool includeOwner = clientRpcAttr.GetField("includeOwner", true); + + names.Add(md.Name); + clientRpcs.Add(new ClientRpcResult + { + method = md, + includeOwner = includeOwner + }); + + MethodDefinition rpcCallFunc = RpcProcessor.ProcessRpcCall(weaverTypes, writers, Log, netBehaviourSubclass, md, clientRpcAttr, ref WeavingFailed); + // need null check here because ProcessRpcCall returns null if it can't write all the args + if (rpcCallFunc == null) { return; } + + MethodDefinition rpcFunc = RpcProcessor.ProcessRpcInvoke(weaverTypes, writers, readers, Log, netBehaviourSubclass, md, rpcCallFunc, ref WeavingFailed); + if (rpcFunc != null) + { + clientRpcInvocationFuncs.Add(rpcFunc); + } + } + + void ProcessTargetRpc(HashSet names, MethodDefinition md, CustomAttribute targetRpcAttr, ref bool WeavingFailed) + { + if (md.IsAbstract) + { + Log.Error("Abstract TargetRpc are currently not supported, use virtual method instead", md); + WeavingFailed = true; + return; + } + + if (!ValidateRemoteCallAndParameters(md, RemoteCallType.TargetRpc, ref WeavingFailed)) + return; + + names.Add(md.Name); + targetRpcs.Add(md); + + MethodDefinition rpcCallFunc = TargetRpcProcessor.ProcessTargetRpcCall(weaverTypes, writers, Log, netBehaviourSubclass, md, targetRpcAttr, ref WeavingFailed); + + MethodDefinition rpcFunc = TargetRpcProcessor.ProcessTargetRpcInvoke(weaverTypes, readers, Log, netBehaviourSubclass, md, rpcCallFunc, ref WeavingFailed); + if (rpcFunc != null) + { + targetRpcInvocationFuncs.Add(rpcFunc); + } + } + + void ProcessCommand(HashSet names, MethodDefinition md, CustomAttribute commandAttr, ref bool WeavingFailed) + { + if (md.IsAbstract) + { + Log.Error("Abstract Commands are currently not supported, use virtual method instead", md); + WeavingFailed = true; + return; + } + + if (!ValidateRemoteCallAndParameters(md, RemoteCallType.Command, ref WeavingFailed)) + return; + + bool requiresAuthority = commandAttr.GetField("requiresAuthority", true); + + names.Add(md.Name); + commands.Add(new CmdResult + { + method = md, + requiresAuthority = requiresAuthority + }); + + MethodDefinition cmdCallFunc = CommandProcessor.ProcessCommandCall(weaverTypes, writers, Log, netBehaviourSubclass, md, commandAttr, ref WeavingFailed); + + MethodDefinition cmdFunc = CommandProcessor.ProcessCommandInvoke(weaverTypes, readers, Log, netBehaviourSubclass, md, cmdCallFunc, ref WeavingFailed); + if (cmdFunc != null) + { + commandInvocationFuncs.Add(cmdFunc); + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs.meta new file mode 100644 index 0000000..67c27dc --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8118d606be3214e5d99943ec39530dd8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs new file mode 100644 index 0000000..280240c --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs @@ -0,0 +1,216 @@ +// finds all readers and writers and register them +using System.Linq; +using Mono.CecilX; +using Mono.CecilX.Cil; +using Mono.CecilX.Rocks; +using UnityEngine; + +namespace Mirror.Weaver +{ + public static class ReaderWriterProcessor + { + public static bool Process(AssemblyDefinition CurrentAssembly, IAssemblyResolver resolver, Logger Log, Writers writers, Readers readers, ref bool WeavingFailed) + { + // find NetworkReader/Writer extensions from Mirror.dll first. + // and NetworkMessage custom writer/reader extensions. + // NOTE: do not include this result in our 'modified' return value, + // otherwise Unity crashes when running tests + ProcessMirrorAssemblyClasses(CurrentAssembly, resolver, Log, writers, readers, ref WeavingFailed); + + // find readers/writers in the assembly we are in right now. + return ProcessAssemblyClasses(CurrentAssembly, CurrentAssembly, writers, readers, ref WeavingFailed); + } + + static void ProcessMirrorAssemblyClasses(AssemblyDefinition CurrentAssembly, IAssemblyResolver resolver, Logger Log, Writers writers, Readers readers, ref bool WeavingFailed) + { + // find Mirror.dll in assembly's references. + // those are guaranteed to be resolvable and correct. + // after all, it references them :) + AssemblyNameReference mirrorAssemblyReference = CurrentAssembly.MainModule.FindReference(Weaver.MirrorAssemblyName); + if (mirrorAssemblyReference != null) + { + // resolve the assembly to load the AssemblyDefinition. + // we need to search all types in it. + // if we only were to resolve one known type like in WeaverTypes, + // then we wouldn't need it. + AssemblyDefinition mirrorAssembly = resolver.Resolve(mirrorAssemblyReference); + if (mirrorAssembly != null) + { + ProcessAssemblyClasses(CurrentAssembly, mirrorAssembly, writers, readers, ref WeavingFailed); + } + else Log.Error($"Failed to resolve {mirrorAssemblyReference}"); + } + else Log.Error("Failed to find Mirror AssemblyNameReference. Can't register Mirror.dll readers/writers."); + } + + static bool ProcessAssemblyClasses(AssemblyDefinition CurrentAssembly, AssemblyDefinition assembly, Writers writers, Readers readers, ref bool WeavingFailed) + { + bool modified = false; + foreach (TypeDefinition klass in assembly.MainModule.Types) + { + // extension methods only live in static classes + // static classes are represented as sealed and abstract + if (klass.IsAbstract && klass.IsSealed) + { + // if assembly has any declared writers then it is "modified" + modified |= LoadDeclaredWriters(CurrentAssembly, klass, writers); + modified |= LoadDeclaredReaders(CurrentAssembly, klass, readers); + } + } + + foreach (TypeDefinition klass in assembly.MainModule.Types) + { + // if assembly has any network message then it is modified + modified |= LoadMessageReadWriter(CurrentAssembly.MainModule, writers, readers, klass, ref WeavingFailed); + } + return modified; + } + + static bool LoadMessageReadWriter(ModuleDefinition module, Writers writers, Readers readers, TypeDefinition klass, ref bool WeavingFailed) + { + bool modified = false; + if (!klass.IsAbstract && !klass.IsInterface && klass.ImplementsInterface()) + { + readers.GetReadFunc(module.ImportReference(klass), ref WeavingFailed); + writers.GetWriteFunc(module.ImportReference(klass), ref WeavingFailed); + modified = true; + } + + foreach (TypeDefinition td in klass.NestedTypes) + { + modified |= LoadMessageReadWriter(module, writers, readers, td, ref WeavingFailed); + } + return modified; + } + + static bool LoadDeclaredWriters(AssemblyDefinition currentAssembly, TypeDefinition klass, Writers writers) + { + // register all the writers in this class. Skip the ones with wrong signature + bool modified = false; + foreach (MethodDefinition method in klass.Methods) + { + if (method.Parameters.Count != 2) + continue; + + if (!method.Parameters[0].ParameterType.Is()) + continue; + + if (!method.ReturnType.Is(typeof(void))) + continue; + + if (!method.HasCustomAttribute()) + continue; + + if (method.HasGenericParameters) + continue; + + TypeReference dataType = method.Parameters[1].ParameterType; + writers.Register(dataType, currentAssembly.MainModule.ImportReference(method)); + modified = true; + } + return modified; + } + + static bool LoadDeclaredReaders(AssemblyDefinition currentAssembly, TypeDefinition klass, Readers readers) + { + // register all the reader in this class. Skip the ones with wrong signature + bool modified = false; + foreach (MethodDefinition method in klass.Methods) + { + if (method.Parameters.Count != 1) + continue; + + if (!method.Parameters[0].ParameterType.Is()) + continue; + + if (method.ReturnType.Is(typeof(void))) + continue; + + if (!method.HasCustomAttribute()) + continue; + + if (method.HasGenericParameters) + continue; + + readers.Register(method.ReturnType, currentAssembly.MainModule.ImportReference(method)); + modified = true; + } + return modified; + } + + // helper function to add [RuntimeInitializeOnLoad] attribute to method + static void AddRuntimeInitializeOnLoadAttribute(AssemblyDefinition assembly, WeaverTypes weaverTypes, MethodDefinition method) + { + // NOTE: previously we used reflection because according paul, + // 'weaving Mirror.dll caused unity to rebuild all dlls but in wrong + // order, which breaks rewired' + // it's not obvious why importing an attribute via reflection instead + // of cecil would break anything. let's use cecil. + + // to add a CustomAttribute, we need the attribute's constructor. + // in this case, there are two: empty, and RuntimeInitializeOnLoadType. + // we want the last one, with the type parameter. + MethodDefinition ctor = weaverTypes.runtimeInitializeOnLoadMethodAttribute.GetConstructors().Last(); + //MethodDefinition ctor = weaverTypes.runtimeInitializeOnLoadMethodAttribute.GetConstructors().First(); + // using ctor directly throws: ArgumentException: Member 'System.Void UnityEditor.InitializeOnLoadMethodAttribute::.ctor()' is declared in another module and needs to be imported + // we need to import it first. + CustomAttribute attribute = new CustomAttribute(assembly.MainModule.ImportReference(ctor)); + // add the RuntimeInitializeLoadType.BeforeSceneLoad argument to ctor + attribute.ConstructorArguments.Add(new CustomAttributeArgument(weaverTypes.Import(), RuntimeInitializeLoadType.BeforeSceneLoad)); + method.CustomAttributes.Add(attribute); + } + + // helper function to add [InitializeOnLoad] attribute to method + // (only works in Editor assemblies. check IsEditorAssembly first.) + static void AddInitializeOnLoadAttribute(AssemblyDefinition assembly, WeaverTypes weaverTypes, MethodDefinition method) + { + // NOTE: previously we used reflection because according paul, + // 'weaving Mirror.dll caused unity to rebuild all dlls but in wrong + // order, which breaks rewired' + // it's not obvious why importing an attribute via reflection instead + // of cecil would break anything. let's use cecil. + + // to add a CustomAttribute, we need the attribute's constructor. + // in this case, there's only one - and it's an empty constructor. + MethodDefinition ctor = weaverTypes.initializeOnLoadMethodAttribute.GetConstructors().First(); + // using ctor directly throws: ArgumentException: Member 'System.Void UnityEditor.InitializeOnLoadMethodAttribute::.ctor()' is declared in another module and needs to be imported + // we need to import it first. + CustomAttribute attribute = new CustomAttribute(assembly.MainModule.ImportReference(ctor)); + method.CustomAttributes.Add(attribute); + } + + // adds Mirror.GeneratedNetworkCode.InitReadWriters() method that + // registers all generated writers into Mirror.Writer static class. + // -> uses [RuntimeInitializeOnLoad] attribute so it's invoke at runtime + // -> uses [InitializeOnLoad] if UnityEditor is referenced so it works + // in Editor and in tests too + // + // use ILSpy to see the result (it's in the DLL's 'Mirror' namespace) + public static void InitializeReaderAndWriters(AssemblyDefinition currentAssembly, WeaverTypes weaverTypes, Writers writers, Readers readers, TypeDefinition GeneratedCodeClass) + { + MethodDefinition initReadWriters = new MethodDefinition("InitReadWriters", MethodAttributes.Public | + MethodAttributes.Static, + weaverTypes.Import(typeof(void))); + + // add [RuntimeInitializeOnLoad] in any case + AddRuntimeInitializeOnLoadAttribute(currentAssembly, weaverTypes, initReadWriters); + + // add [InitializeOnLoad] if UnityEditor is referenced + if (Helpers.IsEditorAssembly(currentAssembly)) + { + AddInitializeOnLoadAttribute(currentAssembly, weaverTypes, initReadWriters); + } + + // fill function body with reader/writer initializers + ILProcessor worker = initReadWriters.Body.GetILProcessor(); + // for debugging: add a log to see if initialized on load + //worker.Emit(OpCodes.Ldstr, $"[InitReadWriters] called!"); + //worker.Emit(OpCodes.Call, Weaver.weaverTypes.logWarningReference); + writers.InitializeWriters(worker); + readers.InitializeReaders(worker); + worker.Emit(OpCodes.Ret); + + GeneratedCodeClass.Methods.Add(initReadWriters); + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs.meta new file mode 100644 index 0000000..c14d6fa --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3263602f0a374ecd8d08588b1fc2f76 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs new file mode 100644 index 0000000..ca2d7b9 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs @@ -0,0 +1,104 @@ +using Mono.CecilX; +using Mono.CecilX.Cil; + +namespace Mirror.Weaver +{ + // Processes [Rpc] methods in NetworkBehaviour + public static class RpcProcessor + { + public static MethodDefinition ProcessRpcInvoke(WeaverTypes weaverTypes, Writers writers, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed) + { + string rpcName = Weaver.GenerateMethodName(RemoteCalls.RemoteProcedureCalls.InvokeRpcPrefix, md); + + MethodDefinition rpc = new MethodDefinition(rpcName, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, + weaverTypes.Import(typeof(void))); + + ILProcessor worker = rpc.Body.GetILProcessor(); + Instruction label = worker.Create(OpCodes.Nop); + + NetworkBehaviourProcessor.WriteClientActiveCheck(worker, weaverTypes, md.Name, label, "RPC"); + + // setup for reader + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Castclass, td); + + if (!NetworkBehaviourProcessor.ReadArguments(md, readers, Log, worker, RemoteCallType.ClientRpc, ref WeavingFailed)) + return null; + + // invoke actual command function + worker.Emit(OpCodes.Callvirt, rpcCallFunc); + worker.Emit(OpCodes.Ret); + + NetworkBehaviourProcessor.AddInvokeParameters(weaverTypes, rpc.Parameters); + td.Methods.Add(rpc); + return rpc; + } + + /* + * generates code like: + + public void RpcTest (int param) + { + NetworkWriter writer = new NetworkWriter (); + writer.WritePackedUInt32((uint)param); + base.SendRPCInternal(typeof(class),"RpcTest", writer, 0); + } + public void CallRpcTest (int param) + { + // whatever the user did before + } + + Originally HLAPI put the send message code inside the Call function + and then proceeded to replace every call to RpcTest with CallRpcTest + + This method moves all the user's code into the "CallRpc" method + and replaces the body of the original method with the send message code. + This way we do not need to modify the code anywhere else, and this works + correctly in dependent assemblies + */ + public static MethodDefinition ProcessRpcCall(WeaverTypes weaverTypes, Writers writers, Logger Log, TypeDefinition td, MethodDefinition md, CustomAttribute clientRpcAttr, ref bool WeavingFailed) + { + MethodDefinition rpc = MethodProcessor.SubstituteMethod(Log, td, md, ref WeavingFailed); + + ILProcessor worker = md.Body.GetILProcessor(); + + NetworkBehaviourProcessor.WriteSetupLocals(worker, weaverTypes); + + // add a log message if needed for debugging + //worker.Emit(OpCodes.Ldstr, $"Call ClientRpc function {md.Name}"); + //worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference); + + NetworkBehaviourProcessor.WriteGetWriter(worker, weaverTypes); + + // write all the arguments that the user passed to the Rpc call + if (!NetworkBehaviourProcessor.WriteArguments(worker, writers, Log, md, RemoteCallType.ClientRpc, ref WeavingFailed)) + return null; + + int channel = clientRpcAttr.GetField("channel", 0); + bool includeOwner = clientRpcAttr.GetField("includeOwner", true); + + // invoke SendInternal and return + // this + worker.Emit(OpCodes.Ldarg_0); + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + worker.Emit(OpCodes.Ldstr, md.FullName); + // pass the function hash so we don't have to compute it at runtime + // otherwise each GetStableHash call requires O(N) complexity. + // noticeable for long function names: + // https://github.com/MirrorNetworking/Mirror/issues/3375 + worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode()); + // writer + worker.Emit(OpCodes.Ldloc_0); + worker.Emit(OpCodes.Ldc_I4, channel); + // includeOwner ? 1 : 0 + worker.Emit(includeOwner ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + worker.Emit(OpCodes.Callvirt, weaverTypes.sendRpcInternal); + + NetworkBehaviourProcessor.WriteReturnWriter(worker, weaverTypes); + + worker.Emit(OpCodes.Ret); + + return rpc; + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs.meta new file mode 100644 index 0000000..22375ba --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3cb7051ff41947e59bba58bdd2b73fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs new file mode 100644 index 0000000..a0b7739 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs @@ -0,0 +1,163 @@ +// Injects server/client active checks for [Server/Client] attributes +using Mono.CecilX; +using Mono.CecilX.Cil; + +namespace Mirror.Weaver +{ + static class ServerClientAttributeProcessor + { + public static bool Process(WeaverTypes weaverTypes, Logger Log, TypeDefinition td, ref bool WeavingFailed) + { + bool modified = false; + foreach (MethodDefinition md in td.Methods) + { + modified |= ProcessSiteMethod(weaverTypes, Log, md, ref WeavingFailed); + } + + foreach (TypeDefinition nested in td.NestedTypes) + { + modified |= Process(weaverTypes, Log, nested, ref WeavingFailed); + } + return modified; + } + + static bool ProcessSiteMethod(WeaverTypes weaverTypes, Logger Log, MethodDefinition md, ref bool WeavingFailed) + { + if (md.Name == ".cctor" || + md.Name == NetworkBehaviourProcessor.ProcessedFunctionName || + md.Name.StartsWith(RemoteCalls.RemoteProcedureCalls.InvokeRpcPrefix)) + return false; + + if (md.IsAbstract) + { + if (HasServerClientAttribute(md)) + { + Log.Error("Server or Client Attributes can't be added to abstract method. Server and Client Attributes are not inherited so they need to be applied to the override methods instead.", md); + WeavingFailed = true; + } + return false; + } + + if (md.Body != null && md.Body.Instructions != null) + { + return ProcessMethodAttributes(weaverTypes, md); + } + return false; + } + + public static bool HasServerClientAttribute(MethodDefinition md) + { + foreach (CustomAttribute attr in md.CustomAttributes) + { + switch (attr.Constructor.DeclaringType.ToString()) + { + case "Mirror.ServerAttribute": + case "Mirror.ServerCallbackAttribute": + case "Mirror.ClientAttribute": + case "Mirror.ClientCallbackAttribute": + return true; + default: + break; + } + } + return false; + } + + public static bool ProcessMethodAttributes(WeaverTypes weaverTypes, MethodDefinition md) + { + if (md.HasCustomAttribute()) + InjectServerGuard(weaverTypes, md, true); + else if (md.HasCustomAttribute()) + InjectServerGuard(weaverTypes, md, false); + else if (md.HasCustomAttribute()) + InjectClientGuard(weaverTypes, md, true); + else if (md.HasCustomAttribute()) + InjectClientGuard(weaverTypes, md, false); + else + return false; + + return true; + } + + static void InjectServerGuard(WeaverTypes weaverTypes, MethodDefinition md, bool logWarning) + { + ILProcessor worker = md.Body.GetILProcessor(); + Instruction top = md.Body.Instructions[0]; + + worker.InsertBefore(top, worker.Create(OpCodes.Call, weaverTypes.NetworkServerGetActive)); + worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top)); + if (logWarning) + { + worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, $"[Server] function '{md.FullName}' called when server was not active")); + worker.InsertBefore(top, worker.Create(OpCodes.Call, weaverTypes.logWarningReference)); + } + InjectGuardParameters(md, worker, top); + InjectGuardReturnValue(md, worker, top); + worker.InsertBefore(top, worker.Create(OpCodes.Ret)); + } + + static void InjectClientGuard(WeaverTypes weaverTypes, MethodDefinition md, bool logWarning) + { + ILProcessor worker = md.Body.GetILProcessor(); + Instruction top = md.Body.Instructions[0]; + + worker.InsertBefore(top, worker.Create(OpCodes.Call, weaverTypes.NetworkClientGetActive)); + worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top)); + if (logWarning) + { + worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, $"[Client] function '{md.FullName}' called when client was not active")); + worker.InsertBefore(top, worker.Create(OpCodes.Call, weaverTypes.logWarningReference)); + } + + InjectGuardParameters(md, worker, top); + InjectGuardReturnValue(md, worker, top); + worker.InsertBefore(top, worker.Create(OpCodes.Ret)); + } + + // this is required to early-out from a function with "ref" or "out" parameters + static void InjectGuardParameters(MethodDefinition md, ILProcessor worker, Instruction top) + { + int offset = md.Resolve().IsStatic ? 0 : 1; + for (int index = 0; index < md.Parameters.Count; index++) + { + ParameterDefinition param = md.Parameters[index]; + if (param.IsOut) + { + // this causes IL2CPP build issues with generic out parameters: + // https://github.com/MirrorNetworking/Mirror/issues/3482 + // TypeReference elementType = param.ParameterType.GetElementType(); + // + // instead we need to use ElementType not GetElementType() + // GetElementType() will get the element type of the inner elementType + // which will return wrong type for arrays and generic + // credit: JamesFrowen + ByReferenceType byRefType = (ByReferenceType)param.ParameterType; + TypeReference elementType = byRefType.ElementType; + + md.Body.Variables.Add(new VariableDefinition(elementType)); + md.Body.InitLocals = true; + + worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, index + offset)); + worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1))); + worker.InsertBefore(top, worker.Create(OpCodes.Initobj, elementType)); + worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1)); + worker.InsertBefore(top, worker.Create(OpCodes.Stobj, elementType)); + } + } + } + + // this is required to early-out from a function with a return value. + static void InjectGuardReturnValue(MethodDefinition md, ILProcessor worker, Instruction top) + { + if (!md.ReturnType.Is(typeof(void))) + { + md.Body.Variables.Add(new VariableDefinition(md.ReturnType)); + md.Body.InitLocals = true; + + worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1))); + worker.InsertBefore(top, worker.Create(OpCodes.Initobj, md.ReturnType)); + worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1)); + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs.meta new file mode 100644 index 0000000..5a5451d --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 024f251bf693bb345b90b9177892d534 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs new file mode 100644 index 0000000..a174403 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs @@ -0,0 +1,39 @@ +using Mono.CecilX; +using Mono.CecilX.Cil; + +namespace Mirror.Weaver +{ + public static class SyncObjectInitializer + { + // generates code like: + // this.InitSyncObject(m_sizes); + public static void GenerateSyncObjectInitializer(ILProcessor worker, WeaverTypes weaverTypes, FieldDefinition fd) + { + // register syncobject in network behaviour + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, fd); + worker.Emit(OpCodes.Call, weaverTypes.InitSyncObjectReference); + } + + public static bool ImplementsSyncObject(TypeReference typeRef) + { + try + { + // value types cant inherit from SyncObject + if (typeRef.IsValueType) + { + return false; + } + + return typeRef.Resolve().IsDerivedFrom(); + } + catch + { + // sometimes this will fail if we reference a weird library that can't be resolved, so we just swallow that exception and return false + } + + return false; + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs.meta new file mode 100644 index 0000000..22f976e --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d02219b00b3674e59a2151f41e791688 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs new file mode 100644 index 0000000..8143e86 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using Mono.CecilX; + +namespace Mirror.Weaver +{ + public static class SyncObjectProcessor + { + // ulong = 64 bytes + const int SyncObjectsLimit = 64; + + // Finds SyncObjects fields in a type + // Type should be a NetworkBehaviour + public static List FindSyncObjectsFields(Writers writers, Readers readers, Logger Log, TypeDefinition td, ref bool WeavingFailed) + { + List syncObjects = new List(); + + foreach (FieldDefinition fd in td.Fields) + { + if (fd.FieldType.IsGenericParameter || fd.ContainsGenericParameter) + { + // can't call .Resolve on generic ones + continue; + } + + if (fd.FieldType.Resolve().IsDerivedFrom()) + { + if (fd.IsStatic) + { + Log.Error($"{fd.Name} cannot be static", fd); + WeavingFailed = true; + continue; + } + + // SyncObjects always needs to be readonly to guarantee. + // Weaver calls InitSyncObject on them for dirty bits etc. + // Reassigning at runtime would cause undefined behaviour. + // (C# 'readonly' is called 'initonly' in IL code.) + // + // NOTE: instead of forcing readonly, we could also scan all + // instructions for SyncObject assignments. this would + // make unit tests very difficult though. + if (!fd.IsInitOnly) + { + // just a warning for now. + // many people might still use non-readonly SyncObjects. + Log.Warning($"{fd.Name} should have a 'readonly' keyword in front of the variable because {typeof(SyncObject)}s always need to be initialized by the Weaver.", fd); + + // only log, but keep weaving. no need to break projects. + //WeavingFailed = true; + } + + GenerateReadersAndWriters(writers, readers, fd.FieldType, ref WeavingFailed); + + syncObjects.Add(fd); + } + } + + // SyncObjects dirty mask is 64 bit. can't sync more than 64. + if (syncObjects.Count > 64) + { + Log.Error($"{td.Name} has > {SyncObjectsLimit} SyncObjects (SyncLists etc). Consider refactoring your class into multiple components", td); + WeavingFailed = true; + } + + + return syncObjects; + } + + // Generates serialization methods for synclists + static void GenerateReadersAndWriters(Writers writers, Readers readers, TypeReference tr, ref bool WeavingFailed) + { + if (tr is GenericInstanceType genericInstance) + { + foreach (TypeReference argument in genericInstance.GenericArguments) + { + if (!argument.IsGenericParameter) + { + readers.GetReadFunc(argument, ref WeavingFailed); + writers.GetWriteFunc(argument, ref WeavingFailed); + } + } + } + + if (tr != null) + { + GenerateReadersAndWriters(writers, readers, tr.Resolve().BaseType, ref WeavingFailed); + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs.meta new file mode 100644 index 0000000..0efe434 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 78f71efc83cde4917b7d21efa90bcc9a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeAccessReplacer.cs b/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeAccessReplacer.cs new file mode 100644 index 0000000..73a9526 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeAccessReplacer.cs @@ -0,0 +1,206 @@ +// [SyncVar] int health; +// is replaced with: +// public int Networkhealth { get; set; } properties. +// this class processes all access to 'health' and replaces it with 'Networkhealth' +using System; +using Mono.CecilX; +using Mono.CecilX.Cil; + +namespace Mirror.Weaver +{ + public static class SyncVarAttributeAccessReplacer + { + // process the module + public static void Process(Logger Log, ModuleDefinition moduleDef, SyncVarAccessLists syncVarAccessLists) + { + DateTime startTime = DateTime.Now; + + // process all classes in this module + foreach (TypeDefinition td in moduleDef.Types) + { + if (td.IsClass) + { + ProcessClass(Log, syncVarAccessLists, td); + } + } + + Console.WriteLine($" ProcessSitesModule {moduleDef.Name} elapsed time:{(DateTime.Now - startTime)}"); + } + + static void ProcessClass(Logger Log, SyncVarAccessLists syncVarAccessLists, TypeDefinition td) + { + //Console.WriteLine($" ProcessClass {td}"); + + // process all methods in this class + foreach (MethodDefinition md in td.Methods) + { + ProcessMethod(Log, syncVarAccessLists, md); + } + + // processes all nested classes in this class recursively + foreach (TypeDefinition nested in td.NestedTypes) + { + ProcessClass(Log, syncVarAccessLists, nested); + } + } + + static void ProcessMethod(Logger Log, SyncVarAccessLists syncVarAccessLists, MethodDefinition md) + { + // process all references to replaced members with properties + //Log.Warning($" ProcessSiteMethod {md}"); + + // skip static constructor, "MirrorProcessed", "InvokeUserCode_" + if (md.Name == ".cctor" || + md.Name == NetworkBehaviourProcessor.ProcessedFunctionName || + md.Name.StartsWith(RemoteCalls.RemoteProcedureCalls.InvokeRpcPrefix)) + return; + + // skip abstract + if (md.IsAbstract) + { + return; + } + + // go through all instructions of this method + if (md.Body != null && md.Body.Instructions != null) + { + for (int i = 0; i < md.Body.Instructions.Count;) + { + Instruction instr = md.Body.Instructions[i]; + i += ProcessInstruction(Log, syncVarAccessLists, md, instr, i); + } + } + } + + static int ProcessInstruction(Logger Log, SyncVarAccessLists syncVarAccessLists, MethodDefinition md, Instruction instr, int iCount) + { + // stfld (sets value of a field)? + if (instr.OpCode == OpCodes.Stfld) + { + // operand is a FieldDefinition in the same assembly? + if (instr.Operand is FieldDefinition opFieldst) + { + ProcessSetInstruction(syncVarAccessLists, md, instr, opFieldst); + } + // operand is a FieldReference in another assembly? + // this is not supported just yet. + // compilation error is better than silently failing SyncVar serialization at runtime. + // https://github.com/MirrorNetworking/Mirror/issues/3525 + else if (instr.Operand is FieldReference opFieldstRef) + { + // resolve it from the other assembly + FieldDefinition field = opFieldstRef.Resolve(); + + // [SyncVar]? + if (field.HasCustomAttribute()) + { + // ILPostProcessor would need to Process() the assembly's + // references before processing this one. + // we can not control the order. + // instead, Log an error to suggest adding a SetSyncVar(value) function. + // this is a very easy solution for a very rare edge case. + Log.Error($"'[SyncVar] {opFieldstRef.DeclaringType.Name}.{opFieldstRef.Name}' in '{field.Module.Name}' is modified by '{md.FullName}' in '{md.Module.Name}'. Modifying a [SyncVar] from another assembly is not supported. Please add a: 'public void Set{opFieldstRef.Name}(value) {{ this.{opFieldstRef.Name} = value; }}' method in '{opFieldstRef.DeclaringType.Name}' and call this function from '{md.FullName}' instead."); + } + } + } + + // ldfld (load value of a field)? + if (instr.OpCode == OpCodes.Ldfld) + { + // operand is a FieldDefinition in the same assembly? + if (instr.Operand is FieldDefinition opFieldld) + { + // this instruction gets the value of a field. cache the field reference. + ProcessGetInstruction(syncVarAccessLists, md, instr, opFieldld); + } + } + + // ldflda (load field address aka reference) + if (instr.OpCode == OpCodes.Ldflda) + { + // operand is a FieldDefinition in the same assembly? + if (instr.Operand is FieldDefinition opFieldlda) + { + // watch out for initobj instruction + // see https://github.com/vis2k/Mirror/issues/696 + return ProcessLoadAddressInstruction(syncVarAccessLists, md, instr, opFieldlda, iCount); + } + } + + // we processed one instruction (instr) + return 1; + } + + // replaces syncvar write access with the NetworkXYZ.set property calls + static void ProcessSetInstruction(SyncVarAccessLists syncVarAccessLists, MethodDefinition md, Instruction i, FieldDefinition opField) + { + // don't replace property call sites in constructors + if (md.Name == ".ctor") + return; + + // does it set a field that we replaced? + if (syncVarAccessLists.replacementSetterProperties.TryGetValue(opField, out MethodDefinition replacement)) + { + //replace with property + //Log.Warning($" replacing {md.Name}:{i}", opField); + i.OpCode = OpCodes.Call; + i.Operand = replacement; + //Log.Warning($" replaced {md.Name}:{i}", opField); + } + } + + // replaces syncvar read access with the NetworkXYZ.get property calls + static void ProcessGetInstruction(SyncVarAccessLists syncVarAccessLists, MethodDefinition md, Instruction i, FieldDefinition opField) + { + // don't replace property call sites in constructors + if (md.Name == ".ctor") + return; + + // does it set a field that we replaced? + if (syncVarAccessLists.replacementGetterProperties.TryGetValue(opField, out MethodDefinition replacement)) + { + //replace with property + //Log.Warning($" replacing {md.Name}:{i}"); + i.OpCode = OpCodes.Call; + i.Operand = replacement; + //Log.Warning($" replaced {md.Name}:{i}"); + } + } + + static int ProcessLoadAddressInstruction(SyncVarAccessLists syncVarAccessLists, MethodDefinition md, Instruction instr, FieldDefinition opField, int iCount) + { + // don't replace property call sites in constructors + if (md.Name == ".ctor") + return 1; + + // does it set a field that we replaced? + if (syncVarAccessLists.replacementSetterProperties.TryGetValue(opField, out MethodDefinition replacement)) + { + // we have a replacement for this property + // is the next instruction a initobj? + Instruction nextInstr = md.Body.Instructions[iCount + 1]; + + if (nextInstr.OpCode == OpCodes.Initobj) + { + // we need to replace this code with: + // var tmp = new MyStruct(); + // this.set_Networkxxxx(tmp); + ILProcessor worker = md.Body.GetILProcessor(); + VariableDefinition tmpVariable = new VariableDefinition(opField.FieldType); + md.Body.Variables.Add(tmpVariable); + + worker.InsertBefore(instr, worker.Create(OpCodes.Ldloca, tmpVariable)); + worker.InsertBefore(instr, worker.Create(OpCodes.Initobj, opField.FieldType)); + worker.InsertBefore(instr, worker.Create(OpCodes.Ldloc, tmpVariable)); + worker.InsertBefore(instr, worker.Create(OpCodes.Call, replacement)); + + worker.Remove(instr); + worker.Remove(nextInstr); + return 4; + } + } + + return 1; + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeAccessReplacer.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeAccessReplacer.cs.meta new file mode 100644 index 0000000..e8c2500 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeAccessReplacer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d48f1ab125e9940a995603796bccc59e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeProcessor.cs new file mode 100644 index 0000000..76e3ac7 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeProcessor.cs @@ -0,0 +1,515 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Mono.CecilX; +using Mono.CecilX.Cil; +using Mono.CecilX.Rocks; + +namespace Mirror.Weaver +{ + // Processes [SyncVar] attribute fields in NetworkBehaviour + // not static, because ILPostProcessor is multithreaded + public class SyncVarAttributeProcessor + { + // ulong = 64 bytes + const int SyncVarLimit = 64; + + AssemblyDefinition assembly; + WeaverTypes weaverTypes; + SyncVarAccessLists syncVarAccessLists; + Logger Log; + + string HookParameterMessage(string hookName, TypeReference ValueType) => + $"void {hookName}({ValueType} oldValue, {ValueType} newValue)"; + + public SyncVarAttributeProcessor(AssemblyDefinition assembly, WeaverTypes weaverTypes, SyncVarAccessLists syncVarAccessLists, Logger Log) + { + this.assembly = assembly; + this.weaverTypes = weaverTypes; + this.syncVarAccessLists = syncVarAccessLists; + this.Log = Log; + } + + // Get hook method if any + public MethodDefinition GetHookMethod(TypeDefinition td, FieldDefinition syncVar, ref bool WeavingFailed) + { + CustomAttribute syncVarAttr = syncVar.GetCustomAttribute(); + + if (syncVarAttr == null) + return null; + + string hookFunctionName = syncVarAttr.GetField("hook", null); + + if (hookFunctionName == null) + return null; + + return FindHookMethod(td, syncVar, hookFunctionName, ref WeavingFailed); + } + + // Create a field definition for a field that will store the Action delegate instance for the syncvar hook method (only instantiate delegate once) + public FieldDefinition CreateNewActionFieldDefinitionFromHookMethod(FieldDefinition syncVarField) + { + TypeReference actionRef = assembly.MainModule.ImportReference(typeof(Action<,>)); + GenericInstanceType syncVarHookActionDelegateType = actionRef.MakeGenericInstanceType(syncVarField.FieldType, syncVarField.FieldType); + string syncVarHookDelegateFieldName = $"_Mirror_SyncVarHookDelegate_{syncVarField.Name}"; + return new FieldDefinition(syncVarHookDelegateFieldName, FieldAttributes.Public, syncVarHookActionDelegateType); + } + + // push hook from GetHookMethod() onto the stack as a new Action. + // allows for reuse without handling static/virtual cases every time. + // perf warning: it is recommended to use this method only when generating IL to create a new Action() in order to store it into a field + // avoid using this to emit IL to instantiate a new action instance every single time one is needed for the same method + public void GenerateNewActionFromHookMethod(FieldDefinition syncVar, ILProcessor worker, MethodDefinition hookMethod) + { + // IL_000a: ldarg.0 + // IL_000b: ldftn instance void Mirror.Examples.Tanks.Tank::ExampleHook(int32, int32) + // IL_0011: newobj instance void class [netstandard]System.Action`2::.ctor(object, native int) + + // we support static hooks and instance hooks. + if (hookMethod.IsStatic) + { + // for static hooks, we need to push 'null' first. + // we can't just push nothing. + // stack would get out of balance because we already pushed + // other stuff above. + worker.Emit(OpCodes.Ldnull); + } + else + { + // for instance hooks, we need to push 'this.' first. + worker.Emit(OpCodes.Ldarg_0); + } + + MethodReference hookMethodReference; + // if the network behaviour class is generic, we need to make the method reference generic for correct IL + if (hookMethod.DeclaringType.HasGenericParameters) + { + hookMethodReference = hookMethod.MakeHostInstanceGeneric(hookMethod.Module, hookMethod.DeclaringType.MakeGenericInstanceType(hookMethod.DeclaringType.GenericParameters.ToArray())); + } + else + { + hookMethodReference = hookMethod; + } + + // we support regular and virtual hook functions. + if (hookMethod.IsVirtual) + { + // for virtual / overwritten hooks, we need different IL. + // this is from simply testing Action = VirtualHook; in C#. + worker.Emit(OpCodes.Dup); + worker.Emit(OpCodes.Ldvirtftn, hookMethodReference); + } + else + { + worker.Emit(OpCodes.Ldftn, hookMethodReference); + } + + // call 'new Action()' constructor to convert the function to an action + // we need to make an instance of the generic Action. + TypeReference actionRef = assembly.MainModule.ImportReference(typeof(Action<,>)); + GenericInstanceType genericInstance = actionRef.MakeGenericInstanceType(syncVar.FieldType, syncVar.FieldType); + worker.Emit(OpCodes.Newobj, weaverTypes.ActionT_T.MakeHostInstanceGeneric(assembly.MainModule, genericInstance)); + } + + // generates CIL to set an Action instance field to a new Action(hookMethod) + // this.hookDelegate = new Action(HookMethod); + public void GenerateSyncVarHookDelegateInitializer(ILProcessor worker, FieldDefinition syncVar, FieldDefinition hookDelegate, MethodDefinition hookMethod) + { + // push this + worker.Emit(OpCodes.Ldarg_0); + // push new Action(hookMethod) + GenerateNewActionFromHookMethod(syncVar, worker, hookMethod); + // set field + worker.Emit(OpCodes.Stfld, hookDelegate); + } + + MethodDefinition FindHookMethod(TypeDefinition td, FieldDefinition syncVar, string hookFunctionName, ref bool WeavingFailed) + { + List methods = td.GetMethods(hookFunctionName); + + List methodsWith2Param = new List(methods.Where(m => m.Parameters.Count == 2)); + + if (methodsWith2Param.Count == 0) + { + Log.Error($"Could not find hook for '{syncVar.Name}', hook name '{hookFunctionName}'. " + + $"Method signature should be {HookParameterMessage(hookFunctionName, syncVar.FieldType)}", + syncVar); + WeavingFailed = true; + + return null; + } + + foreach (MethodDefinition method in methodsWith2Param) + { + if (MatchesParameters(syncVar, method)) + { + return method; + } + } + + Log.Error($"Wrong type for Parameter in hook for '{syncVar.Name}', hook name '{hookFunctionName}'. " + + $"Method signature should be {HookParameterMessage(hookFunctionName, syncVar.FieldType)}", + syncVar); + WeavingFailed = true; + + return null; + } + + bool MatchesParameters(FieldDefinition syncVar, MethodDefinition method) + { + // matches void onValueChange(T oldValue, T newValue) + return method.Parameters[0].ParameterType.FullName == syncVar.FieldType.FullName && + method.Parameters[1].ParameterType.FullName == syncVar.FieldType.FullName; + } + + public MethodDefinition GenerateSyncVarGetter(FieldDefinition fd, string originalName, FieldDefinition netFieldId) + { + //Create the get method + MethodDefinition get = new MethodDefinition( + $"get_Network{originalName}", MethodAttributes.Public | + MethodAttributes.SpecialName | + MethodAttributes.HideBySig, + fd.FieldType); + + ILProcessor worker = get.Body.GetILProcessor(); + + FieldReference fr; + if (fd.DeclaringType.HasGenericParameters) + { + fr = fd.MakeHostInstanceGeneric(); + } + else + { + fr = fd; + } + + FieldReference netIdFieldReference = null; + if (netFieldId != null) + { + if (netFieldId.DeclaringType.HasGenericParameters) + { + netIdFieldReference = netFieldId.MakeHostInstanceGeneric(); + } + else + { + netIdFieldReference = netFieldId; + } + } + + // [SyncVar] GameObject? + if (fd.FieldType.Is()) + { + // return this.GetSyncVarGameObject(ref field, uint netId); + // this. + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, netIdFieldReference); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, fr); + worker.Emit(OpCodes.Call, weaverTypes.getSyncVarGameObjectReference); + worker.Emit(OpCodes.Ret); + } + // [SyncVar] NetworkIdentity? + else if (fd.FieldType.Is()) + { + // return this.GetSyncVarNetworkIdentity(ref field, uint netId); + // this. + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, netIdFieldReference); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, fr); + worker.Emit(OpCodes.Call, weaverTypes.getSyncVarNetworkIdentityReference); + worker.Emit(OpCodes.Ret); + } + // handle both NetworkBehaviour and inheritors. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/2939 + else if (fd.FieldType.IsDerivedFrom() || fd.FieldType.Is()) + { + // return this.GetSyncVarNetworkBehaviour(ref field, uint netId); + // this. + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, netIdFieldReference); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, fr); + MethodReference getFunc = weaverTypes.getSyncVarNetworkBehaviourReference.MakeGeneric(assembly.MainModule, fd.FieldType); + worker.Emit(OpCodes.Call, getFunc); + worker.Emit(OpCodes.Ret); + } + // [SyncVar] int, string, etc. + else + { + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, fr); + worker.Emit(OpCodes.Ret); + } + + get.Body.Variables.Add(new VariableDefinition(fd.FieldType)); + get.Body.InitLocals = true; + get.SemanticsAttributes = MethodSemanticsAttributes.Getter; + + return get; + } + + // for [SyncVar] health, weaver generates + // + // NetworkHealth + // { + // get => health; + // set => GeneratedSyncVarSetter(...) + // } + // + // the setter used to be manually IL generated, but we moved it to C# :) + public MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDefinition fd, string originalName, long dirtyBit, FieldDefinition netFieldId, Dictionary syncVarHookDelegates, ref bool WeavingFailed) + { + //Create the set method + MethodDefinition set = new MethodDefinition($"set_Network{originalName}", MethodAttributes.Public | + MethodAttributes.SpecialName | + MethodAttributes.HideBySig, + weaverTypes.Import(typeof(void))); + + ILProcessor worker = set.Body.GetILProcessor(); + FieldReference fr; + if (fd.DeclaringType.HasGenericParameters) + { + fr = fd.MakeHostInstanceGeneric(); + } + else + { + fr = fd; + } + + FieldReference netIdFieldReference = null; + if (netFieldId != null) + { + if (netFieldId.DeclaringType.HasGenericParameters) + { + netIdFieldReference = netFieldId.MakeHostInstanceGeneric(); + } + else + { + netIdFieldReference = netFieldId; + } + } + + // if (!SyncVarEqual(value, ref playerData)) + Instruction endOfMethod = worker.Create(OpCodes.Nop); + + // NOTE: SyncVar...Equal functions are static. + // don't Emit Ldarg_0 aka 'this'. + + // call WeaverSyncVarSetter(T value, ref T field, ulong dirtyBit, Action OnChanged = null) + // IL_0000: ldarg.0 + // IL_0001: ldarg.1 + // IL_0002: ldarg.0 + // IL_0003: ldflda int32 Mirror.Examples.Tanks.Tank::health + // IL_0008: ldc.i4.1 + // IL_0009: conv.i8 + // IL_000a: ldnull + // IL_000b: call instance void [Mirror]Mirror.NetworkBehaviour::GeneratedSyncVarSetter(!!0, !!0&, uint64, class [netstandard]System.Action`2) + // IL_0010: ret + + // 'this.' for the call + worker.Emit(OpCodes.Ldarg_0); + + // first push 'value' + worker.Emit(OpCodes.Ldarg_1); + + // push 'ref T this.field' + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, fr); + + // push the dirty bit for this SyncVar + worker.Emit(OpCodes.Ldc_I8, dirtyBit); + + // hook? then push 'this.HookDelegate' onto stack + MethodDefinition hookMethod = GetHookMethod(td, fd, ref WeavingFailed); + if (hookMethod != null) + { + // Create the field that will store a single instance of the hook as a delegate (field will be set in constructor) + FieldDefinition hookActionDelegateField = CreateNewActionFieldDefinitionFromHookMethod(fd); + syncVarHookDelegates[fd] = (hookActionDelegateField, hookMethod); + + // push this.hookActionDelegateField + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldfld, hookActionDelegateField); + } + // otherwise push 'null' as hook + else + { + worker.Emit(OpCodes.Ldnull); + } + + // call GeneratedSyncVarSetter. + // special cases for GameObject/NetworkIdentity/NetworkBehaviour + // passing netId too for persistence. + if (fd.FieldType.Is()) + { + // GameObject setter needs one more parameter: netId field ref + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, netIdFieldReference); + worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarSetter_GameObject); + } + else if (fd.FieldType.Is()) + { + // NetworkIdentity setter needs one more parameter: netId field ref + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, netIdFieldReference); + worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarSetter_NetworkIdentity); + } + // handle both NetworkBehaviour and inheritors. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/2939 + else if (fd.FieldType.IsDerivedFrom() || fd.FieldType.Is()) + { + // NetworkIdentity setter needs one more parameter: netId field ref + // (actually its a NetworkBehaviourSyncVar type) + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldflda, netIdFieldReference); + // make generic version of GeneratedSyncVarSetter_NetworkBehaviour + MethodReference getFunc = weaverTypes.generatedSyncVarSetter_NetworkBehaviour_T.MakeGeneric(assembly.MainModule, fd.FieldType); + worker.Emit(OpCodes.Call, getFunc); + } + else + { + // make generic version of GeneratedSyncVarSetter + MethodReference generic = weaverTypes.generatedSyncVarSetter.MakeGeneric(assembly.MainModule, fd.FieldType); + worker.Emit(OpCodes.Call, generic); + } + + worker.Append(endOfMethod); + + worker.Emit(OpCodes.Ret); + + set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType)); + set.SemanticsAttributes = MethodSemanticsAttributes.Setter; + + return set; + } + + public void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, Dictionary syncVarNetIds, Dictionary syncVarHookDelegates, long dirtyBit, ref bool WeavingFailed) + { + string originalName = fd.Name; + + // GameObject/NetworkIdentity SyncVars have a new field for netId + FieldDefinition netIdField = null; + // NetworkBehaviour has different field type than other NetworkIdentityFields + // handle both NetworkBehaviour and inheritors. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/2939 + if (fd.FieldType.IsDerivedFrom() || fd.FieldType.Is()) + { + netIdField = new FieldDefinition($"___{fd.Name}NetId", + FieldAttributes.Family, // needs to be protected for generic classes, otherwise access isn't allowed + weaverTypes.Import()); + netIdField.DeclaringType = td; + + syncVarNetIds[fd] = netIdField; + } + else if (fd.FieldType.IsNetworkIdentityField()) + { + netIdField = new FieldDefinition($"___{fd.Name}NetId", + FieldAttributes.Family, // needs to be protected for generic classes, otherwise access isn't allowed + weaverTypes.Import()); + netIdField.DeclaringType = td; + + syncVarNetIds[fd] = netIdField; + } + + MethodDefinition get = GenerateSyncVarGetter(fd, originalName, netIdField); + MethodDefinition set = GenerateSyncVarSetter(td, fd, originalName, dirtyBit, netIdField, syncVarHookDelegates, ref WeavingFailed); + + //NOTE: is property even needed? Could just use a setter function? + //create the property + PropertyDefinition propertyDefinition = new PropertyDefinition($"Network{originalName}", PropertyAttributes.None, fd.FieldType) + { + GetMethod = get, + SetMethod = set + }; + + //add the methods and property to the type. + td.Methods.Add(get); + td.Methods.Add(set); + td.Properties.Add(propertyDefinition); + syncVarAccessLists.replacementSetterProperties[fd] = set; + + // replace getter field if GameObject/NetworkIdentity so it uses + // netId instead + // -> only for GameObjects, otherwise an int syncvar's getter would + // end up in recursion. + if (fd.FieldType.IsNetworkIdentityField()) + { + syncVarAccessLists.replacementGetterProperties[fd] = get; + } + } + + public (List syncVars, Dictionary syncVarNetIds, Dictionary syncVarHookDelegates) ProcessSyncVars(TypeDefinition td, ref bool WeavingFailed) + { + List syncVars = new List(); + Dictionary syncVarNetIds = new Dictionary(); + Dictionary syncVarHookDelegates = new Dictionary(); + + // the mapping of dirtybits to sync-vars is implicit in the order of the fields here. this order is recorded in m_replacementProperties. + // start assigning syncvars at the place the base class stopped, if any + int dirtyBitCounter = syncVarAccessLists.GetSyncVarStart(td.BaseType.FullName); + + // find syncvars + foreach (FieldDefinition fd in td.Fields) + { + if (fd.HasCustomAttribute()) + { + if ((fd.Attributes & FieldAttributes.Static) != 0) + { + Log.Error($"{fd.Name} cannot be static", fd); + WeavingFailed = true; + continue; + } + + if (fd.FieldType.IsGenericParameter) + { + Log.Error($"{fd.Name} has generic type. Generic SyncVars are not supported", fd); + WeavingFailed = true; + continue; + } + + if (SyncObjectInitializer.ImplementsSyncObject(fd.FieldType)) + { + Log.Warning($"{fd.Name} has [SyncVar] attribute. SyncLists should not be marked with SyncVar", fd); + } + else + { + syncVars.Add(fd); + + ProcessSyncVar(td, fd, syncVarNetIds, syncVarHookDelegates, 1L << dirtyBitCounter, ref WeavingFailed); + dirtyBitCounter += 1; + + if (dirtyBitCounter > SyncVarLimit) + { + Log.Error($"{td.Name} has > {SyncVarLimit} SyncVars. Consider refactoring your class into multiple components", td); + WeavingFailed = true; + continue; + } + } + } + } + + // add all the new SyncVar __netId fields + foreach (FieldDefinition fd in syncVarNetIds.Values) + { + td.Fields.Add(fd); + } + + // add all of the new SyncVar Action fields + foreach((FieldDefinition hookDelegateInstanceField, MethodDefinition) entry in syncVarHookDelegates.Values) + { + td.Fields.Add(entry.hookDelegateInstanceField); + } + + // include parent class syncvars + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3457 + int parentSyncVarCount = syncVarAccessLists.GetSyncVarStart(td.BaseType.FullName); + syncVarAccessLists.SetNumSyncVars(td.FullName, parentSyncVarCount + syncVars.Count); + + return (syncVars, syncVarNetIds, syncVarHookDelegates); + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeProcessor.cs.meta new file mode 100644 index 0000000..982f768 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncVarAttributeProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f52c39bddd95d42b88f9cd554dfd9198 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs new file mode 100644 index 0000000..8d56040 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs @@ -0,0 +1,159 @@ +using Mono.CecilX; +using Mono.CecilX.Cil; + +namespace Mirror.Weaver +{ + // Processes [TargetRpc] methods in NetworkBehaviour + public static class TargetRpcProcessor + { + // helper functions to check if the method has a NetworkConnection parameter + public static bool HasNetworkConnectionParameter(MethodDefinition md) + { + if (md.Parameters.Count > 0) + { + // we need to allow both NetworkConnection, and inheriting types. + // NetworkBehaviour.SendTargetRpc takes a NetworkConnection parameter. + // fixes https://github.com/vis2k/Mirror/issues/3290 + TypeReference type = md.Parameters[0].ParameterType; + return type.Is() || + type.IsDerivedFrom(); + } + return false; + } + + public static MethodDefinition ProcessTargetRpcInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed) + { + string trgName = Weaver.GenerateMethodName(RemoteCalls.RemoteProcedureCalls.InvokeRpcPrefix, md); + + MethodDefinition rpc = new MethodDefinition(trgName, MethodAttributes.Family | + MethodAttributes.Static | + MethodAttributes.HideBySig, + weaverTypes.Import(typeof(void))); + + ILProcessor worker = rpc.Body.GetILProcessor(); + Instruction label = worker.Create(OpCodes.Nop); + + NetworkBehaviourProcessor.WriteClientActiveCheck(worker, weaverTypes, md.Name, label, "TargetRPC"); + + // setup for reader + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Castclass, td); + + // NetworkConnection parameter is optional + if (HasNetworkConnectionParameter(md)) + { + // TargetRpcs are sent from server to client. + // on server, we currently support two types: + // TargetRpc(NetworkConnection) + // TargetRpc(NetworkConnectionToClient) + // however, it's always a connection to client. + // in the future, only NetworkConnectionToClient will be supported. + // explicit typing helps catch issues at compile time. + // + // on client, InvokeTargetRpc calls the original code. + // we need to fill in the NetworkConnection parameter. + // NetworkClient.connection is always a connection to server. + // + // we used to pass NetworkClient.connection as the TargetRpc parameter. + // which caused: https://github.com/MirrorNetworking/Mirror/issues/3455 + // when the parameter is defined as a NetworkConnectionToClient. + // + // a client's connection never fits into a NetworkConnectionToClient. + // we need to always pass null here. + worker.Emit(OpCodes.Ldnull); + } + + // process reader parameters and skip first one if first one is NetworkConnection + if (!NetworkBehaviourProcessor.ReadArguments(md, readers, Log, worker, RemoteCallType.TargetRpc, ref WeavingFailed)) + return null; + + // invoke actual command function + worker.Emit(OpCodes.Callvirt, rpcCallFunc); + worker.Emit(OpCodes.Ret); + + NetworkBehaviourProcessor.AddInvokeParameters(weaverTypes, rpc.Parameters); + td.Methods.Add(rpc); + return rpc; + } + + /* generates code like: + public void TargetTest (NetworkConnection conn, int param) + { + NetworkWriter writer = new NetworkWriter (); + writer.WritePackedUInt32 ((uint)param); + base.SendTargetRPCInternal (conn, typeof(class), "TargetTest", val); + } + public void CallTargetTest (NetworkConnection conn, int param) + { + // whatever the user did before + } + + or if optional: + public void TargetTest (int param) + { + NetworkWriter writer = new NetworkWriter (); + writer.WritePackedUInt32 ((uint)param); + base.SendTargetRPCInternal (null, typeof(class), "TargetTest", val); + } + public void CallTargetTest (int param) + { + // whatever the user did before + } + + Originally HLAPI put the send message code inside the Call function + and then proceeded to replace every call to TargetTest with CallTargetTest + + This method moves all the user's code into the "CallTargetRpc" method + and replaces the body of the original method with the send message code. + This way we do not need to modify the code anywhere else, and this works + correctly in dependent assemblies + + */ + public static MethodDefinition ProcessTargetRpcCall(WeaverTypes weaverTypes, Writers writers, Logger Log, TypeDefinition td, MethodDefinition md, CustomAttribute targetRpcAttr, ref bool WeavingFailed) + { + MethodDefinition rpc = MethodProcessor.SubstituteMethod(Log, td, md, ref WeavingFailed); + + ILProcessor worker = md.Body.GetILProcessor(); + + NetworkBehaviourProcessor.WriteSetupLocals(worker, weaverTypes); + + NetworkBehaviourProcessor.WriteGetWriter(worker, weaverTypes); + + // write all the arguments that the user passed to the TargetRpc call + // (skip first one if first one is NetworkConnection) + if (!NetworkBehaviourProcessor.WriteArguments(worker, writers, Log, md, RemoteCallType.TargetRpc, ref WeavingFailed)) + return null; + + // invoke SendInternal and return + // this + worker.Emit(OpCodes.Ldarg_0); + if (HasNetworkConnectionParameter(md)) + { + // connection + worker.Emit(OpCodes.Ldarg_1); + } + else + { + // null + worker.Emit(OpCodes.Ldnull); + } + // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions + worker.Emit(OpCodes.Ldstr, md.FullName); + // pass the function hash so we don't have to compute it at runtime + // otherwise each GetStableHash call requires O(N) complexity. + // noticeable for long function names: + // https://github.com/MirrorNetworking/Mirror/issues/3375 + worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode()); + // writer + worker.Emit(OpCodes.Ldloc_0); + worker.Emit(OpCodes.Ldc_I4, targetRpcAttr.GetField("channel", 0)); + worker.Emit(OpCodes.Callvirt, weaverTypes.sendTargetRpcInternal); + + NetworkBehaviourProcessor.WriteReturnWriter(worker, weaverTypes); + + worker.Emit(OpCodes.Ret); + + return rpc; + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs.meta new file mode 100644 index 0000000..0ff7cc5 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb3ce6c6f3f2942ae88178b86f5a8282 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Readers.cs b/Assets/Mirror/Editor/Weaver/Readers.cs new file mode 100644 index 0000000..33941d9 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Readers.cs @@ -0,0 +1,385 @@ +using System; +using System.Collections.Generic; +using Mono.CecilX; +using Mono.CecilX.Cil; +// to use Mono.CecilX.Rocks here, we need to 'override references' in the +// Unity.Mirror.CodeGen assembly definition file in the Editor, and add CecilX.Rocks. +// otherwise we get an unknown import exception. +using Mono.CecilX.Rocks; + +namespace Mirror.Weaver +{ + // not static, because ILPostProcessor is multithreaded + public class Readers + { + // Readers are only for this assembly. + // can't be used from another assembly, otherwise we will get: + // "System.ArgumentException: Member ... is declared in another module and needs to be imported" + AssemblyDefinition assembly; + WeaverTypes weaverTypes; + TypeDefinition GeneratedCodeClass; + Logger Log; + + Dictionary readFuncs = + new Dictionary(new TypeReferenceComparer()); + + public Readers(AssemblyDefinition assembly, WeaverTypes weaverTypes, TypeDefinition GeneratedCodeClass, Logger Log) + { + this.assembly = assembly; + this.weaverTypes = weaverTypes; + this.GeneratedCodeClass = GeneratedCodeClass; + this.Log = Log; + } + + internal void Register(TypeReference dataType, MethodReference methodReference) + { + if (readFuncs.ContainsKey(dataType)) + { + // TODO enable this again later. + // Reader has some obsolete functions that were renamed. + // Don't want weaver warnings for all of them. + //Log.Warning($"Registering a Read method for {dataType.FullName} when one already exists", methodReference); + } + + // we need to import type when we Initialize Readers so import here in case it is used anywhere else + TypeReference imported = assembly.MainModule.ImportReference(dataType); + readFuncs[imported] = methodReference; + } + + void RegisterReadFunc(TypeReference typeReference, MethodDefinition newReaderFunc) + { + Register(typeReference, newReaderFunc); + GeneratedCodeClass.Methods.Add(newReaderFunc); + } + + // Finds existing reader for type, if non exists trys to create one + public MethodReference GetReadFunc(TypeReference variable, ref bool WeavingFailed) + { + if (readFuncs.TryGetValue(variable, out MethodReference foundFunc)) + return foundFunc; + + TypeReference importedVariable = assembly.MainModule.ImportReference(variable); + return GenerateReader(importedVariable, ref WeavingFailed); + } + + MethodReference GenerateReader(TypeReference variableReference, ref bool WeavingFailed) + { + // Arrays are special, if we resolve them, we get the element type, + // so the following ifs might choke on it for scriptable objects + // or other objects that require a custom serializer + // thus check if it is an array and skip all the checks. + if (variableReference.IsArray) + { + if (variableReference.IsMultidimensionalArray()) + { + Log.Error($"{variableReference.Name} is an unsupported type. Multidimensional arrays are not supported", variableReference); + WeavingFailed = true; + return null; + } + + return GenerateReadCollection(variableReference, variableReference.GetElementType(), nameof(NetworkReaderExtensions.ReadArray), ref WeavingFailed); + } + + TypeDefinition variableDefinition = variableReference.Resolve(); + + // check if the type is completely invalid + if (variableDefinition == null) + { + Log.Error($"{variableReference.Name} is not a supported type", variableReference); + WeavingFailed = true; + return null; + } + else if (variableReference.IsByReference) + { + // error?? + Log.Error($"Cannot pass type {variableReference.Name} by reference", variableReference); + WeavingFailed = true; + return null; + } + + // use existing func for known types + if (variableDefinition.IsEnum) + { + return GenerateEnumReadFunc(variableReference, ref WeavingFailed); + } + else if (variableDefinition.Is(typeof(ArraySegment<>))) + { + return GenerateArraySegmentReadFunc(variableReference, ref WeavingFailed); + } + else if (variableDefinition.Is(typeof(List<>))) + { + GenericInstanceType genericInstance = (GenericInstanceType)variableReference; + TypeReference elementType = genericInstance.GenericArguments[0]; + + return GenerateReadCollection(variableReference, elementType, nameof(NetworkReaderExtensions.ReadList), ref WeavingFailed); + } + // handle both NetworkBehaviour and inheritors. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/2939 + else if (variableReference.IsDerivedFrom() || variableReference.Is()) + { + return GetNetworkBehaviourReader(variableReference); + } + + // check if reader generation is applicable on this type + if (variableDefinition.IsDerivedFrom()) + { + Log.Error($"Cannot generate reader for component type {variableReference.Name}. Use a supported type or provide a custom reader", variableReference); + WeavingFailed = true; + return null; + } + if (variableReference.Is()) + { + Log.Error($"Cannot generate reader for {variableReference.Name}. Use a supported type or provide a custom reader", variableReference); + WeavingFailed = true; + return null; + } + if (variableReference.Is()) + { + Log.Error($"Cannot generate reader for {variableReference.Name}. Use a supported type or provide a custom reader", variableReference); + WeavingFailed = true; + return null; + } + if (variableDefinition.HasGenericParameters) + { + Log.Error($"Cannot generate reader for generic variable {variableReference.Name}. Use a supported type or provide a custom reader", variableReference); + WeavingFailed = true; + return null; + } + if (variableDefinition.IsInterface) + { + Log.Error($"Cannot generate reader for interface {variableReference.Name}. Use a supported type or provide a custom reader", variableReference); + WeavingFailed = true; + return null; + } + if (variableDefinition.IsAbstract) + { + Log.Error($"Cannot generate reader for abstract class {variableReference.Name}. Use a supported type or provide a custom reader", variableReference); + WeavingFailed = true; + return null; + } + + return GenerateClassOrStructReadFunction(variableReference, ref WeavingFailed); + } + + MethodReference GetNetworkBehaviourReader(TypeReference variableReference) + { + // uses generic ReadNetworkBehaviour rather than having weaver create one for each NB + MethodReference generic = weaverTypes.readNetworkBehaviourGeneric; + + MethodReference readFunc = generic.MakeGeneric(assembly.MainModule, variableReference); + + // register function so it is added to Reader + // use Register instead of RegisterWriteFunc because this is not a generated function + Register(variableReference, readFunc); + + return readFunc; + } + + MethodDefinition GenerateEnumReadFunc(TypeReference variable, ref bool WeavingFailed) + { + MethodDefinition readerFunc = GenerateReaderFunction(variable); + + ILProcessor worker = readerFunc.Body.GetILProcessor(); + + worker.Emit(OpCodes.Ldarg_0); + + TypeReference underlyingType = variable.Resolve().GetEnumUnderlyingType(); + MethodReference underlyingFunc = GetReadFunc(underlyingType, ref WeavingFailed); + + worker.Emit(OpCodes.Call, underlyingFunc); + worker.Emit(OpCodes.Ret); + return readerFunc; + } + + MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable, ref bool WeavingFailed) + { + GenericInstanceType genericInstance = (GenericInstanceType)variable; + TypeReference elementType = genericInstance.GenericArguments[0]; + + MethodDefinition readerFunc = GenerateReaderFunction(variable); + + ILProcessor worker = readerFunc.Body.GetILProcessor(); + + // $array = reader.Read<[T]>() + ArrayType arrayType = elementType.MakeArrayType(); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Call, GetReadFunc(arrayType, ref WeavingFailed)); + + // return new ArraySegment($array); + worker.Emit(OpCodes.Newobj, weaverTypes.ArraySegmentConstructorReference.MakeHostInstanceGeneric(assembly.MainModule, genericInstance)); + worker.Emit(OpCodes.Ret); + return readerFunc; + } + + MethodDefinition GenerateReaderFunction(TypeReference variable) + { + string functionName = $"_Read_{variable.FullName}"; + + // create new reader for this type + MethodDefinition readerFunc = new MethodDefinition(functionName, + MethodAttributes.Public | + MethodAttributes.Static | + MethodAttributes.HideBySig, + variable); + + readerFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, weaverTypes.Import())); + readerFunc.Body.InitLocals = true; + RegisterReadFunc(variable, readerFunc); + + return readerFunc; + } + + MethodDefinition GenerateReadCollection(TypeReference variable, TypeReference elementType, string readerFunction, ref bool WeavingFailed) + { + MethodDefinition readerFunc = GenerateReaderFunction(variable); + // generate readers for the element + GetReadFunc(elementType, ref WeavingFailed); + + ModuleDefinition module = assembly.MainModule; + TypeReference readerExtensions = module.ImportReference(typeof(NetworkReaderExtensions)); + MethodReference listReader = Resolvers.ResolveMethod(readerExtensions, assembly, Log, readerFunction, ref WeavingFailed); + + GenericInstanceMethod methodRef = new GenericInstanceMethod(listReader); + methodRef.GenericArguments.Add(elementType); + + // generates + // return reader.ReadList(); + + ILProcessor worker = readerFunc.Body.GetILProcessor(); + worker.Emit(OpCodes.Ldarg_0); // reader + worker.Emit(OpCodes.Call, methodRef); // Read + + worker.Emit(OpCodes.Ret); + + return readerFunc; + } + + MethodDefinition GenerateClassOrStructReadFunction(TypeReference variable, ref bool WeavingFailed) + { + MethodDefinition readerFunc = GenerateReaderFunction(variable); + + // create local for return value + readerFunc.Body.Variables.Add(new VariableDefinition(variable)); + + ILProcessor worker = readerFunc.Body.GetILProcessor(); + + TypeDefinition td = variable.Resolve(); + + if (!td.IsValueType) + GenerateNullCheck(worker, ref WeavingFailed); + + CreateNew(variable, worker, td, ref WeavingFailed); + ReadAllFields(variable, worker, ref WeavingFailed); + + worker.Emit(OpCodes.Ldloc_0); + worker.Emit(OpCodes.Ret); + return readerFunc; + } + + void GenerateNullCheck(ILProcessor worker, ref bool WeavingFailed) + { + // if (!reader.ReadBoolean()) { + // return null; + // } + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Call, GetReadFunc(weaverTypes.Import(), ref WeavingFailed)); + + Instruction labelEmptyArray = worker.Create(OpCodes.Nop); + worker.Emit(OpCodes.Brtrue, labelEmptyArray); + // return null + worker.Emit(OpCodes.Ldnull); + worker.Emit(OpCodes.Ret); + worker.Append(labelEmptyArray); + } + + // Initialize the local variable with a new instance + void CreateNew(TypeReference variable, ILProcessor worker, TypeDefinition td, ref bool WeavingFailed) + { + if (variable.IsValueType) + { + // structs are created with Initobj + worker.Emit(OpCodes.Ldloca, 0); + worker.Emit(OpCodes.Initobj, variable); + } + else if (td.IsDerivedFrom()) + { + GenericInstanceMethod genericInstanceMethod = new GenericInstanceMethod(weaverTypes.ScriptableObjectCreateInstanceMethod); + genericInstanceMethod.GenericArguments.Add(variable); + worker.Emit(OpCodes.Call, genericInstanceMethod); + worker.Emit(OpCodes.Stloc_0); + } + else + { + // classes are created with their constructor + MethodDefinition ctor = Resolvers.ResolveDefaultPublicCtor(variable); + if (ctor == null) + { + Log.Error($"{variable.Name} can't be deserialized because it has no default constructor. Don't use {variable.Name} in [SyncVar]s, Rpcs, Cmds, etc.", variable); + WeavingFailed = true; + return; + } + + MethodReference ctorRef = assembly.MainModule.ImportReference(ctor); + + worker.Emit(OpCodes.Newobj, ctorRef); + worker.Emit(OpCodes.Stloc_0); + } + } + + void ReadAllFields(TypeReference variable, ILProcessor worker, ref bool WeavingFailed) + { + foreach (FieldDefinition field in variable.FindAllPublicFields()) + { + // mismatched ldloca/ldloc for struct/class combinations is invalid IL, which causes crash at runtime + OpCode opcode = variable.IsValueType ? OpCodes.Ldloca : OpCodes.Ldloc; + worker.Emit(opcode, 0); + MethodReference readFunc = GetReadFunc(field.FieldType, ref WeavingFailed); + if (readFunc != null) + { + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Call, readFunc); + } + else + { + Log.Error($"{field.Name} has an unsupported type", field); + WeavingFailed = true; + } + FieldReference fieldRef = assembly.MainModule.ImportReference(field); + + worker.Emit(OpCodes.Stfld, fieldRef); + } + } + + // Save a delegate for each one of the readers into Reader.read + internal void InitializeReaders(ILProcessor worker) + { + ModuleDefinition module = assembly.MainModule; + + TypeReference genericReaderClassRef = module.ImportReference(typeof(Reader<>)); + + System.Reflection.FieldInfo fieldInfo = typeof(Reader<>).GetField(nameof(Reader.read)); + FieldReference fieldRef = module.ImportReference(fieldInfo); + TypeReference networkReaderRef = module.ImportReference(typeof(NetworkReader)); + TypeReference funcRef = module.ImportReference(typeof(Func<,>)); + MethodReference funcConstructorRef = module.ImportReference(typeof(Func<,>).GetConstructors()[0]); + + foreach (KeyValuePair kvp in readFuncs) + { + TypeReference targetType = kvp.Key; + MethodReference readFunc = kvp.Value; + + // create a Func delegate + worker.Emit(OpCodes.Ldnull); + worker.Emit(OpCodes.Ldftn, readFunc); + GenericInstanceType funcGenericInstance = funcRef.MakeGenericInstanceType(networkReaderRef, targetType); + MethodReference funcConstructorInstance = funcConstructorRef.MakeHostInstanceGeneric(assembly.MainModule, funcGenericInstance); + worker.Emit(OpCodes.Newobj, funcConstructorInstance); + + // save it in Reader.read + GenericInstanceType genericInstance = genericReaderClassRef.MakeGenericInstanceType(targetType); + FieldReference specializedField = fieldRef.SpecializeField(assembly.MainModule, genericInstance); + worker.Emit(OpCodes.Stsfld, specializedField); + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Readers.cs.meta b/Assets/Mirror/Editor/Weaver/Readers.cs.meta new file mode 100644 index 0000000..838ff59 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Readers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be40277098a024539bf63d0205cae824 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Resolvers.cs b/Assets/Mirror/Editor/Weaver/Resolvers.cs new file mode 100644 index 0000000..0af32ca --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Resolvers.cs @@ -0,0 +1,126 @@ +// all the resolve functions for the weaver +// NOTE: these functions should be made extensions, but right now they still +// make heavy use of Weaver.fail and we'd have to check each one's return +// value for null otherwise. +// (original FieldType.Resolve returns null if not found too, so +// exceptions would be a bit inconsistent here) +using Mono.CecilX; + +namespace Mirror.Weaver +{ + public static class Resolvers + { + public static MethodReference ResolveMethod(TypeReference tr, AssemblyDefinition assembly, Logger Log, string name, ref bool WeavingFailed) + { + if (tr == null) + { + Log.Error($"Cannot resolve method {name} without a class"); + WeavingFailed = true; + return null; + } + MethodReference method = ResolveMethod(tr, assembly, Log, m => m.Name == name, ref WeavingFailed); + if (method == null) + { + Log.Error($"Method not found with name {name} in type {tr.Name}", tr); + WeavingFailed = true; + } + return method; + } + + public static MethodReference ResolveMethod(TypeReference t, AssemblyDefinition assembly, Logger Log, System.Func predicate, ref bool WeavingFailed) + { + foreach (MethodDefinition methodRef in t.Resolve().Methods) + { + if (predicate(methodRef)) + { + return assembly.MainModule.ImportReference(methodRef); + } + } + + Log.Error($"Method not found in type {t.Name}", t); + WeavingFailed = true; + return null; + } + + public static FieldReference ResolveField(TypeReference tr, AssemblyDefinition assembly, Logger Log, string name, ref bool WeavingFailed) + { + if (tr == null) + { + Log.Error($"Cannot resolve Field {name} without a class"); + WeavingFailed = true; + return null; + } + FieldReference field = ResolveField(tr, assembly, Log, m => m.Name == name, ref WeavingFailed); + if (field == null) + { + Log.Error($"Field not found with name {name} in type {tr.Name}", tr); + WeavingFailed = true; + } + return field; + } + + public static FieldReference ResolveField(TypeReference t, AssemblyDefinition assembly, Logger Log, System.Func predicate, ref bool WeavingFailed) + { + foreach (FieldDefinition fieldRef in t.Resolve().Fields) + { + if (predicate(fieldRef)) + { + return assembly.MainModule.ImportReference(fieldRef); + } + } + + Log.Error($"Field not found in type {t.Name}", t); + WeavingFailed = true; + return null; + } + + public static MethodReference TryResolveMethodInParents(TypeReference tr, AssemblyDefinition assembly, string name) + { + if (tr == null) + { + return null; + } + foreach (MethodDefinition methodDef in tr.Resolve().Methods) + { + if (methodDef.Name == name) + { + MethodReference methodRef = methodDef; + if (tr.IsGenericInstance) + { + methodRef = methodRef.MakeHostInstanceGeneric(tr.Module, (GenericInstanceType)tr); + } + return assembly.MainModule.ImportReference(methodRef); + } + } + + // Could not find the method in this class, try the parent + return TryResolveMethodInParents(tr.Resolve().BaseType.ApplyGenericParameters(tr), assembly, name); + } + + public static MethodDefinition ResolveDefaultPublicCtor(TypeReference variable) + { + foreach (MethodDefinition methodRef in variable.Resolve().Methods) + { + if (methodRef.Name == ".ctor" && + methodRef.Resolve().IsPublic && + methodRef.Parameters.Count == 0) + { + return methodRef; + } + } + return null; + } + + public static MethodReference ResolveProperty(TypeReference tr, AssemblyDefinition assembly, string name) + { + foreach (PropertyDefinition pd in tr.Resolve().Properties) + { + if (pd.Name == name) + { + return assembly.MainModule.ImportReference(pd.GetMethod); + } + } + return null; + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Resolvers.cs.meta b/Assets/Mirror/Editor/Weaver/Resolvers.cs.meta new file mode 100644 index 0000000..f4f6602 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Resolvers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3039a59c76aec43c797ad66930430367 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/SyncVarAccessLists.cs b/Assets/Mirror/Editor/Weaver/SyncVarAccessLists.cs new file mode 100644 index 0000000..fa7a682 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/SyncVarAccessLists.cs @@ -0,0 +1,32 @@ +// tracks SyncVar read/write access when processing NetworkBehaviour, +// to later be replaced by SyncVarAccessReplacer. +using System.Collections.Generic; +using Mono.CecilX; + +namespace Mirror.Weaver +{ + // This data is flushed each time - if we are run multiple times in the same process/domain + public class SyncVarAccessLists + { + // setter functions that replace [SyncVar] member variable references. dict + public Dictionary replacementSetterProperties = + new Dictionary(); + + // getter functions that replace [SyncVar] member variable references. dict + public Dictionary replacementGetterProperties = + new Dictionary(); + + // amount of SyncVars per class. dict + // necessary for SyncVar dirty bits, where inheriting classes start + // their dirty bits at base class SyncVar amount. + public Dictionary numSyncVars = new Dictionary(); + + public int GetSyncVarStart(string className) => + numSyncVars.TryGetValue(className, out int value) ? value : 0; + + public void SetNumSyncVars(string className, int num) + { + numSyncVars[className] = num; + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/SyncVarAccessLists.cs.meta b/Assets/Mirror/Editor/Weaver/SyncVarAccessLists.cs.meta new file mode 100644 index 0000000..9a4da44 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/SyncVarAccessLists.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6905230c3c4c4e158760065a93380e83 +timeCreated: 1629348618 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/TypeReferenceComparer.cs b/Assets/Mirror/Editor/Weaver/TypeReferenceComparer.cs new file mode 100644 index 0000000..e3c31d5 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/TypeReferenceComparer.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Mono.CecilX; + +namespace Mirror.Weaver +{ + // Compares TypeReference using FullName + public class TypeReferenceComparer : IEqualityComparer + { + public bool Equals(TypeReference x, TypeReference y) => + x.FullName == y.FullName; + + public int GetHashCode(TypeReference obj) => + obj.FullName.GetHashCode(); + } +} diff --git a/Assets/Mirror/Editor/Weaver/TypeReferenceComparer.cs.meta b/Assets/Mirror/Editor/Weaver/TypeReferenceComparer.cs.meta new file mode 100644 index 0000000..890b4dc --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/TypeReferenceComparer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55eb9eb8794946f4da7ad39788c9920b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Unity.Mirror.CodeGen.asmdef b/Assets/Mirror/Editor/Weaver/Unity.Mirror.CodeGen.asmdef new file mode 100644 index 0000000..987382c --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Unity.Mirror.CodeGen.asmdef @@ -0,0 +1,21 @@ +{ + "name": "Unity.Mirror.CodeGen", + "rootNamespace": "", + "references": [ + "GUID:30817c1a0e6d646d99c048fc403f5979" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": true, + "precompiledReferences": [ + "Mono.CecilX.dll", + "Mono.CecilX.Rocks.dll" + ], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/Unity.Mirror.CodeGen.asmdef.meta b/Assets/Mirror/Editor/Weaver/Unity.Mirror.CodeGen.asmdef.meta new file mode 100644 index 0000000..b65a0cd --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Unity.Mirror.CodeGen.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1d0b9d21c3ff546a4aa32399dfd33474 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/Weaver.cs b/Assets/Mirror/Editor/Weaver/Weaver.cs new file mode 100644 index 0000000..3aef7b8 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Weaver.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Mono.CecilX; +using Mono.CecilX.Cil; +using Mono.CecilX.Rocks; + +namespace Mirror.Weaver +{ + // not static, because ILPostProcessor is multithreaded + internal class Weaver + { + // generated code class + public const string GeneratedCodeNamespace = "Mirror"; + public const string GeneratedCodeClassName = "GeneratedNetworkCode"; + TypeDefinition GeneratedCodeClass; + + // for resolving Mirror.dll in ReaderWriterProcessor, we need to know + // Mirror.dll name + public const string MirrorAssemblyName = "Mirror"; + + WeaverTypes weaverTypes; + SyncVarAccessLists syncVarAccessLists; + AssemblyDefinition CurrentAssembly; + Writers writers; + Readers readers; + + // in case of weaver errors, we don't stop immediately. + // we log all errors and then eventually return false if + // weaving has failed. + // this way the user can fix multiple errors at once, instead of having + // to fix -> recompile -> fix -> recompile for one error at a time. + bool WeavingFailed; + + // logger functions can be set from the outside. + // for example, Debug.Log or ILPostProcessor Diagnostics log for + // multi threaded logging. + public Logger Log; + + // remote actions now support overloads, + // -> but IL2CPP doesnt like it when two generated methods + // -> have the same signature, + // -> so, append the signature to the generated method name, + // -> to create a unique name + // Example: + // RpcTeleport(Vector3 position) -> InvokeUserCode_RpcTeleport__Vector3() + // RpcTeleport(Vector3 position, Quaternion rotation) -> InvokeUserCode_RpcTeleport__Vector3Quaternion() + // fixes https://github.com/vis2k/Mirror/issues/3060 + public static string GenerateMethodName(string initialPrefix, MethodDefinition md) + { + initialPrefix += md.Name; + + for (int i = 0; i < md.Parameters.Count; ++i) + { + // with __ so it's more obvious that this is the parameter suffix. + // otherwise RpcTest(int) => RpcTestInt(int) which is not obvious. + initialPrefix += $"__{md.Parameters[i].ParameterType.Name}"; + } + + return initialPrefix; + } + + public Weaver(Logger Log) + { + this.Log = Log; + } + + // returns 'true' if modified (=if we did anything) + bool WeaveNetworkBehavior(TypeDefinition td) + { + if (!td.IsClass) + return false; + + if (!td.IsDerivedFrom()) + { + if (td.IsDerivedFrom()) + MonoBehaviourProcessor.Process(Log, td, ref WeavingFailed); + return false; + } + + // process this and base classes from parent to child order + + List behaviourClasses = new List(); + + TypeDefinition parent = td; + while (parent != null) + { + if (parent.Is()) + { + break; + } + + try + { + behaviourClasses.Insert(0, parent); + parent = parent.BaseType.Resolve(); + } + catch (AssemblyResolutionException) + { + // this can happen for plugins. + //Console.WriteLine("AssemblyResolutionException: "+ ex.ToString()); + break; + } + } + + bool modified = false; + foreach (TypeDefinition behaviour in behaviourClasses) + { + modified |= new NetworkBehaviourProcessor(CurrentAssembly, weaverTypes, syncVarAccessLists, writers, readers, Log, behaviour).Process(ref WeavingFailed); + } + return modified; + } + + bool WeaveModule(ModuleDefinition moduleDefinition) + { + bool modified = false; + + Stopwatch watch = Stopwatch.StartNew(); + watch.Start(); + + // ModuleDefinition.Types only finds top level types. + // GetAllTypes recursively finds all nested types as well. + // fixes nested types not being weaved, for example: + // class Parent { // ModuleDefinition.Types finds this + // class Child { // .Types.NestedTypes finds this + // class GrandChild {} // only GetAllTypes finds this too + // } + // } + // note this is not about inheritance, only about type definitions. + // see test: NetworkBehaviourTests.DeeplyNested() + foreach (TypeDefinition td in moduleDefinition.GetAllTypes()) + { + if (td.IsClass && td.BaseType.CanBeResolved()) + { + modified |= WeaveNetworkBehavior(td); + modified |= ServerClientAttributeProcessor.Process(weaverTypes, Log, td, ref WeavingFailed); + } + } + + watch.Stop(); + Console.WriteLine($"Weave behaviours and messages took {watch.ElapsedMilliseconds} milliseconds"); + + return modified; + } + + void CreateGeneratedCodeClass() + { + // create "Mirror.GeneratedNetworkCode" class which holds all + // Readers and Writers + GeneratedCodeClass = new TypeDefinition(GeneratedCodeNamespace, GeneratedCodeClassName, + TypeAttributes.BeforeFieldInit | TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Abstract | TypeAttributes.Sealed, + weaverTypes.Import()); + } + + void ToggleWeaverFuse() + { + // // find Weaved() function + MethodDefinition func = weaverTypes.weaverFuseMethod.Resolve(); + // // change return 0 to return 1 + + ILProcessor worker = func.Body.GetILProcessor(); + func.Body.Instructions[0] = worker.Create(OpCodes.Ldc_I4_1); + } + + // Weave takes an AssemblyDefinition to be compatible with both old and + // new weavers: + // * old takes a filepath, new takes a in-memory byte[] + // * old uses DefaultAssemblyResolver with added dependencies paths, + // new uses ...? + // + // => assembly: the one we are currently weaving (MyGame.dll) + // => resolver: useful in case we need to resolve any of the assembly's + // assembly.MainModule.AssemblyReferences. + // -> we can resolve ANY of them given that the resolver + // works properly (need custom one for ILPostProcessor) + // -> IMPORTANT: .Resolve() takes an AssemblyNameReference. + // those from assembly.MainModule.AssemblyReferences are + // guaranteed to be resolve-able. + // Parsing from a string for Library/.../Mirror.dll + // would not be guaranteed to be resolve-able because + // for ILPostProcessor we can't assume where Mirror.dll + // is etc. + public bool Weave(AssemblyDefinition assembly, IAssemblyResolver resolver, out bool modified) + { + WeavingFailed = false; + modified = false; + try + { + CurrentAssembly = assembly; + + // fix "No writer found for ..." error + // https://github.com/vis2k/Mirror/issues/2579 + // -> when restarting Unity, weaver would try to weave a DLL + // again + // -> resulting in two GeneratedNetworkCode classes (see ILSpy) + // -> the second one wouldn't have all the writer types setup + if (CurrentAssembly.MainModule.ContainsClass(GeneratedCodeNamespace, GeneratedCodeClassName)) + { + //Log.Warning($"Weaver: skipping {CurrentAssembly.Name} because already weaved"); + return true; + } + + weaverTypes = new WeaverTypes(CurrentAssembly, Log, ref WeavingFailed); + + // weaverTypes are needed for CreateGeneratedCodeClass + CreateGeneratedCodeClass(); + + // WeaverList depends on WeaverTypes setup because it uses Import + syncVarAccessLists = new SyncVarAccessLists(); + + // initialize readers & writers with this assembly. + // we need to do this in every Process() call. + // otherwise we would get + // "System.ArgumentException: Member ... is declared in another module and needs to be imported" + // errors when still using the previous module's reader/writer funcs. + writers = new Writers(CurrentAssembly, weaverTypes, GeneratedCodeClass, Log); + readers = new Readers(CurrentAssembly, weaverTypes, GeneratedCodeClass, Log); + + Stopwatch rwstopwatch = Stopwatch.StartNew(); + // Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages + modified = ReaderWriterProcessor.Process(CurrentAssembly, resolver, Log, writers, readers, ref WeavingFailed); + rwstopwatch.Stop(); + Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds"); + + ModuleDefinition moduleDefinition = CurrentAssembly.MainModule; + Console.WriteLine($"Script Module: {moduleDefinition.Name}"); + + modified |= WeaveModule(moduleDefinition); + + if (WeavingFailed) + { + return false; + } + + if (modified) + { + SyncVarAttributeAccessReplacer.Process(Log, moduleDefinition, syncVarAccessLists); + + // add class that holds read/write functions + moduleDefinition.Types.Add(GeneratedCodeClass); + + ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly, weaverTypes, writers, readers, GeneratedCodeClass); + + // DO NOT WRITE here. + // CompilationFinishedHook writes to the file. + // ILPostProcessor writes to in-memory assembly. + // it depends on the caller. + //CurrentAssembly.Write(new WriterParameters{ WriteSymbols = true }); + } + + // if weaving succeeded, switch on the Weaver Fuse in Mirror.dll + if (CurrentAssembly.Name.Name == MirrorAssemblyName) + { + ToggleWeaverFuse(); + } + + return true; + } + catch (Exception e) + { + Log.Error($"Exception :{e}"); + WeavingFailed = true; + return false; + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Weaver.cs.meta b/Assets/Mirror/Editor/Weaver/Weaver.cs.meta new file mode 100644 index 0000000..0ea2dfe --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Weaver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de160f52931054064852f2afd7e7a86f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/WeaverExceptions.cs b/Assets/Mirror/Editor/Weaver/WeaverExceptions.cs new file mode 100644 index 0000000..efedd27 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/WeaverExceptions.cs @@ -0,0 +1,26 @@ +using System; +using System.Runtime.Serialization; +using Mono.CecilX; + +namespace Mirror.Weaver +{ + [Serializable] + public abstract class WeaverException : Exception + { + public MemberReference MemberReference { get; } + + protected WeaverException(string message, MemberReference member) : base(message) + { + MemberReference = member; + } + + protected WeaverException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) {} + } + + [Serializable] + public class GenerateWriterException : WeaverException + { + public GenerateWriterException(string message, MemberReference member) : base(message, member) {} + protected GenerateWriterException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) {} + } +} diff --git a/Assets/Mirror/Editor/Weaver/WeaverExceptions.cs.meta b/Assets/Mirror/Editor/Weaver/WeaverExceptions.cs.meta new file mode 100644 index 0000000..68643b2 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/WeaverExceptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8aaaf6193bad7424492677f8e81f1b30 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Weaver/WeaverTypes.cs b/Assets/Mirror/Editor/Weaver/WeaverTypes.cs new file mode 100644 index 0000000..aa0d42d --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/WeaverTypes.cs @@ -0,0 +1,171 @@ +using System; +using Mono.CecilX; +using UnityEditor; +using UnityEngine; + +namespace Mirror.Weaver +{ + // not static, because ILPostProcessor is multithreaded + public class WeaverTypes + { + public MethodReference ScriptableObjectCreateInstanceMethod; + + public FieldReference NetworkBehaviourDirtyBitsReference; + public MethodReference GetWriterReference; + public MethodReference ReturnWriterReference; + + public MethodReference NetworkClientConnectionReference; + + public MethodReference RemoteCallDelegateConstructor; + + public MethodReference NetworkServerGetActive; + public MethodReference NetworkClientGetActive; + + // custom attribute types + public MethodReference InitSyncObjectReference; + + // array segment + public MethodReference ArraySegmentConstructorReference; + + // Action for SyncVar Hooks + public MethodReference ActionT_T; + + // syncvar + public MethodReference generatedSyncVarSetter; + public MethodReference generatedSyncVarSetter_GameObject; + public MethodReference generatedSyncVarSetter_NetworkIdentity; + public MethodReference generatedSyncVarSetter_NetworkBehaviour_T; + public MethodReference generatedSyncVarDeserialize; + public MethodReference generatedSyncVarDeserialize_GameObject; + public MethodReference generatedSyncVarDeserialize_NetworkIdentity; + public MethodReference generatedSyncVarDeserialize_NetworkBehaviour_T; + public MethodReference getSyncVarGameObjectReference; + public MethodReference getSyncVarNetworkIdentityReference; + public MethodReference getSyncVarNetworkBehaviourReference; + public MethodReference registerCommandReference; + public MethodReference registerRpcReference; + public MethodReference getTypeFromHandleReference; + public MethodReference logErrorReference; + public MethodReference logWarningReference; + public MethodReference sendCommandInternal; + public MethodReference sendRpcInternal; + public MethodReference sendTargetRpcInternal; + + public MethodReference readNetworkBehaviourGeneric; + + public TypeReference weaverFuseType; + public MethodReference weaverFuseMethod; + + // attributes + public TypeDefinition initializeOnLoadMethodAttribute; + public TypeDefinition runtimeInitializeOnLoadMethodAttribute; + + AssemblyDefinition assembly; + + public TypeReference Import() => Import(typeof(T)); + + public TypeReference Import(Type t) => assembly.MainModule.ImportReference(t); + + // constructor resolves the types and stores them in fields + public WeaverTypes(AssemblyDefinition assembly, Logger Log, ref bool WeavingFailed) + { + // system types + this.assembly = assembly; + + TypeReference ArraySegmentType = Import(typeof(ArraySegment<>)); + ArraySegmentConstructorReference = Resolvers.ResolveMethod(ArraySegmentType, assembly, Log, ".ctor", ref WeavingFailed); + + TypeReference ActionType = Import(typeof(Action<,>)); + ActionT_T = Resolvers.ResolveMethod(ActionType, assembly, Log, ".ctor", ref WeavingFailed); + + weaverFuseType = Import(typeof(WeaverFuse)); + weaverFuseMethod = Resolvers.ResolveMethod(weaverFuseType, assembly, Log, "Weaved", ref WeavingFailed); + + TypeReference NetworkServerType = Import(typeof(NetworkServer)); + NetworkServerGetActive = Resolvers.ResolveMethod(NetworkServerType, assembly, Log, "get_active", ref WeavingFailed); + + TypeReference NetworkClientType = Import(typeof(NetworkClient)); + NetworkClientGetActive = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_active", ref WeavingFailed); + NetworkClientConnectionReference = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_connection", ref WeavingFailed); + + TypeReference NetworkBehaviourType = Import(); + + NetworkBehaviourDirtyBitsReference = Resolvers.ResolveField(NetworkBehaviourType, assembly, Log, "syncVarDirtyBits", ref WeavingFailed); + + generatedSyncVarSetter = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter", ref WeavingFailed); + generatedSyncVarSetter_GameObject = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter_GameObject", ref WeavingFailed); + generatedSyncVarSetter_NetworkIdentity = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter_NetworkIdentity", ref WeavingFailed); + generatedSyncVarSetter_NetworkBehaviour_T = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter_NetworkBehaviour", ref WeavingFailed); + + generatedSyncVarDeserialize_GameObject = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarDeserialize_GameObject", ref WeavingFailed); + generatedSyncVarDeserialize = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarDeserialize", ref WeavingFailed); + generatedSyncVarDeserialize_NetworkIdentity = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarDeserialize_NetworkIdentity", ref WeavingFailed); + generatedSyncVarDeserialize_NetworkBehaviour_T = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarDeserialize_NetworkBehaviour", ref WeavingFailed); + + getSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarGameObject", ref WeavingFailed); + getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarNetworkIdentity", ref WeavingFailed); + getSyncVarNetworkBehaviourReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarNetworkBehaviour", ref WeavingFailed); + + sendCommandInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendCommandInternal", ref WeavingFailed); + sendRpcInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendRPCInternal", ref WeavingFailed); + sendTargetRpcInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendTargetRPCInternal", ref WeavingFailed); + + InitSyncObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "InitSyncObject", ref WeavingFailed); + + TypeReference RemoteProcedureCallsType = Import(typeof(RemoteCalls.RemoteProcedureCalls)); + registerCommandReference = Resolvers.ResolveMethod(RemoteProcedureCallsType, assembly, Log, "RegisterCommand", ref WeavingFailed); + registerRpcReference = Resolvers.ResolveMethod(RemoteProcedureCallsType, assembly, Log, "RegisterRpc", ref WeavingFailed); + + TypeReference RemoteCallDelegateType = Import(); + RemoteCallDelegateConstructor = Resolvers.ResolveMethod(RemoteCallDelegateType, assembly, Log, ".ctor", ref WeavingFailed); + + TypeReference ScriptableObjectType = Import(); + ScriptableObjectCreateInstanceMethod = Resolvers.ResolveMethod( + ScriptableObjectType, assembly, Log, + md => md.Name == "CreateInstance" && md.HasGenericParameters, + ref WeavingFailed); + + TypeReference unityDebug = Import(typeof(UnityEngine.Debug)); + // these have multiple methods with same name, so need to check parameters too + logErrorReference = Resolvers.ResolveMethod(unityDebug, assembly, Log, md => + md.Name == "LogError" && + md.Parameters.Count == 1 && + md.Parameters[0].ParameterType.FullName == typeof(object).FullName, + ref WeavingFailed); + + logWarningReference = Resolvers.ResolveMethod(unityDebug, assembly, Log, md => + md.Name == "LogWarning" && + md.Parameters.Count == 1 && + md.Parameters[0].ParameterType.FullName == typeof(object).FullName, + ref WeavingFailed); + + TypeReference typeType = Import(typeof(Type)); + getTypeFromHandleReference = Resolvers.ResolveMethod(typeType, assembly, Log, "GetTypeFromHandle", ref WeavingFailed); + + TypeReference NetworkWriterPoolType = Import(typeof(NetworkWriterPool)); + GetWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, assembly, Log, "Get", ref WeavingFailed); + ReturnWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, assembly, Log, "Return", ref WeavingFailed); + + TypeReference readerExtensions = Import(typeof(NetworkReaderExtensions)); + readNetworkBehaviourGeneric = Resolvers.ResolveMethod(readerExtensions, assembly, Log, (md => + { + return md.Name == nameof(NetworkReaderExtensions.ReadNetworkBehaviour) && + md.HasGenericParameters; + }), + ref WeavingFailed); + + // [InitializeOnLoadMethod] + // 'UnityEditor' is not available in builds. + // we can only import this attribute if we are in an Editor assembly. + if (Helpers.IsEditorAssembly(assembly)) + { + TypeReference initializeOnLoadMethodAttributeRef = Import(typeof(InitializeOnLoadMethodAttribute)); + initializeOnLoadMethodAttribute = initializeOnLoadMethodAttributeRef.Resolve(); + } + + // [RuntimeInitializeOnLoadMethod] + TypeReference runtimeInitializeOnLoadMethodAttributeRef = Import(typeof(RuntimeInitializeOnLoadMethodAttribute)); + runtimeInitializeOnLoadMethodAttribute = runtimeInitializeOnLoadMethodAttributeRef.Resolve(); + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/WeaverTypes.cs.meta b/Assets/Mirror/Editor/Weaver/WeaverTypes.cs.meta new file mode 100644 index 0000000..d71c33f --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/WeaverTypes.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2585961bf7fe4c10a9143f4087efdf6f +timeCreated: 1596486854 \ No newline at end of file diff --git a/Assets/Mirror/Editor/Weaver/Writers.cs b/Assets/Mirror/Editor/Weaver/Writers.cs new file mode 100644 index 0000000..8311a26 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Writers.cs @@ -0,0 +1,341 @@ +using System; +using System.Collections.Generic; +using Mono.CecilX; +using Mono.CecilX.Cil; +// to use Mono.CecilX.Rocks here, we need to 'override references' in the +// Unity.Mirror.CodeGen assembly definition file in the Editor, and add CecilX.Rocks. +// otherwise we get an unknown import exception. +using Mono.CecilX.Rocks; + +namespace Mirror.Weaver +{ + // not static, because ILPostProcessor is multithreaded + public class Writers + { + // Writers are only for this assembly. + // can't be used from another assembly, otherwise we will get: + // "System.ArgumentException: Member ... is declared in another module and needs to be imported" + AssemblyDefinition assembly; + WeaverTypes weaverTypes; + TypeDefinition GeneratedCodeClass; + Logger Log; + + Dictionary writeFuncs = + new Dictionary(new TypeReferenceComparer()); + + public Writers(AssemblyDefinition assembly, WeaverTypes weaverTypes, TypeDefinition GeneratedCodeClass, Logger Log) + { + this.assembly = assembly; + this.weaverTypes = weaverTypes; + this.GeneratedCodeClass = GeneratedCodeClass; + this.Log = Log; + } + + public void Register(TypeReference dataType, MethodReference methodReference) + { + if (writeFuncs.ContainsKey(dataType)) + { + // TODO enable this again later. + // Writer has some obsolete functions that were renamed. + // Don't want weaver warnings for all of them. + //Log.Warning($"Registering a Write method for {dataType.FullName} when one already exists", methodReference); + } + + // we need to import type when we Initialize Writers so import here in case it is used anywhere else + TypeReference imported = assembly.MainModule.ImportReference(dataType); + writeFuncs[imported] = methodReference; + } + + void RegisterWriteFunc(TypeReference typeReference, MethodDefinition newWriterFunc) + { + Register(typeReference, newWriterFunc); + GeneratedCodeClass.Methods.Add(newWriterFunc); + } + + // Finds existing writer for type, if non exists trys to create one + public MethodReference GetWriteFunc(TypeReference variable, ref bool WeavingFailed) + { + if (writeFuncs.TryGetValue(variable, out MethodReference foundFunc)) + return foundFunc; + + // this try/catch will be removed in future PR and make `GetWriteFunc` throw instead + try + { + TypeReference importedVariable = assembly.MainModule.ImportReference(variable); + return GenerateWriter(importedVariable, ref WeavingFailed); + } + catch (GenerateWriterException e) + { + Log.Error(e.Message, e.MemberReference); + WeavingFailed = true; + return null; + } + } + + //Throws GenerateWriterException when writer could not be generated for type + MethodReference GenerateWriter(TypeReference variableReference, ref bool WeavingFailed) + { + if (variableReference.IsByReference) + { + throw new GenerateWriterException($"Cannot pass {variableReference.Name} by reference", variableReference); + } + + // Arrays are special, if we resolve them, we get the element type, + // e.g. int[] resolves to int + // therefore process this before checks below + if (variableReference.IsArray) + { + if (variableReference.IsMultidimensionalArray()) + { + throw new GenerateWriterException($"{variableReference.Name} is an unsupported type. Multidimensional arrays are not supported", variableReference); + } + TypeReference elementType = variableReference.GetElementType(); + return GenerateCollectionWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteArray), ref WeavingFailed); + } + + if (variableReference.Resolve()?.IsEnum ?? false) + { + // serialize enum as their base type + return GenerateEnumWriteFunc(variableReference, ref WeavingFailed); + } + + // check for collections + if (variableReference.Is(typeof(ArraySegment<>))) + { + GenericInstanceType genericInstance = (GenericInstanceType)variableReference; + TypeReference elementType = genericInstance.GenericArguments[0]; + + return GenerateCollectionWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteArraySegment), ref WeavingFailed); + } + if (variableReference.Is(typeof(List<>))) + { + GenericInstanceType genericInstance = (GenericInstanceType)variableReference; + TypeReference elementType = genericInstance.GenericArguments[0]; + + return GenerateCollectionWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteList), ref WeavingFailed); + } + + // handle both NetworkBehaviour and inheritors. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/2939 + if (variableReference.IsDerivedFrom() || variableReference.Is()) + { + return GetNetworkBehaviourWriter(variableReference); + } + + // check for invalid types + TypeDefinition variableDefinition = variableReference.Resolve(); + if (variableDefinition == null) + { + throw new GenerateWriterException($"{variableReference.Name} is not a supported type. Use a supported type or provide a custom writer", variableReference); + } + if (variableDefinition.IsDerivedFrom()) + { + throw new GenerateWriterException($"Cannot generate writer for component type {variableReference.Name}. Use a supported type or provide a custom writer", variableReference); + } + if (variableReference.Is()) + { + throw new GenerateWriterException($"Cannot generate writer for {variableReference.Name}. Use a supported type or provide a custom writer", variableReference); + } + if (variableReference.Is()) + { + throw new GenerateWriterException($"Cannot generate writer for {variableReference.Name}. Use a supported type or provide a custom writer", variableReference); + } + if (variableDefinition.HasGenericParameters) + { + throw new GenerateWriterException($"Cannot generate writer for generic type {variableReference.Name}. Use a supported type or provide a custom writer", variableReference); + } + if (variableDefinition.IsInterface) + { + throw new GenerateWriterException($"Cannot generate writer for interface {variableReference.Name}. Use a supported type or provide a custom writer", variableReference); + } + if (variableDefinition.IsAbstract) + { + throw new GenerateWriterException($"Cannot generate writer for abstract class {variableReference.Name}. Use a supported type or provide a custom writer", variableReference); + } + + // generate writer for class/struct + return GenerateClassOrStructWriterFunction(variableReference, ref WeavingFailed); + } + + MethodReference GetNetworkBehaviourWriter(TypeReference variableReference) + { + // all NetworkBehaviours can use the same write function + if (writeFuncs.TryGetValue(weaverTypes.Import(), out MethodReference func)) + { + // register function so it is added to writer + // use Register instead of RegisterWriteFunc because this is not a generated function + Register(variableReference, func); + + return func; + } + else + { + // this exception only happens if mirror is missing the WriteNetworkBehaviour method + throw new MissingMethodException($"Could not find writer for NetworkBehaviour"); + } + } + + MethodDefinition GenerateEnumWriteFunc(TypeReference variable, ref bool WeavingFailed) + { + MethodDefinition writerFunc = GenerateWriterFunc(variable); + + ILProcessor worker = writerFunc.Body.GetILProcessor(); + + MethodReference underlyingWriter = GetWriteFunc(variable.Resolve().GetEnumUnderlyingType(), ref WeavingFailed); + + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldarg_1); + worker.Emit(OpCodes.Call, underlyingWriter); + + worker.Emit(OpCodes.Ret); + return writerFunc; + } + + MethodDefinition GenerateWriterFunc(TypeReference variable) + { + string functionName = $"_Write_{variable.FullName}"; + // create new writer for this type + MethodDefinition writerFunc = new MethodDefinition(functionName, + MethodAttributes.Public | + MethodAttributes.Static | + MethodAttributes.HideBySig, + weaverTypes.Import(typeof(void))); + + writerFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, weaverTypes.Import())); + writerFunc.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, variable)); + writerFunc.Body.InitLocals = true; + + RegisterWriteFunc(variable, writerFunc); + return writerFunc; + } + + MethodDefinition GenerateClassOrStructWriterFunction(TypeReference variable, ref bool WeavingFailed) + { + MethodDefinition writerFunc = GenerateWriterFunc(variable); + + ILProcessor worker = writerFunc.Body.GetILProcessor(); + + if (!variable.Resolve().IsValueType) + WriteNullCheck(worker, ref WeavingFailed); + + if (!WriteAllFields(variable, worker, ref WeavingFailed)) + return null; + + worker.Emit(OpCodes.Ret); + return writerFunc; + } + + void WriteNullCheck(ILProcessor worker, ref bool WeavingFailed) + { + // if (value == null) + // { + // writer.WriteBoolean(false); + // return; + // } + // + + Instruction labelNotNull = worker.Create(OpCodes.Nop); + worker.Emit(OpCodes.Ldarg_1); + worker.Emit(OpCodes.Brtrue, labelNotNull); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldc_I4_0); + worker.Emit(OpCodes.Call, GetWriteFunc(weaverTypes.Import(), ref WeavingFailed)); + worker.Emit(OpCodes.Ret); + worker.Append(labelNotNull); + + // write.WriteBoolean(true); + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldc_I4_1); + worker.Emit(OpCodes.Call, GetWriteFunc(weaverTypes.Import(), ref WeavingFailed)); + } + + // Find all fields in type and write them + bool WriteAllFields(TypeReference variable, ILProcessor worker, ref bool WeavingFailed) + { + foreach (FieldDefinition field in variable.FindAllPublicFields()) + { + MethodReference writeFunc = GetWriteFunc(field.FieldType, ref WeavingFailed); + // need this null check till later PR when GetWriteFunc throws exception instead + if (writeFunc == null) { return false; } + + FieldReference fieldRef = assembly.MainModule.ImportReference(field); + + worker.Emit(OpCodes.Ldarg_0); + worker.Emit(OpCodes.Ldarg_1); + worker.Emit(OpCodes.Ldfld, fieldRef); + worker.Emit(OpCodes.Call, writeFunc); + } + + return true; + } + + MethodDefinition GenerateCollectionWriter(TypeReference variable, TypeReference elementType, string writerFunction, ref bool WeavingFailed) + { + + MethodDefinition writerFunc = GenerateWriterFunc(variable); + + MethodReference elementWriteFunc = GetWriteFunc(elementType, ref WeavingFailed); + MethodReference intWriterFunc = GetWriteFunc(weaverTypes.Import(), ref WeavingFailed); + + // need this null check till later PR when GetWriteFunc throws exception instead + if (elementWriteFunc == null) + { + Log.Error($"Cannot generate writer for {variable}. Use a supported type or provide a custom writer", variable); + WeavingFailed = true; + return writerFunc; + } + + ModuleDefinition module = assembly.MainModule; + TypeReference readerExtensions = module.ImportReference(typeof(NetworkWriterExtensions)); + MethodReference collectionWriter = Resolvers.ResolveMethod(readerExtensions, assembly, Log, writerFunction, ref WeavingFailed); + + GenericInstanceMethod methodRef = new GenericInstanceMethod(collectionWriter); + methodRef.GenericArguments.Add(elementType); + + // generates + // reader.WriteArray(array); + + ILProcessor worker = writerFunc.Body.GetILProcessor(); + worker.Emit(OpCodes.Ldarg_0); // writer + worker.Emit(OpCodes.Ldarg_1); // collection + + worker.Emit(OpCodes.Call, methodRef); // WriteArray + + worker.Emit(OpCodes.Ret); + + return writerFunc; + } + + // Save a delegate for each one of the writers into Writer{T}.write + internal void InitializeWriters(ILProcessor worker) + { + ModuleDefinition module = assembly.MainModule; + + TypeReference genericWriterClassRef = module.ImportReference(typeof(Writer<>)); + + System.Reflection.FieldInfo fieldInfo = typeof(Writer<>).GetField(nameof(Writer.write)); + FieldReference fieldRef = module.ImportReference(fieldInfo); + TypeReference networkWriterRef = module.ImportReference(typeof(NetworkWriter)); + TypeReference actionRef = module.ImportReference(typeof(Action<,>)); + MethodReference actionConstructorRef = module.ImportReference(typeof(Action<,>).GetConstructors()[0]); + + foreach (KeyValuePair kvp in writeFuncs) + { + TypeReference targetType = kvp.Key; + MethodReference writeFunc = kvp.Value; + + // create a Action delegate + worker.Emit(OpCodes.Ldnull); + worker.Emit(OpCodes.Ldftn, writeFunc); + GenericInstanceType actionGenericInstance = actionRef.MakeGenericInstanceType(networkWriterRef, targetType); + MethodReference actionRefInstance = actionConstructorRef.MakeHostInstanceGeneric(assembly.MainModule, actionGenericInstance); + worker.Emit(OpCodes.Newobj, actionRefInstance); + + // save it in Writer.write + GenericInstanceType genericInstance = genericWriterClassRef.MakeGenericInstanceType(targetType); + FieldReference specializedField = fieldRef.SpecializeField(assembly.MainModule, genericInstance); + worker.Emit(OpCodes.Stsfld, specializedField); + } + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Writers.cs.meta b/Assets/Mirror/Editor/Weaver/Writers.cs.meta new file mode 100644 index 0000000..3769f7f --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Writers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a90060ad76ea044aba613080dd922709 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Editor/Welcome.cs b/Assets/Mirror/Editor/Welcome.cs new file mode 100644 index 0000000..14e57bc --- /dev/null +++ b/Assets/Mirror/Editor/Welcome.cs @@ -0,0 +1,23 @@ +// Shows either a welcome message, only once per session. +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; + +namespace Mirror +{ + static class Welcome + { + [InitializeOnLoadMethod] + static void OnInitializeOnLoad() + { + // InitializeOnLoad is called on start and after each rebuild, + // but we only want to show this once per editor session. + if (!SessionState.GetBool("MIRROR_WELCOME", false)) + { + SessionState.SetBool("MIRROR_WELCOME", true); + Debug.Log("Mirror | mirror-networking.com | discord.gg/N9QVxbM"); + } + } + } +} +#endif diff --git a/Assets/Mirror/Editor/Welcome.cs.meta b/Assets/Mirror/Editor/Welcome.cs.meta new file mode 100644 index 0000000..9062df0 --- /dev/null +++ b/Assets/Mirror/Editor/Welcome.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 180619c3887314f56bf396769c0a23ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Notice.txt b/Assets/Mirror/Notice.txt new file mode 100644 index 0000000..5eeaf88 --- /dev/null +++ b/Assets/Mirror/Notice.txt @@ -0,0 +1,123 @@ +This asset is governed by the Asset Store EULA; however, the following +components are governed by the licenses indicated below: + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +Mirror +MIT License + +Copyright (c) 2015, Unity Technologies +Copyright (c) 2019, vis2k, Paul and Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +kcp2k +MIT License + +Copyright (c) 2016 limpo1989 +Copyright (c) 2020 Paul Pacheco +Copyright (c) 2020 Lymdun +Copyright (c) 2020 vis2k + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +Mono.Cecil +MIT License + +Copyright (c) 2008 - 2015 Jb Evain +Copyright (c) 2008 - 2011 Novell, Inc. + +https://github.com/jbevain/cecil + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +Telepathy +MIT License + +Copyright (c) 2018, vis2k + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- \ No newline at end of file diff --git a/Assets/Mirror/Notice.txt.meta b/Assets/Mirror/Notice.txt.meta new file mode 100644 index 0000000..3281bd8 --- /dev/null +++ b/Assets/Mirror/Notice.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1a7b49ad188074707b004e7bb8824857 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins.meta b/Assets/Mirror/Plugins.meta new file mode 100644 index 0000000..9504239 --- /dev/null +++ b/Assets/Mirror/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 05eb4061e2eb94061b9a08c918fff99b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/BouncyCastle.meta b/Assets/Mirror/Plugins/BouncyCastle.meta new file mode 100644 index 0000000..e064e80 --- /dev/null +++ b/Assets/Mirror/Plugins/BouncyCastle.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 31ff83bf6d2e72542adcbe2c21383f4a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/BouncyCastle/BouncyCastle.Cryptography.dll b/Assets/Mirror/Plugins/BouncyCastle/BouncyCastle.Cryptography.dll new file mode 100644 index 0000000..9d9b6ac Binary files /dev/null and b/Assets/Mirror/Plugins/BouncyCastle/BouncyCastle.Cryptography.dll differ diff --git a/Assets/Mirror/Plugins/BouncyCastle/BouncyCastle.Cryptography.dll.meta b/Assets/Mirror/Plugins/BouncyCastle/BouncyCastle.Cryptography.dll.meta new file mode 100644 index 0000000..69befd7 --- /dev/null +++ b/Assets/Mirror/Plugins/BouncyCastle/BouncyCastle.Cryptography.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a67bf078294b36e4686b9912bf172010 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/BouncyCastle/LICENSE.md b/Assets/Mirror/Plugins/BouncyCastle/LICENSE.md new file mode 100644 index 0000000..277dcd1 --- /dev/null +++ b/Assets/Mirror/Plugins/BouncyCastle/LICENSE.md @@ -0,0 +1,13 @@ +Copyright (c) 2000-2024 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org). +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sub license, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: The above copyright notice and this +permission notice shall be included in all copies or substantial portions of the Software. + +**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** diff --git a/Assets/Mirror/Plugins/BouncyCastle/LICENSE.md.meta b/Assets/Mirror/Plugins/BouncyCastle/LICENSE.md.meta new file mode 100644 index 0000000..d0ce883 --- /dev/null +++ b/Assets/Mirror/Plugins/BouncyCastle/LICENSE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2b45a99b5583cda419e1f1ec943fec4b +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/Mono.Cecil.meta b/Assets/Mirror/Plugins/Mono.Cecil.meta new file mode 100644 index 0000000..a104e2e --- /dev/null +++ b/Assets/Mirror/Plugins/Mono.Cecil.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce126b4e1a7d13b4c865cd92929f13c3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/Mono.Cecil/License.txt b/Assets/Mirror/Plugins/Mono.Cecil/License.txt new file mode 100644 index 0000000..2a9b88f --- /dev/null +++ b/Assets/Mirror/Plugins/Mono.Cecil/License.txt @@ -0,0 +1,25 @@ +Copyright (c) 2008 - 2015 Jb Evain +Copyright (c) 2008 - 2011 Novell, Inc. +Copyright vis2k + +https://github.com/jbevain/cecil +https://github.com/vis2k/cecil <- X + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Assets/Mirror/Plugins/Mono.Cecil/License.txt.meta b/Assets/Mirror/Plugins/Mono.Cecil/License.txt.meta new file mode 100644 index 0000000..9477cb6 --- /dev/null +++ b/Assets/Mirror/Plugins/Mono.Cecil/License.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ab858db5ebbb0d542a9acd197669cb5a +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll new file mode 100644 index 0000000..f6815d3 Binary files /dev/null and b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll differ diff --git a/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll.meta b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll.meta new file mode 100644 index 0000000..d5555bf --- /dev/null +++ b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll.meta @@ -0,0 +1,92 @@ +fileFormatVersion: 2 +guid: a078fc7c0dc14d047a28dea9c93fd259 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll new file mode 100644 index 0000000..3b58436 Binary files /dev/null and b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll differ diff --git a/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll.meta b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll.meta new file mode 100644 index 0000000..3ab420f --- /dev/null +++ b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll.meta @@ -0,0 +1,92 @@ +fileFormatVersion: 2 +guid: 534d998d93b238041bddcd864f7f1088 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll new file mode 100644 index 0000000..7d820f0 Binary files /dev/null and b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll differ diff --git a/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll.meta b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll.meta new file mode 100644 index 0000000..aff0237 --- /dev/null +++ b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll.meta @@ -0,0 +1,92 @@ +fileFormatVersion: 2 +guid: 7526641fb3ae25144aa0a96aad853745 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll new file mode 100644 index 0000000..c042418 Binary files /dev/null and b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll differ diff --git a/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll.meta b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll.meta new file mode 100644 index 0000000..f87dc69 --- /dev/null +++ b/Assets/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll.meta @@ -0,0 +1,94 @@ +fileFormatVersion: 2 +guid: 307911e5ad044dd42b1649eb8637aaf3 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Presets.meta b/Assets/Mirror/Presets.meta new file mode 100644 index 0000000..b8cf771 --- /dev/null +++ b/Assets/Mirror/Presets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 80d00a982048947fa93f2be2ea402b4e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Presets/NetworkTransform.meta b/Assets/Mirror/Presets/NetworkTransform.meta new file mode 100644 index 0000000..561aec5 --- /dev/null +++ b/Assets/Mirror/Presets/NetworkTransform.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eb1ce23d9d0fa494d919aefb1f1fc1d8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Presets/NetworkTransform/ClientAuth-Balanced.preset b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-Balanced.preset new file mode 100644 index 0000000..59bde78 --- /dev/null +++ b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-Balanced.preset @@ -0,0 +1,124 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: ClientAuth-Balanced + m_TargetType: + m_NativeTypeID: 114 + m_ManagedTypePPtr: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, + type: 3} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorHideFlags + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorClassIdentifier + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncDirection + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncInterval + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: target + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: clientAuthority + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncPosition + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncRotation + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncScale + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolatePosition + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolateRotation + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolateScale + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: sendIntervalMultiplier + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: timelineOffset + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: showGizmos + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: showOverlay + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.r + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.g + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.b + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.a + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: onlySyncOnChange + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: bufferResetMultiplier + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: positionSensitivity + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: rotationSensitivity + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: scaleSensitivity + value: 0.01 + objectReference: {fileID: 0} + m_ExcludedProperties: [] diff --git a/Assets/Mirror/Presets/NetworkTransform/ClientAuth-Balanced.preset.meta b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-Balanced.preset.meta new file mode 100644 index 0000000..d5e6c20 --- /dev/null +++ b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-Balanced.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e60045a6c41184f7a97cfa46762adb24 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Presets/NetworkTransform/ClientAuth-FastPaced.preset b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-FastPaced.preset new file mode 100644 index 0000000..29ec753 --- /dev/null +++ b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-FastPaced.preset @@ -0,0 +1,124 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: ClientAuth-FastPaced + m_TargetType: + m_NativeTypeID: 114 + m_ManagedTypePPtr: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, + type: 3} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorHideFlags + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorClassIdentifier + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncDirection + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncInterval + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: target + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: clientAuthority + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncPosition + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncRotation + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncScale + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolatePosition + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolateRotation + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolateScale + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: sendIntervalMultiplier + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: timelineOffset + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: showGizmos + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: showOverlay + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.r + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.g + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.b + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.a + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: onlySyncOnChange + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: bufferResetMultiplier + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: positionSensitivity + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: rotationSensitivity + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: scaleSensitivity + value: 0.01 + objectReference: {fileID: 0} + m_ExcludedProperties: [] diff --git a/Assets/Mirror/Presets/NetworkTransform/ClientAuth-FastPaced.preset.meta b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-FastPaced.preset.meta new file mode 100644 index 0000000..7a23b75 --- /dev/null +++ b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-FastPaced.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 628910e11d35a46ef8b3556b13f59db3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Presets/NetworkTransform/ClientAuth-VeryCasual.preset b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-VeryCasual.preset new file mode 100644 index 0000000..cacaf51 --- /dev/null +++ b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-VeryCasual.preset @@ -0,0 +1,124 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: ClientAuth-VeryCasual + m_TargetType: + m_NativeTypeID: 114 + m_ManagedTypePPtr: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, + type: 3} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorHideFlags + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorClassIdentifier + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncDirection + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncInterval + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: target + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: clientAuthority + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncPosition + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncRotation + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: syncScale + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolatePosition + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolateRotation + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: interpolateScale + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: sendIntervalMultiplier + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: timelineOffset + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: showGizmos + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: showOverlay + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.r + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.g + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.b + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: overlayColor.a + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: onlySyncOnChange + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: bufferResetMultiplier + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: positionSensitivity + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: rotationSensitivity + value: 0.01 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: scaleSensitivity + value: 0.01 + objectReference: {fileID: 0} + m_ExcludedProperties: [] diff --git a/Assets/Mirror/Presets/NetworkTransform/ClientAuth-VeryCasual.preset.meta b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-VeryCasual.preset.meta new file mode 100644 index 0000000..7f810cf --- /dev/null +++ b/Assets/Mirror/Presets/NetworkTransform/ClientAuth-VeryCasual.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c70320295478407885dc307baa7091a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Readme.txt b/Assets/Mirror/Readme.txt new file mode 100644 index 0000000..5e9a4ec --- /dev/null +++ b/Assets/Mirror/Readme.txt @@ -0,0 +1,15 @@ +Mirror is a MMO Scale Networking library for Unity, used in uMMORPG, uSurvival and several MMO projects in development. + +*** IMPORTANT *** +You must restart Unity after importing Mirror for the Components Menu to update! + +Requirements: + Unity 2019 / 2020 LTS + Runtime .Net 4.x (Project Settings > Player > Other Settings) + +Documentation: + https://mirror-networking.gitbook.io/docs/ + +Support: + Discord: https://discordapp.com/invite/N9QVxbM + Bug Reports: https://github.com/vis2k/Mirror/issues diff --git a/Assets/Mirror/Readme.txt.meta b/Assets/Mirror/Readme.txt.meta new file mode 100644 index 0000000..d52ccce --- /dev/null +++ b/Assets/Mirror/Readme.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f6d84e019c68446f28415a923b460a03 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime.meta b/Assets/Mirror/Runtime.meta new file mode 100644 index 0000000..23b34fd --- /dev/null +++ b/Assets/Mirror/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ebe42cc4f3e63744bb101143931aaf8b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports.meta b/Assets/Mirror/Runtime/Transports.meta new file mode 100644 index 0000000..d700a82 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 70be02c4ac478f14fa4af3dc9ae7d429 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks.meta new file mode 100644 index 0000000..7657d71 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c58fd67859269df469f1773bc3789106 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/BidirectionalDictionary.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/BidirectionalDictionary.cs new file mode 100644 index 0000000..383219e --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/BidirectionalDictionary.cs @@ -0,0 +1,89 @@ +using System.Collections; +using System.Collections.Generic; + +namespace Mirror.FizzySteam +{ + public class BidirectionalDictionary : IEnumerable + { + private Dictionary t1ToT2Dict = new Dictionary(); + private Dictionary t2ToT1Dict = new Dictionary(); + + public IEnumerable FirstTypes => t1ToT2Dict.Keys; + public IEnumerable SecondTypes => t2ToT1Dict.Keys; + + public IEnumerator GetEnumerator() => t1ToT2Dict.GetEnumerator(); + + public int Count => t1ToT2Dict.Count; + + public void Add(T1 key, T2 value) + { + if (t1ToT2Dict.ContainsKey(key)) + { + Remove(key); + } + + t1ToT2Dict[key] = value; + t2ToT1Dict[value] = key; + } + + public void Add(T2 key, T1 value) + { + if (t2ToT1Dict.ContainsKey(key)) + { + Remove(key); + } + + t2ToT1Dict[key] = value; + t1ToT2Dict[value] = key; + } + + public T2 Get(T1 key) => t1ToT2Dict[key]; + + public T1 Get(T2 key) => t2ToT1Dict[key]; + + public bool TryGetValue(T1 key, out T2 value) => t1ToT2Dict.TryGetValue(key, out value); + + public bool TryGetValue(T2 key, out T1 value) => t2ToT1Dict.TryGetValue(key, out value); + + public bool Contains(T1 key) => t1ToT2Dict.ContainsKey(key); + + public bool Contains(T2 key) => t2ToT1Dict.ContainsKey(key); + + public void Remove(T1 key) + { + if (Contains(key)) + { + T2 val = t1ToT2Dict[key]; + t1ToT2Dict.Remove(key); + t2ToT1Dict.Remove(val); + } + } + public void Remove(T2 key) + { + if (Contains(key)) + { + T1 val = t2ToT1Dict[key]; + t1ToT2Dict.Remove(val); + t2ToT1Dict.Remove(key); + } + } + + public T1 this[T2 key] + { + get => t2ToT1Dict[key]; + set + { + Add(key, value); + } + } + + public T2 this[T1 key] + { + get => t1ToT2Dict[key]; + set + { + Add(key, value); + } + } + } +} \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/BidirectionalDictionary.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/BidirectionalDictionary.cs.meta new file mode 100644 index 0000000..07a9689 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/BidirectionalDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ffc59ba41dcc8a44b41943b2987dd92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.asmdef b/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.asmdef new file mode 100644 index 0000000..43afc56 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.asmdef @@ -0,0 +1,22 @@ +{ + "name": "FizzySteamworks", + "references": [ + "GUID:68bd7fdb68ef2684e982e8a9825b18a5", + "GUID:30817c1a0e6d646d99c048fc403f5979" + ], + "includePlatforms": [ + "Editor", + "LinuxStandalone64", + "macOSStandalone", + "WindowsStandalone32", + "WindowsStandalone64" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.asmdef.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.asmdef.meta new file mode 100644 index 0000000..b3b22d6 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bd78bb22ae3a60443a865fb2d7dfdafa +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.cs new file mode 100644 index 0000000..bf03a50 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.cs @@ -0,0 +1,311 @@ +#if !DISABLESTEAMWORKS +using Steamworks; +using System; +using System.IO; +using UnityEngine; + +namespace Mirror.FizzySteam +{ + [HelpURL("https://github.com/Chykary/FizzySteamworks")] + public class FizzySteamworks : Transport + { + private const string STEAM_SCHEME = "steam"; + + private static IClient client; + private static IServer server; + + [SerializeField] + public EP2PSend[] Channels = new EP2PSend[2] { EP2PSend.k_EP2PSendReliable, EP2PSend.k_EP2PSendUnreliableNoDelay }; + + [Tooltip("Timeout for connecting in seconds.")] + public int Timeout = 25; + [Tooltip("Allow or disallow P2P connections to fall back to being relayed through the Steam servers if a direct connection or NAT-traversal cannot be established.")] + public bool AllowSteamRelay = true; + + [Tooltip("Use SteamSockets instead of the (deprecated) SteamNetworking. This will always use Relay.")] + public bool UseNextGenSteamNetworking = true; + + private void OnEnable() + { + Debug.Assert(Channels != null && Channels.Length > 0, "No channel configured for FizzySteamworks."); + Invoke(nameof(InitRelayNetworkAccess), 1f); + } + + public override void ClientEarlyUpdate() + { + if (enabled) + { + client?.ReceiveData(); + } + } + + public override void ServerEarlyUpdate() + { + if (enabled) + { + server?.ReceiveData(); + } + } + + public override void ClientLateUpdate() + { + if (enabled) + { + client?.FlushData(); + } + } + + public override void ServerLateUpdate() + { + if (enabled) + { + server?.FlushData(); + } + } + + public override bool ClientConnected() => ClientActive() && client.Connected; + public override void ClientConnect(string address) + { + try + { +#if UNITY_SERVER + SteamGameServerNetworkingUtils.InitRelayNetworkAccess(); +#else + SteamNetworkingUtils.InitRelayNetworkAccess(); +#endif + + InitRelayNetworkAccess(); + + if (ServerActive()) + { + Debug.LogError("Transport already running as server!"); + return; + } + + if (!ClientActive() || client.Error) + { + if (UseNextGenSteamNetworking) + { + Debug.Log($"Starting client [SteamSockets], target address {address}."); + client = NextClient.CreateClient(this, address); + } + else + { + Debug.Log($"Starting client [DEPRECATED SteamNetworking], target address {address}. Relay enabled: {AllowSteamRelay}"); + SteamNetworking.AllowP2PPacketRelay(AllowSteamRelay); + client = LegacyClient.CreateClient(this, address); + } + } + else + { + Debug.LogError("Client already running!"); + } + } + catch (Exception ex) + { + Debug.LogError("Exception: " + ex.Message + ". Client could not be started."); + OnClientDisconnected.Invoke(); + } + } + + public override void ClientConnect(Uri uri) + { + if (uri.Scheme != STEAM_SCHEME) + throw new ArgumentException($"Invalid url {uri}, use {STEAM_SCHEME}://SteamID instead", nameof(uri)); + + ClientConnect(uri.Host); + } + + public override void ClientSend(ArraySegment segment, int channelId) + { + byte[] data = new byte[segment.Count]; + Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count); + client.Send(data, channelId); + } + + public override void ClientDisconnect() + { + if (ClientActive()) + { + Shutdown(); + } + } + public bool ClientActive() => client != null; + + + public override bool ServerActive() => server != null; + public override void ServerStart() + { + try + { +#if UNITY_SERVER + SteamGameServerNetworkingUtils.InitRelayNetworkAccess(); +#else + SteamNetworkingUtils.InitRelayNetworkAccess(); +#endif + + + InitRelayNetworkAccess(); + + if (ClientActive()) + { + Debug.LogError("Transport already running as client!"); + return; + } + + if (!ServerActive()) + { + if (UseNextGenSteamNetworking) + { + Debug.Log($"Starting server [SteamSockets]."); + server = NextServer.CreateServer(this, NetworkManager.singleton.maxConnections); + } + else + { + Debug.Log($"Starting server [DEPRECATED SteamNetworking]. Relay enabled: {AllowSteamRelay}"); +#if UNITY_SERVER + SteamGameServerNetworking.AllowP2PPacketRelay(AllowSteamRelay); +#else + + SteamNetworking.AllowP2PPacketRelay(AllowSteamRelay); +#endif + server = LegacyServer.CreateServer(this, NetworkManager.singleton.maxConnections); + } + } + else + { + Debug.LogError("Server already started!"); + } + } + catch (Exception ex) + { + Debug.LogException(ex); + return; + } + } + + public override Uri ServerUri() + { + var steamBuilder = new UriBuilder + { + Scheme = STEAM_SCHEME, +#if UNITY_SERVER + Host = SteamGameServer.GetSteamID().m_SteamID.ToString() +#else + Host = SteamUser.GetSteamID().m_SteamID.ToString() +#endif + }; + + return steamBuilder.Uri; + } + + public override void ServerSend(int connectionId, ArraySegment segment, int channelId) + { + if (ServerActive()) + { + byte[] data = new byte[segment.Count]; + Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count); + server.Send(connectionId, data, channelId); + } + } + public override void ServerDisconnect(int connectionId) + { + if (ServerActive()) + { + server.Disconnect(connectionId); + } + } + public override string ServerGetClientAddress(int connectionId) => ServerActive() ? server.ServerGetClientAddress(connectionId) : string.Empty; + public override void ServerStop() + { + if (ServerActive()) + { + Shutdown(); + } + } + + public override void Shutdown() + { + if (server != null) + { + server.Shutdown(); + server = null; + Debug.Log("Transport shut down - was server."); + } + + if (client != null) + { + client.Disconnect(); + client = null; + Debug.Log("Transport shut down - was client."); + } + } + + public override int GetMaxPacketSize(int channelId) + { + if (UseNextGenSteamNetworking) + { + return Constants.k_cbMaxSteamNetworkingSocketsMessageSizeSend; + } + else + { + if (channelId >= Channels.Length) + { + Debug.LogError("Channel Id exceeded configured channels! Please configure more channels."); + return 1200; + } + + switch (Channels[channelId]) + { + case EP2PSend.k_EP2PSendUnreliable: + case EP2PSend.k_EP2PSendUnreliableNoDelay: + return 1200; + case EP2PSend.k_EP2PSendReliable: + case EP2PSend.k_EP2PSendReliableWithBuffering: + return 1048576; + default: + throw new NotSupportedException(); + } + } + } + + public override bool Available() + { + try + { +#if UNITY_SERVER + SteamGameServerNetworkingUtils.InitRelayNetworkAccess(); +#else + SteamNetworkingUtils.InitRelayNetworkAccess(); +#endif + return true; + } + catch + { + return false; + } + } + + private void InitRelayNetworkAccess() + { + try + { + if (UseNextGenSteamNetworking) + { +#if UNITY_SERVER + SteamGameServerNetworkingUtils.InitRelayNetworkAccess(); +#else + SteamNetworkingUtils.InitRelayNetworkAccess(); +#endif + } + } + catch { } + } + + private void OnDestroy() + { + Shutdown(); + } + } +} +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.cs.meta new file mode 100644 index 0000000..a48bbf8 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/FizzySteamworks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e6e55fca1f4e4844593a3dd65a3ecb39 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/IClient.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/IClient.cs new file mode 100644 index 0000000..043ff4f --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/IClient.cs @@ -0,0 +1,14 @@ +namespace Mirror.FizzySteam +{ + public interface IClient + { + bool Connected { get; } + bool Error { get; } + + + void ReceiveData(); + void Disconnect(); + void FlushData(); + void Send(byte[] data, int channelId); + } +} \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/IClient.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/IClient.cs.meta new file mode 100644 index 0000000..71feea9 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/IClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c65d0a35946fe34aa415488cd674bce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/IServer.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/IServer.cs new file mode 100644 index 0000000..570bc3b --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/IServer.cs @@ -0,0 +1,12 @@ +namespace Mirror.FizzySteam +{ + public interface IServer + { + void ReceiveData(); + void Send(int connectionId, byte[] data, int channelId); + void Disconnect(int connectionId); + void FlushData(); + string ServerGetClientAddress(int connectionId); + void Shutdown(); + } +} \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/IServer.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/IServer.cs.meta new file mode 100644 index 0000000..c84a4b2 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/IServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ed34f1f9e087d74094368efc7a84aad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/LICENSE b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LICENSE new file mode 100644 index 0000000..7131057 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LICENSE @@ -0,0 +1,37 @@ +MIT License + +Copyright Fizz Cube Ltd (c) 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +=== + +Copyright Marco Hoffmann (c) 2020 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +MIT License \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/LICENSE.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LICENSE.meta new file mode 100644 index 0000000..9055aec --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 80411239d210c5c4fb875c2d24c06fe0 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyClient.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyClient.cs new file mode 100644 index 0000000..39c65f8 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyClient.cs @@ -0,0 +1,177 @@ +#if !DISABLESTEAMWORKS +using Steamworks; +using System; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; + +namespace Mirror.FizzySteam +{ + public class LegacyClient : LegacyCommon, IClient + { + public bool Connected { get; private set; } + public bool Error { get; private set; } + + private event Action OnReceivedData; + private event Action OnConnected; + private event Action OnDisconnected; + + private TimeSpan ConnectionTimeout; + + private CSteamID hostSteamID = CSteamID.Nil; + private TaskCompletionSource connectedComplete; + private CancellationTokenSource cancelToken; + + private LegacyClient(FizzySteamworks transport) : base(transport) + { + ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.Timeout)); + } + + public static LegacyClient CreateClient(FizzySteamworks transport, string host) + { + LegacyClient c = new LegacyClient(transport); + + c.OnConnected += () => transport.OnClientConnected.Invoke(); + c.OnDisconnected += () => transport.OnClientDisconnected.Invoke(); + c.OnReceivedData += (data, channel) => transport.OnClientDataReceived.Invoke(new ArraySegment(data), channel); + + + try + { +#if UNITY_SERVER + InteropHelp.TestIfAvailableGameServer(); +#else + InteropHelp.TestIfAvailableClient(); +#endif + c.Connect(host); + } + catch + { + Debug.LogError("SteamWorks not initialized."); + c.OnConnectionFailed(CSteamID.Nil); + } + + return c; + } + + private async void Connect(string host) + { + cancelToken = new CancellationTokenSource(); + + try + { + hostSteamID = new CSteamID(UInt64.Parse(host)); + connectedComplete = new TaskCompletionSource(); + + OnConnected += SetConnectedComplete; + + SendInternal(hostSteamID, InternalMessages.CONNECT); + + Task connectedCompleteTask = connectedComplete.Task; + Task timeOutTask = Task.Delay(ConnectionTimeout, cancelToken.Token); + + if (await Task.WhenAny(connectedCompleteTask, timeOutTask) != connectedCompleteTask) + { + if (cancelToken.IsCancellationRequested) + { + Debug.LogError($"The connection attempt was cancelled."); + } + else if (timeOutTask.IsCompleted) + { + Debug.LogError($"Connection to {host} timed out."); + } + OnConnected -= SetConnectedComplete; + OnConnectionFailed(hostSteamID); + } + + OnConnected -= SetConnectedComplete; + } + catch (FormatException) + { + Debug.LogError($"Connection string was not in the right format. Did you enter a SteamId?"); + Error = true; + OnConnectionFailed(hostSteamID); + } + catch (Exception ex) + { + Debug.LogError(ex.Message); + Error = true; + OnConnectionFailed(hostSteamID); + } + finally + { + if (Error) + { + OnConnectionFailed(CSteamID.Nil); + } + } + } + + public void Disconnect() + { + Debug.Log("Sending Disconnect message"); + SendInternal(hostSteamID, InternalMessages.DISCONNECT); + Dispose(); + cancelToken?.Cancel(); + + WaitForClose(hostSteamID); + } + + private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task); + + protected override void OnReceiveData(byte[] data, CSteamID clientSteamID, int channel) + { + if (clientSteamID != hostSteamID) + { + Debug.LogError("Received a message from an unknown"); + return; + } + + OnReceivedData.Invoke(data, channel); + } + + protected override void OnNewConnection(P2PSessionRequest_t result) + { + if (hostSteamID == result.m_steamIDRemote) + { + SteamNetworking.AcceptP2PSessionWithUser(result.m_steamIDRemote); + } + else + { + Debug.LogError("P2P Acceptance Request from unknown host ID."); + } + } + + protected override void OnReceiveInternalData(InternalMessages type, CSteamID clientSteamID) + { + switch (type) + { + case InternalMessages.ACCEPT_CONNECT: + if (!Connected) + { + Connected = true; + OnConnected.Invoke(); + Debug.Log("Connection established."); + } + break; + case InternalMessages.DISCONNECT: + if (Connected) + { + Connected = false; + Debug.Log("Disconnected."); + OnDisconnected.Invoke(); + } + break; + default: + Debug.Log("Received unknown message type"); + break; + } + } + + public void Send(byte[] data, int channelId) => Send(hostSteamID, data, channelId); + + protected override void OnConnectionFailed(CSteamID remoteId) => OnDisconnected.Invoke(); + public void FlushData() { } + } +} +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyClient.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyClient.cs.meta new file mode 100644 index 0000000..3a4bae5 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 862fc5e604ebaa0438662870d4a14e43 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyCommon.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyCommon.cs new file mode 100644 index 0000000..8fcb573 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyCommon.cs @@ -0,0 +1,180 @@ +#if !DISABLESTEAMWORKS +using Steamworks; +using System; +using System.Collections; +using UnityEngine; + +namespace Mirror.FizzySteam +{ + public abstract class LegacyCommon + { + private EP2PSend[] channels; + private int internal_ch => channels.Length; + + protected enum InternalMessages : byte + { + CONNECT, + ACCEPT_CONNECT, + DISCONNECT + } + + private Callback callback_OnNewConnection = null; + private Callback callback_OnConnectFail = null; + + protected readonly FizzySteamworks transport; + + protected LegacyCommon(FizzySteamworks transport) + { + channels = transport.Channels; + + callback_OnNewConnection = Callback.Create(OnNewConnection); + callback_OnConnectFail = Callback.Create(OnConnectFail); + + this.transport = transport; + } + + protected void Dispose() + { + if (callback_OnNewConnection != null) + { + callback_OnNewConnection.Dispose(); + callback_OnNewConnection = null; + } + + if (callback_OnConnectFail != null) + { + callback_OnConnectFail.Dispose(); + callback_OnConnectFail = null; + } + } + + protected abstract void OnNewConnection(P2PSessionRequest_t result); + + private void OnConnectFail(P2PSessionConnectFail_t result) + { + OnConnectionFailed(result.m_steamIDRemote); + CloseP2PSessionWithUser(result.m_steamIDRemote); + + switch (result.m_eP2PSessionError) + { + case 1: + Debug.LogError("Connection failed: The target user is not running the same game."); + break; + case 2: + Debug.LogError("Connection failed: The local user doesn't own the app that is running."); + break; + case 3: + Debug.LogError("Connection failed: Target user isn't connected to Steam."); + break; + case 4: + Debug.LogError("Connection failed: The connection timed out because the target user didn't respond."); + break; + default: + Debug.LogError("Connection failed: Unknown error."); + break; + } + } + + protected void SendInternal(CSteamID target, InternalMessages type) + { +#if UNITY_SERVER + SteamGameServerNetworking.SendP2PPacket(target, new byte[] { (byte)type }, 1, EP2PSend.k_EP2PSendReliable, internal_ch); +#else + SteamNetworking.SendP2PPacket(target, new byte[] { (byte)type }, 1, EP2PSend.k_EP2PSendReliable, internal_ch); +#endif + } + protected void Send(CSteamID host, byte[] msgBuffer, int channel) + { +#if UNITY_SERVER + SteamGameServerNetworking.SendP2PPacket(host, msgBuffer, (uint)msgBuffer.Length, channels[Mathf.Min(channel, channels.Length - 1)], channel); +#else + SteamNetworking.SendP2PPacket(host, msgBuffer, (uint)msgBuffer.Length, channels[Mathf.Min(channel, channels.Length - 1)], channel); +#endif + } + + private bool Receive(out CSteamID clientSteamID, out byte[] receiveBuffer, int channel) + { +#if UNITY_SERVER + if (SteamGameServerNetworking.IsP2PPacketAvailable(out uint packetSize, channel)) + { + receiveBuffer = new byte[packetSize]; + return SteamGameServerNetworking.ReadP2PPacket(receiveBuffer, packetSize, out _, out clientSteamID, channel); + } +#else + if (SteamNetworking.IsP2PPacketAvailable(out uint packetSize, channel)) + { + receiveBuffer = new byte[packetSize]; + return SteamNetworking.ReadP2PPacket(receiveBuffer, packetSize, out _, out clientSteamID, channel); + } +#endif + + receiveBuffer = null; + clientSteamID = CSteamID.Nil; + return false; + } + + protected void CloseP2PSessionWithUser(CSteamID clientSteamID) + { +#if UNITY_SERVER + SteamGameServerNetworking.CloseP2PSessionWithUser(clientSteamID); +#else + SteamNetworking.CloseP2PSessionWithUser(clientSteamID); +#endif + } + + protected void WaitForClose(CSteamID cSteamID) + { + if (transport.enabled) + { + transport.StartCoroutine(DelayedClose(cSteamID)); + } + else + { + CloseP2PSessionWithUser(cSteamID); + } + } + + private IEnumerator DelayedClose(CSteamID cSteamID) + { + yield return null; + CloseP2PSessionWithUser(cSteamID); + } + + public void ReceiveData() + { + try + { + while (transport.enabled && Receive(out CSteamID clientSteamID, out byte[] internalMessage, internal_ch)) + { + if (internalMessage.Length == 1) + { + OnReceiveInternalData((InternalMessages)internalMessage[0], clientSteamID); + return; // Wait one frame + } + else + { + Debug.Log("Incorrect package length on internal channel."); + } + } + + for (int chNum = 0; chNum < channels.Length; chNum++) + { + while (transport.enabled && Receive(out CSteamID clientSteamID, out byte[] receiveBuffer, chNum)) + { + OnReceiveData(receiveBuffer, clientSteamID, chNum); + } + } + + } + catch (Exception e) + { + Debug.LogException(e); + } + } + + protected abstract void OnReceiveInternalData(InternalMessages type, CSteamID clientSteamID); + protected abstract void OnReceiveData(byte[] data, CSteamID clientSteamID, int channel); + protected abstract void OnConnectionFailed(CSteamID remoteId); + } +} +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyCommon.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyCommon.cs.meta new file mode 100644 index 0000000..314faf9 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyCommon.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 805bd7b4762d722499a9f229c905a8d9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyServer.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyServer.cs new file mode 100644 index 0000000..7ce89e1 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyServer.cs @@ -0,0 +1,170 @@ +#if !DISABLESTEAMWORKS +using Steamworks; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror.FizzySteam +{ + public class LegacyServer : LegacyCommon, IServer + { + private event Action OnConnected; + private event Action OnReceivedData; + private event Action OnDisconnected; + private event Action OnReceivedError; + + private BidirectionalDictionary steamToMirrorIds; + private int maxConnections; + private int nextConnectionID; + + public static LegacyServer CreateServer(FizzySteamworks transport, int maxConnections) + { + LegacyServer s = new LegacyServer(transport, maxConnections); + + s.OnConnected += (id) => transport.OnServerConnected.Invoke(id); + s.OnDisconnected += (id) => transport.OnServerDisconnected.Invoke(id); + s.OnReceivedData += (id, data, channel) => transport.OnServerDataReceived.Invoke(id, new ArraySegment(data), channel); + s.OnReceivedError += (id, error, reason) => transport.OnServerError.Invoke(id, error, reason); + + try + { +#if UNITY_SERVER + InteropHelp.TestIfAvailableGameServer(); +#else + InteropHelp.TestIfAvailableClient(); +#endif + } + catch + { + Debug.LogError("SteamWorks not initialized."); + } + + return s; + } + + private LegacyServer(FizzySteamworks transport, int maxConnections) : base(transport) + { + this.maxConnections = maxConnections; + steamToMirrorIds = new BidirectionalDictionary(); + nextConnectionID = 1; + } + + protected override void OnNewConnection(P2PSessionRequest_t result) + { +#if UNITY_SERVER + SteamGameServerNetworking.AcceptP2PSessionWithUser(result.m_steamIDRemote); +#else + SteamNetworking.AcceptP2PSessionWithUser(result.m_steamIDRemote); +#endif + } + + protected override void OnReceiveInternalData(InternalMessages type, CSteamID clientSteamID) + { + switch (type) + { + case InternalMessages.CONNECT: + if (steamToMirrorIds.Count >= maxConnections) + { + SendInternal(clientSteamID, InternalMessages.DISCONNECT); + return; + } + + SendInternal(clientSteamID, InternalMessages.ACCEPT_CONNECT); + + int connectionId = nextConnectionID++; + steamToMirrorIds.Add(clientSteamID, connectionId); + OnConnected.Invoke(connectionId); + Debug.Log($"Client with SteamID {clientSteamID} connected. Assigning connection id {connectionId}"); + break; + case InternalMessages.DISCONNECT: + if (steamToMirrorIds.TryGetValue(clientSteamID, out int connId)) + { + OnDisconnected.Invoke(connId); + CloseP2PSessionWithUser(clientSteamID); + steamToMirrorIds.Remove(clientSteamID); + Debug.Log($"Client with SteamID {clientSteamID} disconnected."); + } + + break; + default: + Debug.Log("Received unknown message type"); + break; + } + } + + protected override void OnReceiveData(byte[] data, CSteamID clientSteamID, int channel) + { + if (steamToMirrorIds.TryGetValue(clientSteamID, out int connectionId)) + { + OnReceivedData.Invoke(connectionId, data, channel); + } + else + { + CloseP2PSessionWithUser(clientSteamID); + Debug.LogError("Data received from steam client thats not known " + clientSteamID); + OnReceivedError.Invoke(-1, TransportError.DnsResolve, "ERROR Unknown SteamID"); + } + } + + public void Disconnect(int connectionId) + { + if (steamToMirrorIds.TryGetValue(connectionId, out CSteamID steamID)) + { + SendInternal(steamID, InternalMessages.DISCONNECT); + steamToMirrorIds.Remove(connectionId); + } + else + { + Debug.LogWarning("Trying to disconnect unknown connection id: " + connectionId); + } + } + + public void Shutdown() + { + foreach (KeyValuePair client in steamToMirrorIds) + { + Disconnect(client.Value); + WaitForClose(client.Key); + } + + Dispose(); + } + + public void Send(int connectionId, byte[] data, int channelId) + { + if (steamToMirrorIds.TryGetValue(connectionId, out CSteamID steamId)) + { + Send(steamId, data, channelId); + } + else + { + Debug.LogError("Trying to send on unknown connection: " + connectionId); + OnReceivedError.Invoke(connectionId, TransportError.Unexpected, "ERROR Unknown Connection"); + } + } + + public string ServerGetClientAddress(int connectionId) + { + if (steamToMirrorIds.TryGetValue(connectionId, out CSteamID steamId)) + { + return steamId.ToString(); + } + else + { + Debug.LogError("Trying to get info on unknown connection: " + connectionId); + OnReceivedError.Invoke(connectionId, TransportError.Unexpected, "ERROR Unknown Connection"); + return string.Empty; + } + } + + protected override void OnConnectionFailed(CSteamID remoteId) + { + int connectionId = steamToMirrorIds.TryGetValue(remoteId, out int connId) ? connId : nextConnectionID++; + OnDisconnected.Invoke(connectionId); + + steamToMirrorIds.Remove(remoteId); + } + public void FlushData() { } + } +} +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyServer.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyServer.cs.meta new file mode 100644 index 0000000..341a6e9 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/LegacyServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6b4fdab451e8c647b7e26d8c4d934f9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextClient.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextClient.cs new file mode 100644 index 0000000..50681f3 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextClient.cs @@ -0,0 +1,226 @@ +#if !DISABLESTEAMWORKS +using Steamworks; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; + +namespace Mirror.FizzySteam +{ + public class NextClient : NextCommon, IClient + { + public bool Connected { get; private set; } + public bool Error { get; private set; } + + private TimeSpan ConnectionTimeout; + + private event Action OnReceivedData; + private event Action OnConnected; + private event Action OnDisconnected; + private Callback c_onConnectionChange = null; + + private CancellationTokenSource cancelToken; + private TaskCompletionSource connectedComplete; + private CSteamID hostSteamID = CSteamID.Nil; + private HSteamNetConnection HostConnection; + private List BufferedData; + + private NextClient(FizzySteamworks transport) + { + ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.Timeout)); + BufferedData = new List(); + } + + public static NextClient CreateClient(FizzySteamworks transport, string host) + { + NextClient c = new NextClient(transport); + + c.OnConnected += () => transport.OnClientConnected.Invoke(); + c.OnDisconnected += () => transport.OnClientDisconnected.Invoke(); + c.OnReceivedData += (data, ch) => transport.OnClientDataReceived.Invoke(new ArraySegment(data), ch); + + try + { +#if UNITY_SERVER + SteamGameServerNetworkingUtils.InitRelayNetworkAccess(); +#else + SteamNetworkingUtils.InitRelayNetworkAccess(); +#endif + c.Connect(host); + } + catch (Exception ex) + { + Debug.LogException(ex); + c.OnConnectionFailed(); + } + + return c; + } + + private async void Connect(string host) + { + cancelToken = new CancellationTokenSource(); + c_onConnectionChange = Callback.Create(OnConnectionStatusChanged); + + try + { + hostSteamID = new CSteamID(UInt64.Parse(host)); + connectedComplete = new TaskCompletionSource(); + OnConnected += SetConnectedComplete; + + SteamNetworkingIdentity smi = new SteamNetworkingIdentity(); + smi.SetSteamID(hostSteamID); + + SteamNetworkingConfigValue_t[] options = new SteamNetworkingConfigValue_t[] { }; + HostConnection = SteamNetworkingSockets.ConnectP2P(ref smi, 0, options.Length, options); + + Task connectedCompleteTask = connectedComplete.Task; + Task timeOutTask = Task.Delay(ConnectionTimeout, cancelToken.Token); + + if (await Task.WhenAny(connectedCompleteTask, timeOutTask) != connectedCompleteTask) + { + if (cancelToken.IsCancellationRequested) + { + Debug.LogError($"The connection attempt was cancelled."); + } + else if (timeOutTask.IsCompleted) + { + Debug.LogError($"Connection to {host} timed out."); + } + + OnConnected -= SetConnectedComplete; + OnConnectionFailed(); + } + + OnConnected -= SetConnectedComplete; + } + catch (FormatException) + { + Debug.LogError($"Connection string was not in the right format. Did you enter a SteamId?"); + Error = true; + OnConnectionFailed(); + } + catch (Exception ex) + { + Debug.LogError(ex.Message); + Error = true; + OnConnectionFailed(); + } + finally + { + if (Error) + { + Debug.LogError("Connection failed."); + OnConnectionFailed(); + } + } + } + + private void OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t param) + { + ulong clientSteamID = param.m_info.m_identityRemote.GetSteamID64(); + if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connected) + { + Connected = true; + OnConnected.Invoke(); + Debug.Log("Connection established."); + + if (BufferedData.Count > 0) + { + Debug.Log($"{BufferedData.Count} received before connection was established. Processing now."); + { + foreach (Action a in BufferedData) + { + a(); + } + } + } + } + else if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ClosedByPeer || param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ProblemDetectedLocally) + { + Debug.Log($"Connection was closed by peer, {param.m_info.m_szEndDebug}"); + Disconnect(); + } + else + { + Debug.Log($"Connection state changed: {param.m_info.m_eState.ToString()} - {param.m_info.m_szEndDebug}"); + } + } + + public void Disconnect() + { + cancelToken?.Cancel(); + Dispose(); + + if (HostConnection.m_HSteamNetConnection != 0) + { + Debug.Log("Sending Disconnect message"); + SteamNetworkingSockets.CloseConnection(HostConnection, 0, "Graceful disconnect", false); + HostConnection.m_HSteamNetConnection = 0; + } + } + + protected void Dispose() + { + if (c_onConnectionChange != null) + { + c_onConnectionChange.Dispose(); + c_onConnectionChange = null; + } + } + + private void InternalDisconnect() + { + Connected = false; + OnDisconnected.Invoke(); + Debug.Log("Disconnected."); + SteamNetworkingSockets.CloseConnection(HostConnection, 0, "Disconnected", false); + } + + public void ReceiveData() + { + IntPtr[] ptrs = new IntPtr[MAX_MESSAGES]; + int messageCount; + + if ((messageCount = SteamNetworkingSockets.ReceiveMessagesOnConnection(HostConnection, ptrs, MAX_MESSAGES)) > 0) + { + for (int i = 0; i < messageCount; i++) + { + (byte[] data, int ch) = ProcessMessage(ptrs[i]); + if (Connected) + { + OnReceivedData(data, ch); + } + else + { + BufferedData.Add(() => OnReceivedData(data, ch)); + } + } + } + } + + public void Send(byte[] data, int channelId) + { + EResult res = SendSocket(HostConnection, data, channelId); + + if (res == EResult.k_EResultNoConnection || res == EResult.k_EResultInvalidParam) + { + Debug.Log($"Connection to server was lost."); + InternalDisconnect(); + } + else if (res != EResult.k_EResultOK) + { + Debug.LogError($"Could not send: {res.ToString()}"); + } + } + + private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task); + private void OnConnectionFailed() => OnDisconnected.Invoke(); + public void FlushData() + { + SteamNetworkingSockets.FlushMessagesOnConnection(HostConnection); + } + } +} +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextClient.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextClient.cs.meta new file mode 100644 index 0000000..66ddf9f --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a76b4f832739fae40ac8bebdc30ad63d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextCommon.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextCommon.cs new file mode 100644 index 0000000..175beac --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextCommon.cs @@ -0,0 +1,48 @@ +#if !DISABLESTEAMWORKS +using Steamworks; +using System; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace Mirror.FizzySteam +{ + public abstract class NextCommon + { + protected const int MAX_MESSAGES = 256; + + protected EResult SendSocket(HSteamNetConnection conn, byte[] data, int channelId) + { + Array.Resize(ref data, data.Length + 1); + data[data.Length - 1] = (byte)channelId; + + GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned); + IntPtr pData = pinnedArray.AddrOfPinnedObject(); + int sendFlag = channelId == Channels.Unreliable ? Constants.k_nSteamNetworkingSend_Unreliable : Constants.k_nSteamNetworkingSend_Reliable; +#if UNITY_SERVER + EResult res = SteamGameServerNetworkingSockets.SendMessageToConnection(conn, pData, (uint)data.Length, sendFlag, out long _); +#else + EResult res = SteamNetworkingSockets.SendMessageToConnection(conn, pData, (uint)data.Length, sendFlag, out long _); +#endif + if (res != EResult.k_EResultOK) + { + Debug.LogWarning($"Send issue: {res}"); + } + + pinnedArray.Free(); + return res; + } + + protected (byte[], int) ProcessMessage(IntPtr ptrs) + { + SteamNetworkingMessage_t data = Marshal.PtrToStructure(ptrs); + byte[] managedArray = new byte[data.m_cbSize]; + Marshal.Copy(data.m_pData, managedArray, 0, data.m_cbSize); + SteamNetworkingMessage_t.Release(ptrs); + + int channel = managedArray[managedArray.Length - 1]; + Array.Resize(ref managedArray, managedArray.Length - 1); + return (managedArray, channel); + } + } +} +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextCommon.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextCommon.cs.meta new file mode 100644 index 0000000..d7d9a74 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextCommon.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 79668d9d397a0fc4982afadecd11c869 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextServer.cs b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextServer.cs new file mode 100644 index 0000000..e5f18a4 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextServer.cs @@ -0,0 +1,246 @@ +#if !DISABLESTEAMWORKS +using Steamworks; +using System; +using System.Linq; +using UnityEngine; + +namespace Mirror.FizzySteam +{ + public class NextServer : NextCommon, IServer + { + private event Action OnConnected; + private event Action OnReceivedData; + private event Action OnDisconnected; + private event Action OnReceivedError; + + private BidirectionalDictionary connToMirrorID; + private BidirectionalDictionary steamIDToMirrorID; + private int maxConnections; + private int nextConnectionID; + + private HSteamListenSocket listenSocket; + + private Callback c_onConnectionChange = null; + + private NextServer(int maxConnections) + { + this.maxConnections = maxConnections; + connToMirrorID = new BidirectionalDictionary(); + steamIDToMirrorID = new BidirectionalDictionary(); + nextConnectionID = 1; + c_onConnectionChange = Callback.Create(OnConnectionStatusChanged); + } + + public static NextServer CreateServer(FizzySteamworks transport, int maxConnections) + { + NextServer s = new NextServer(maxConnections); + + s.OnConnected += (id) => transport.OnServerConnected.Invoke(id); + s.OnDisconnected += (id) => transport.OnServerDisconnected.Invoke(id); + s.OnReceivedData += (id, data, ch) => transport.OnServerDataReceived.Invoke(id, new ArraySegment(data), ch); + s.OnReceivedError += (id, error, reason) => transport.OnServerError.Invoke(id, error, reason); + + try + { +#if UNITY_SERVER + SteamGameServerNetworkingUtils.InitRelayNetworkAccess(); +#else + SteamNetworkingUtils.InitRelayNetworkAccess(); +#endif + } + catch (Exception ex) + { + Debug.LogException(ex); + } + + s.Host(); + + return s; + } + + private void Host() + { + SteamNetworkingConfigValue_t[] options = new SteamNetworkingConfigValue_t[] { }; +#if UNITY_SERVER + listenSocket = SteamGameServerNetworkingSockets.CreateListenSocketP2P(0, options.Length, options); +#else + listenSocket = SteamNetworkingSockets.CreateListenSocketP2P(0, options.Length, options); +#endif + } + + private void OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t param) + { + ulong clientSteamID = param.m_info.m_identityRemote.GetSteamID64(); + if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connecting) + { + if (connToMirrorID.Count >= maxConnections) + { + Debug.Log($"Incoming connection {clientSteamID} would exceed max connection count. Rejecting."); +#if UNITY_SERVER + SteamGameServerNetworkingSockets.CloseConnection(param.m_hConn, 0, "Max Connection Count", false); +#else + SteamNetworkingSockets.CloseConnection(param.m_hConn, 0, "Max Connection Count", false); +#endif + return; + } + + EResult res; + +#if UNITY_SERVER + if ((res = SteamGameServerNetworkingSockets.AcceptConnection(param.m_hConn)) == EResult.k_EResultOK) +#else + if ((res = SteamNetworkingSockets.AcceptConnection(param.m_hConn)) == EResult.k_EResultOK) +#endif + { + Debug.Log($"Accepting connection {clientSteamID}"); + } + else + { + Debug.Log($"Connection {clientSteamID} could not be accepted: {res.ToString()}"); + } + } + else if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connected) + { + int connectionId = nextConnectionID++; + connToMirrorID.Add(param.m_hConn, connectionId); + steamIDToMirrorID.Add(param.m_info.m_identityRemote.GetSteamID(), connectionId); + OnConnected.Invoke(connectionId); + Debug.Log($"Client with SteamID {clientSteamID} connected. Assigning connection id {connectionId}"); + } + else if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ClosedByPeer || param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ProblemDetectedLocally) + { + if (connToMirrorID.TryGetValue(param.m_hConn, out int connId)) + { + InternalDisconnect(connId, param.m_hConn); + } + } + else + { + Debug.Log($"Connection {clientSteamID} state changed: {param.m_info.m_eState.ToString()}"); + } + } + + private void InternalDisconnect(int connId, HSteamNetConnection socket) + { + OnDisconnected.Invoke(connId); +#if UNITY_SERVER + SteamGameServerNetworkingSockets.CloseConnection(socket, 0, "Graceful disconnect", false); +#else + SteamNetworkingSockets.CloseConnection(socket, 0, "Graceful disconnect", false); +#endif + connToMirrorID.Remove(connId); + steamIDToMirrorID.Remove(connId); + Debug.Log($"Client with ConnectionID {connId} disconnected."); + } + + public void Disconnect(int connectionId) + { + if (connToMirrorID.TryGetValue(connectionId, out HSteamNetConnection conn)) + { + Debug.Log($"Connection id {connectionId} disconnected."); +#if UNITY_SERVER + SteamGameServerNetworkingSockets.CloseConnection(conn, 0, "Disconnected by server", false); +#else + SteamNetworkingSockets.CloseConnection(conn, 0, "Disconnected by server", false); +#endif + steamIDToMirrorID.Remove(connectionId); + connToMirrorID.Remove(connectionId); + OnDisconnected(connectionId); + } + else + { + Debug.LogWarning("Trying to disconnect unknown connection id: " + connectionId); + } + } + + public void FlushData() + { + foreach (HSteamNetConnection conn in connToMirrorID.FirstTypes) + { +#if UNITY_SERVER + SteamGameServerNetworkingSockets.FlushMessagesOnConnection(conn); +#else + SteamNetworkingSockets.FlushMessagesOnConnection(conn); +#endif + } + } + + public void ReceiveData() + { + foreach (HSteamNetConnection conn in connToMirrorID.FirstTypes.ToList()) + { + if (connToMirrorID.TryGetValue(conn, out int connId)) + { + IntPtr[] ptrs = new IntPtr[MAX_MESSAGES]; + int messageCount; + +#if UNITY_SERVER + if ((messageCount = SteamGameServerNetworkingSockets.ReceiveMessagesOnConnection(conn, ptrs, MAX_MESSAGES)) > 0) +#else + if ((messageCount = SteamNetworkingSockets.ReceiveMessagesOnConnection(conn, ptrs, MAX_MESSAGES)) > 0) +#endif + { + for (int i = 0; i < messageCount; i++) + { + (byte[] data, int ch) = ProcessMessage(ptrs[i]); + OnReceivedData(connId, data, ch); + } + } + } + } + } + + public void Send(int connectionId, byte[] data, int channelId) + { + if (connToMirrorID.TryGetValue(connectionId, out HSteamNetConnection conn)) + { + EResult res = SendSocket(conn, data, channelId); + + if (res == EResult.k_EResultNoConnection || res == EResult.k_EResultInvalidParam) + { + Debug.Log($"Connection to {connectionId} was lost."); + InternalDisconnect(connectionId, conn); + } + else if (res != EResult.k_EResultOK) + { + Debug.LogError($"Could not send: {res.ToString()}"); + } + } + else + { + Debug.LogError("Trying to send on unknown connection: " + connectionId); + OnReceivedError.Invoke(connectionId, TransportError.Unexpected, "ERROR Unknown Connection"); + } + } + + public string ServerGetClientAddress(int connectionId) + { + if (steamIDToMirrorID.TryGetValue(connectionId, out CSteamID steamId)) + { + return steamId.ToString(); + } + else + { + Debug.LogError("Trying to get info on unknown connection: " + connectionId); + OnReceivedError.Invoke(connectionId, TransportError.Unexpected, "ERROR Unknown Connection"); + return string.Empty; + } + } + + public void Shutdown() + { +#if UNITY_SERVER + SteamGameServerNetworkingSockets.CloseListenSocket(listenSocket); +#else + SteamNetworkingSockets.CloseListenSocket(listenSocket); +#endif + + if (c_onConnectionChange != null) + { + c_onConnectionChange.Dispose(); + c_onConnectionChange = null; + } + } + } +} +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextServer.cs.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextServer.cs.meta new file mode 100644 index 0000000..6411606 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/NextServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 84bd1cd26eae15647a6f0a27cc0e2b69 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/README.md b/Assets/Mirror/Runtime/Transports/FizzySteamworks/README.md new file mode 100644 index 0000000..9f5615b --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/README.md @@ -0,0 +1,55 @@ +# FizzySteamworks + +This is a community maintained repo forked from **[RayStorm](https://github.com/Raystorms/FizzySteamyMirror)**. + +Mirror **[docs](https://mirror-networking.com/docs/Transports/Fizzy.html)** and the official community **[Discord](https://discord.gg/N9QVxbM)**. + +FizzySteamworks brings together **[Steam](https://store.steampowered.com)** and **[Mirror](https://github.com/vis2k/Mirror)** . It supports both the old SteamNetworking and the new SteamSockets. + +## Dependencies +You must have Mirror installed and working before you can use this transport. +**[Mirror](https://github.com/vis2k/Mirror)** FizzySteamworks is also obviously dependant on Mirror which is a streamline, bug fixed, maintained version of UNET for Unity. + +You must have Steamworks.NET installed and working before you can use this transport. +**[Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET)** FizzySteamworks relies on Steamworks.NET to communicate with the **[Steamworks API](https://partner.steamgames.com/doc/sdk)**. **Requires .Net 4.x** + +## Installation +### Unity Package Manager + +Unity Package Manager support is still fairly new but you can use it like so: + +1. Open the Package Manager +2. Click the "+" (plus) button located in the upper left of the window +3. Select the "Add package from git URL..." option +4. Enter the following URL: + `https://github.com/Chykary/FizzySteamworks.git?path=/com.mirror.steamworks.net` +5. Click the "Add" button and wait several seconds for the system to download and install the Steamworks.NET package from GitHub. + +### Manual + +Fewer steps but more error prone and subject to being out of date with the latest changes: + +1. Download the latest [unitypackage](https://github.com/Chykary/FizzySteamworks/releases) from the release section. +2. Import the package into Unity. + + +## Setting Up + +1. Install Steamworks.NET instructions can be found [here](https://github.com/rlabrecque/Steamworks.NET). +2. Install Mirror **(Requires Mirror 35.0+)** from the Unity asset store **[Download Mirror](https://assetstore.unity.com/packages/tools/network/mirror-129321)**. +3. Install FizzySteamworks from package manager as discribed in the above Install step. +3. In your **"NetworkManager"** object replace **"KCP"** with **"FizzySteamworks"**. + +## Host +To be able to have your game working you need to make sure you have Steam running in the background and that the Steam API initalized correctly. You can then call StartHost and use Mirror as you normally would. + +## Client +To connect a client to a host or server you need the CSteamID of the target you wish to connect to this is used in place of IP/Port. If your creating a Peer to Peer architecture then you would use the CSteamID of the host, this is Steam user ID as a ulong value. If you are creating a Client Server architecture then you will be using the CSteamID issued to the Steam Game Server when it logs the Steam API on. This is an advanced use case supported by Heathen's Steamworks but requires additional custom code if your using Steamworks.NET directly. + +1. Send the game to your buddy. +2. Your buddy needs the host or game server **steamID64** to be able to connect. +3. Place the **steamID64** into **"localhost"** then click **"Client"** +5. Then they will be connected to your server be that your machine as a P2P connection or yoru Steam Game Server as a Client Server connection. + +## Testing your game locally +You cant connect to yourself locally while using **FizzySteamworks** since it's using Steams Networking which runs over Steam Client and addresses its connection based on the unique CSteamID of each actor. If you want to test your game locally you'll have to use **"Telepathy Transport"** instead of **"FizzySteamworks"**. diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/README.md.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/README.md.meta new file mode 100644 index 0000000..1de53c0 --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 76396690c716d454c93044b15adaaffd +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/package.json b/Assets/Mirror/Runtime/Transports/FizzySteamworks/package.json new file mode 100644 index 0000000..d46cefd --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/package.json @@ -0,0 +1,21 @@ +{ + "name": "com.mirror.steamworks.net", + "displayName": "FizzySteamworks", + "version": "5.0.2", + "unity": "2019.4", + "author": { + "name": "Mirror Community", + "url": "https://discord.gg/XXWRwf2kNd" + }, + "documentationUrl": "https://github.com/Chykary/FizzySteamworks", + "license": "https://github.com/JamesMcGhee/FizzySteamworks/blob/master/com.mirror.steamworks.net/LICENSE", + "repository": { + "type": "git", + "url": "git+https://github.com/Chykary/FizzySteamworks.git?path=/com.mirror.steamworks.net" + }, + "keywords": [ + "steam", + "steamworks" + ], + "description": "FizzySteamworks is a Mirror transport for use with Steamworks.NET. You must have already installed Steamworks.NET, you can get Steamworks.NET from git by following the instructions documented in the GitHub you aquired this from." +} \ No newline at end of file diff --git a/Assets/Mirror/Runtime/Transports/FizzySteamworks/package.json.meta b/Assets/Mirror/Runtime/Transports/FizzySteamworks/package.json.meta new file mode 100644 index 0000000..39b5f2f --- /dev/null +++ b/Assets/Mirror/Runtime/Transports/FizzySteamworks/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d89fc70cedcb5d64b903514772ec2220 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports.meta b/Assets/Mirror/Transports.meta new file mode 100644 index 0000000..72fd20d --- /dev/null +++ b/Assets/Mirror/Transports.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d7d3068968d80427e8cc256e22b0b0b5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap.meta b/Assets/Mirror/Transports/Edgegap.meta new file mode 100644 index 0000000..39cd5b6 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d2959d363903444bae4333db12a9ea1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay.meta b/Assets/Mirror/Transports/Edgegap/EdgegapRelay.meta new file mode 100644 index 0000000..34ff726 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 62c28e855fc644011b4079c268b46b71 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpClient.cs b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpClient.cs new file mode 100644 index 0000000..ecec9f7 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpClient.cs @@ -0,0 +1,141 @@ +// overwrite RawSend/Receive +using System; +using System.Net.Sockets; +using Mirror; +using UnityEngine; +using kcp2k; + +namespace Edgegap +{ + public class EdgegapKcpClient : KcpClient + { + // need buffer larger than KcpClient.rawReceiveBuffer to add metadata + readonly byte[] relayReceiveBuffer; + + // authentication + public uint userId; + public uint sessionId; + public ConnectionState connectionState = ConnectionState.Disconnected; + + // ping + double lastPingTime; + + public EdgegapKcpClient( + Action OnConnected, + Action, KcpChannel> OnData, + Action OnDisconnected, + Action OnError, + KcpConfig config) + : base(OnConnected, OnData, OnDisconnected, OnError, config) + { + relayReceiveBuffer = new byte[config.Mtu + Protocol.Overhead]; + } + + // custom start function with relay parameters; connects udp client. + public void Connect(string relayAddress, ushort relayPort, uint userId, uint sessionId) + { + // reset last state + connectionState = ConnectionState.Checking; + this.userId = userId; + this.sessionId = sessionId; + + // reuse base connect + base.Connect(relayAddress, relayPort); + } + + // parse metadata, then pass to kcp + protected override bool RawReceive(out ArraySegment segment) + { + segment = default; + if (socket == null) return false; + + try + { + if (socket.ReceiveNonBlocking(relayReceiveBuffer, out ArraySegment content)) + { + using (NetworkReaderPooled reader = NetworkReaderPool.Get(content)) + { + // parse message type + if (reader.Remaining == 0) + { + Debug.LogWarning($"EdgegapClient: message of {content.Count} is too small to parse."); + return false; + } + byte messageType = reader.ReadByte(); + + // handle message type + switch (messageType) + { + case (byte)MessageType.Ping: + { + // parse state + if (reader.Remaining < 1) return false; + ConnectionState last = connectionState; + connectionState = (ConnectionState)reader.ReadByte(); + + // log state changes for debugging. + if (connectionState != last) Debug.Log($"EdgegapClient: state updated to: {connectionState}"); + + // return true indicates Mirror to keep checking + // for further messages. + return true; + } + case (byte)MessageType.Data: + { + segment = reader.ReadBytesSegment(reader.Remaining); + return true; + } + // wrong message type. return false, don't throw. + default: return false; + } + } + } + } + catch (SocketException e) + { + Log.Info($"EdgegapClient: looks like the other end has closed the connection. This is fine: {e}"); + Disconnect(); + } + + return false; + } + + protected override void RawSend(ArraySegment data) + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + writer.WriteUInt(userId); + writer.WriteUInt(sessionId); + writer.WriteByte((byte)MessageType.Data); + writer.WriteBytes(data.Array, data.Offset, data.Count); + base.RawSend(writer); + } + } + + void SendPing() + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + writer.WriteUInt(userId); + writer.WriteUInt(sessionId); + writer.WriteByte((byte)MessageType.Ping); + base.RawSend(writer); + } + } + + public override void TickOutgoing() + { + if (connected) + { + // ping every interval for keepalive & handshake + if (NetworkTime.localTime >= lastPingTime + Protocol.PingInterval) + { + SendPing(); + lastPingTime = NetworkTime.localTime; + } + } + + base.TickOutgoing(); + } + } +} diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpClient.cs.meta b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpClient.cs.meta new file mode 100644 index 0000000..c3f2697 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a0d6fba7098f4ea3949d0195e8276adc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpServer.cs b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpServer.cs new file mode 100644 index 0000000..9aaf75f --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpServer.cs @@ -0,0 +1,203 @@ +using System; +using System.Net; +using System.Net.Sockets; +using Mirror; +using UnityEngine; +using kcp2k; + +namespace Edgegap +{ + public class EdgegapKcpServer : KcpServer + { + // need buffer larger than KcpClient.rawReceiveBuffer to add metadata + readonly byte[] relayReceiveBuffer; + + // authentication + public uint userId; + public uint sessionId; + public ConnectionState state = ConnectionState.Disconnected; + + // server is an UDP client talking to relay + protected Socket relaySocket; + public EndPoint remoteEndPoint; + + // ping + double lastPingTime; + + // custom 'active'. while connected to relay + bool relayActive; + + public EdgegapKcpServer( + Action OnConnected, + Action, KcpChannel> OnData, + Action OnDisconnected, + Action OnError, + KcpConfig config) + // TODO don't call base. don't listen to local UdpServer at all? + : base(OnConnected, OnData, OnDisconnected, OnError, config) + { + relayReceiveBuffer = new byte[config.Mtu + Protocol.Overhead]; + } + + public override bool IsActive() => relayActive; + + // custom start function with relay parameters; connects udp client. + public void Start(string relayAddress, ushort relayPort, uint userId, uint sessionId) + { + // reset last state + state = ConnectionState.Checking; + this.userId = userId; + this.sessionId = sessionId; + + // try resolve host name + if (!Common.ResolveHostname(relayAddress, out IPAddress[] addresses)) + { + OnError(0, ErrorCode.DnsResolve, $"Failed to resolve host: {relayAddress}"); + return; + } + + // create socket + remoteEndPoint = new IPEndPoint(addresses[0], relayPort); + relaySocket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); + relaySocket.Blocking = false; + + // configure buffer sizes + Common.ConfigureSocketBuffers(relaySocket, config.RecvBufferSize, config.SendBufferSize); + + // bind to endpoint for Send/Receive instead of SendTo/ReceiveFrom + relaySocket.Connect(remoteEndPoint); + relayActive = true; + } + + public override void Stop() + { + relayActive = false; + } + + protected override bool RawReceiveFrom(out ArraySegment segment, out int connectionId) + { + segment = default; + connectionId = 0; + + if (relaySocket == null) return false; + + try + { + // TODO need separate buffer. don't write into result yet. only payload + + if (relaySocket.ReceiveNonBlocking(relayReceiveBuffer, out ArraySegment content)) + { + using (NetworkReaderPooled reader = NetworkReaderPool.Get(content)) + { + // parse message type + if (reader.Remaining == 0) + { + Debug.LogWarning($"EdgegapServer: message of {content.Count} is too small to parse header."); + return false; + } + byte messageType = reader.ReadByte(); + + // handle message type + switch (messageType) + { + case (byte)MessageType.Ping: + { + // parse state + if (reader.Remaining < 1) return false; + ConnectionState last = state; + state = (ConnectionState)reader.ReadByte(); + + // log state changes for debugging. + if (state != last) Debug.Log($"EdgegapServer: state updated to: {state}"); + + // return true indicates Mirror to keep checking + // for further messages. + return true; + } + case (byte)MessageType.Data: + { + // parse connectionId and payload + if (reader.Remaining <= 4) + { + Debug.LogWarning($"EdgegapServer: message of {content.Count} is too small to parse connId."); + return false; + } + + connectionId = reader.ReadInt(); + segment = reader.ReadBytesSegment(reader.Remaining); + // Debug.Log($"EdgegapServer: receiving from connId={connectionId}: {segment.ToHexString()}"); + return true; + } + // wrong message type. return false, don't throw. + default: return false; + } + } + } + } + catch (SocketException e) + { + Log.Info($"EdgegapServer: looks like the other end has closed the connection. This is fine: {e}"); + } + return false; + } + + protected override void RawSend(int connectionId, ArraySegment data) + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + // Debug.Log($"EdgegapServer: sending to connId={connectionId}: {data.ToHexString()}"); + writer.WriteUInt(userId); + writer.WriteUInt(sessionId); + writer.WriteByte((byte)MessageType.Data); + writer.WriteInt(connectionId); + writer.WriteBytes(data.Array, data.Offset, data.Count); + ArraySegment message = writer; + + try + { + relaySocket.SendNonBlocking(message); + } + catch (SocketException e) + { + Log.Error($"KcpRleayServer: RawSend failed: {e}"); + } + } + } + + void SendPing() + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + writer.WriteUInt(userId); + writer.WriteUInt(sessionId); + writer.WriteByte((byte)MessageType.Ping); + ArraySegment message = writer; + + try + { + relaySocket.SendNonBlocking(message); + } + catch (SocketException e) + { + Debug.LogWarning($"EdgegapServer: failed to ping. perhaps the relay isn't running? {e}"); + } + } + } + + public override void TickOutgoing() + { + if (relayActive) + { + // ping every interval for keepalive & handshake + if (NetworkTime.localTime >= lastPingTime + Protocol.PingInterval) + { + SendPing(); + lastPingTime = NetworkTime.localTime; + } + } + + // base processing + base.TickOutgoing(); + } + } +} diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpServer.cs.meta b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpServer.cs.meta new file mode 100644 index 0000000..7517ee3 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd8551078397248b0848950352c208ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpTransport.cs b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpTransport.cs new file mode 100644 index 0000000..5c057b0 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpTransport.cs @@ -0,0 +1,162 @@ +// edgegap relay transport. +// reuses KcpTransport with custom KcpServer/Client. + +//#if MIRROR <- commented out because MIRROR isn't defined on first import yet +using System; +using System.Text.RegularExpressions; +using UnityEngine; +using Mirror; +using kcp2k; + +namespace Edgegap +{ + [DisallowMultipleComponent] + public class EdgegapKcpTransport : KcpTransport + { + [Header("Relay")] + public string relayAddress = "127.0.0.1"; + public ushort relayGameServerPort = 8888; + public ushort relayGameClientPort = 9999; + + // mtu for kcp transport. respects relay overhead. + public const int MaxPayload = Kcp.MTU_DEF - Protocol.Overhead; + + [Header("Relay")] + public bool relayGUI = true; + public uint userId = 11111111; + public uint sessionId = 22222222; + + // helper + internal static String ReParse(String cmd, String pattern, String defaultValue) + { + Match match = Regex.Match(cmd, pattern); + return match.Success ? match.Groups[1].Value : defaultValue; + } + + protected override void Awake() + { + // logging + // Log.Info should use Debug.Log if enabled, or nothing otherwise + // (don't want to spam the console on headless servers) + if (debugLog) + Log.Info = Debug.Log; + else + Log.Info = _ => {}; + Log.Warning = Debug.LogWarning; + Log.Error = Debug.LogError; + + // create config from serialized settings. + // with MaxPayload as max size to respect relay overhead. + config = new KcpConfig(DualMode, RecvBufferSize, SendBufferSize, MaxPayload, NoDelay, Interval, FastResend, false, SendWindowSize, ReceiveWindowSize, Timeout, MaxRetransmit); + + // client (NonAlloc version is not necessary anymore) + client = new EdgegapKcpClient( + () => OnClientConnected.Invoke(), + (message, channel) => OnClientDataReceived.Invoke(message, FromKcpChannel(channel)), + () => OnClientDisconnected.Invoke(), + (error, reason) => OnClientError.Invoke(ToTransportError(error), reason), + config + ); + + // server + server = new EdgegapKcpServer( + (connectionId) => OnServerConnected.Invoke(connectionId), + (connectionId, message, channel) => OnServerDataReceived.Invoke(connectionId, message, FromKcpChannel(channel)), + (connectionId) => OnServerDisconnected.Invoke(connectionId), + (connectionId, error, reason) => OnServerError.Invoke(connectionId, ToTransportError(error), reason), + config); + + if (statisticsLog) + InvokeRepeating(nameof(OnLogStatistics), 1, 1); + + Debug.Log("EdgegapTransport initialized!"); + } + + protected override void OnValidate() + { + // show max message sizes in inspector for convenience. + // 'config' isn't available in edit mode yet, so use MTU define. + ReliableMaxMessageSize = KcpPeer.ReliableMaxMessageSize(MaxPayload, ReceiveWindowSize); + UnreliableMaxMessageSize = KcpPeer.UnreliableMaxMessageSize(MaxPayload); + } + + // client overwrites to use EdgegapClient instead of KcpClient + public override void ClientConnect(string address) + { + // connect to relay address:port instead of the expected server address + EdgegapKcpClient client = (EdgegapKcpClient)this.client; + client.userId = userId; + client.sessionId = sessionId; + client.connectionState = ConnectionState.Checking; // reset from last time + client.Connect(relayAddress, relayGameClientPort); + } + public override void ClientConnect(Uri uri) + { + if (uri.Scheme != Scheme) + throw new ArgumentException($"Invalid url {uri}, use {Scheme}://host:port instead", nameof(uri)); + + // connect to relay address:port instead of the expected server address + EdgegapKcpClient client = (EdgegapKcpClient)this.client; + client.Connect(relayAddress, relayGameClientPort, userId, sessionId); + } + + // server overwrites to use EdgegapServer instead of KcpServer + public override void ServerStart() + { + // start the server + EdgegapKcpServer server = (EdgegapKcpServer)this.server; + server.Start(relayAddress, relayGameServerPort, userId, sessionId); + } + + void OnGUIRelay() + { + // if (server.IsActive()) return; + + GUILayout.BeginArea(new Rect(300, 30, 200, 100)); + + GUILayout.BeginHorizontal(); + GUILayout.Label("SessionId:"); + sessionId = Convert.ToUInt32(GUILayout.TextField(sessionId.ToString())); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + GUILayout.Label("UserId:"); + userId = Convert.ToUInt32(GUILayout.TextField(userId.ToString())); + GUILayout.EndHorizontal(); + + if (NetworkServer.active) + { + EdgegapKcpServer server = (EdgegapKcpServer)this.server; + GUILayout.BeginHorizontal(); + GUILayout.Label("State:"); + GUILayout.Label(server.state.ToString()); + GUILayout.EndHorizontal(); + } + else if (NetworkClient.active) + { + EdgegapKcpClient client = (EdgegapKcpClient)this.client; + GUILayout.BeginHorizontal(); + GUILayout.Label("State:"); + GUILayout.Label(client.connectionState.ToString()); + GUILayout.EndHorizontal(); + } + + GUILayout.EndArea(); + } + + // base OnGUI only shows in editor & development builds. + // here we always show it because we need the sessionid & userid buttons. +#pragma warning disable CS0109 + new void OnGUI() + { +#if UNITY_EDITOR || DEVELOPMENT_BUILD + base.OnGUI(); +#endif + if (relayGUI) OnGUIRelay(); + } + + public override string ToString() => "Edgegap Kcp Transport"; + } +#pragma warning restore CS0109 +} +//#endif MIRROR <- commented out because MIRROR isn't defined on first import yet diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpTransport.cs.meta b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpTransport.cs.meta new file mode 100644 index 0000000..e8962a9 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/EdgegapKcpTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2d1e0e17f753449798fa27474d6b86b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/Protocol.cs b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/Protocol.cs new file mode 100644 index 0000000..58ba478 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/Protocol.cs @@ -0,0 +1,29 @@ +// relay protocol definitions +namespace Edgegap +{ + public enum ConnectionState : byte + { + Disconnected = 0, // until the user calls connect() + Checking = 1, // recently connected, validation in progress + Valid = 2, // validation succeeded + Invalid = 3, // validation rejected by tower + SessionTimeout = 4, // session owner timed out + Error = 5, // other error + } + + public enum MessageType : byte + { + Ping = 1, + Data = 2 + } + + public static class Protocol + { + // MTU: relay adds up to 13 bytes of metadata in the worst case. + public const int Overhead = 13; + + // ping interval should be between 100 ms and 1 second. + // faster ping gives faster authentication, but higher bandwidth. + public const float PingInterval = 0.5f; + } +} diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/Protocol.cs.meta b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/Protocol.cs.meta new file mode 100644 index 0000000..269457c --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/Protocol.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eac30312ba61470b849e368af3c3b0e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/README.md b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/README.md new file mode 100644 index 0000000..51add6e --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/README.md @@ -0,0 +1,20 @@ +# Edgegap Relay for Mirror +Documentation: https://docs.edgegap.com/docs/distributed-relay-manager/ + +## Prerequisites +- Unity project set up with the Mirror networking library installed + - Supported Versions: [Mirror](https://assetstore.unity.com/packages/tools/network/mirror-129321) and [Mirror LTS](https://assetstore.unity.com/packages/tools/network/mirror-lts-102631) +- EdgegapTransport module downloaded and extracted + +## Steps +1. Open your Unity project and navigate to the "Assets" folder. +2. Locate the "Mirror" folder within "Assets" and open it. +3. Within the "Mirror" folder, open the "Transports" folder. +4. Drag and drop the "Unity" folder from the extracted EdgegapTransport files into the "Transports" folder. +5. Open your NetworkManager script in the Unity Editor and navigate to the "Inspector" panel. +6. In the "Inspector" panel, locate the "Network Manager" component and click the "+" button next to the "Transport" property. +7. In the "Add Component" menu that appears, select "Edgegap Transport" to add it to the NetworkManager. +8. Drag the newly added "Edgegap Transport" component into the "Transport" property in the "Inspector" panel. + +## Notes +- The EdgegapTransport module is only compatible with Mirror and Mirror LTS versions. diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/README.md.meta b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/README.md.meta new file mode 100644 index 0000000..375a0f8 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8ade7c960d8fe4e94970ddd88ede3bca +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/RelayCredentialsFromArgs.cs b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/RelayCredentialsFromArgs.cs new file mode 100644 index 0000000..670c507 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/RelayCredentialsFromArgs.cs @@ -0,0 +1,25 @@ +// parse session_id and user_id from command line args. +// mac: "open mirror.app --args session_id=123 user_id=456" +using System; +using UnityEngine; + +namespace Edgegap +{ + public class RelayCredentialsFromArgs : MonoBehaviour + { + void Awake() + { + String cmd = Environment.CommandLine; + + // parse session_id via regex + String sessionId = EdgegapKcpTransport.ReParse(cmd, "session_id=(\\d+)", "111111"); + String userID = EdgegapKcpTransport.ReParse(cmd, "user_id=(\\d+)", "222222"); + Debug.Log($"Parsed sessionId: {sessionId} user_id: {userID}"); + + // configure transport + EdgegapKcpTransport transport = GetComponent(); + transport.sessionId = UInt32.Parse(sessionId); + transport.userId = UInt32.Parse(userID); + } + } +} diff --git a/Assets/Mirror/Transports/Edgegap/EdgegapRelay/RelayCredentialsFromArgs.cs.meta b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/RelayCredentialsFromArgs.cs.meta new file mode 100644 index 0000000..9dcd8f7 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/EdgegapRelay/RelayCredentialsFromArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e9ec7091b26c4d3882f4b42f10f9b8c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Edgegap/edgegap.png b/Assets/Mirror/Transports/Edgegap/edgegap.png new file mode 100644 index 0000000..89aa798 Binary files /dev/null and b/Assets/Mirror/Transports/Edgegap/edgegap.png differ diff --git a/Assets/Mirror/Transports/Edgegap/edgegap.png.meta b/Assets/Mirror/Transports/Edgegap/edgegap.png.meta new file mode 100644 index 0000000..08d8fd1 --- /dev/null +++ b/Assets/Mirror/Transports/Edgegap/edgegap.png.meta @@ -0,0 +1,123 @@ +fileFormatVersion: 2 +guid: 3ea6ff15cda674a57b0c7c8b7dc1878c +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + 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 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 16 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Encryption.meta b/Assets/Mirror/Transports/Encryption.meta new file mode 100644 index 0000000..6c507ab --- /dev/null +++ b/Assets/Mirror/Transports/Encryption.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 741b3c7e5d0842049ff50a2f6e27ca12 +timeCreated: 1708015148 \ No newline at end of file diff --git a/Assets/Mirror/Transports/Encryption/Editor.meta b/Assets/Mirror/Transports/Encryption/Editor.meta new file mode 100644 index 0000000..b6cf690 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/Editor.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0d3cd9d7d6e84a578f7e4b384ff813f1 +timeCreated: 1708793986 \ No newline at end of file diff --git a/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportEditor.asmdef b/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportEditor.asmdef new file mode 100644 index 0000000..0ba9c76 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportEditor.asmdef @@ -0,0 +1,18 @@ +{ + "name": "EncryptionTransportEditor", + "rootNamespace": "", + "references": [ + "GUID:627104647b9c04b4ebb8978a92ecac63" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportEditor.asmdef.meta b/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportEditor.asmdef.meta new file mode 100644 index 0000000..43ba20c --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportEditor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4c9c7b0ef83e6e945b276d644816a489 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportInspector.cs b/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportInspector.cs new file mode 100644 index 0000000..24557f9 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportInspector.cs @@ -0,0 +1,81 @@ +using UnityEditor; +using UnityEngine; + +namespace Mirror.Transports.Encryption +{ + [CustomEditor(typeof(EncryptionTransport), true)] + public class EncryptionTransportInspector : UnityEditor.Editor + { + SerializedProperty innerProperty; + SerializedProperty clientValidatesServerPubKeyProperty; + SerializedProperty clientTrustedPubKeySignaturesProperty; + SerializedProperty serverKeypairPathProperty; + SerializedProperty serverLoadKeyPairFromFileProperty; + + // Assuming proper SerializedProperty definitions for properties + // Add more SerializedProperty fields related to different modes as needed + + void OnEnable() + { + innerProperty = serializedObject.FindProperty("inner"); + clientValidatesServerPubKeyProperty = serializedObject.FindProperty("clientValidateServerPubKey"); + clientTrustedPubKeySignaturesProperty = serializedObject.FindProperty("clientTrustedPubKeySignatures"); + serverKeypairPathProperty = serializedObject.FindProperty("serverKeypairPath"); + serverLoadKeyPairFromFileProperty = serializedObject.FindProperty("serverLoadKeyPairFromFile"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + EditorGUILayout.LabelField("Common", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(innerProperty); + EditorGUILayout.Separator(); + // Client Section + EditorGUILayout.LabelField("Client", EditorStyles.boldLabel); + EditorGUILayout.HelpBox("Validating the servers public key is essential for complete man-in-the-middle (MITM) safety, but might not be feasible for all modes of hosting.", MessageType.Info); + EditorGUILayout.PropertyField(clientValidatesServerPubKeyProperty, new GUIContent("Validate Server Public Key")); + + EncryptionTransport.ValidationMode validationMode = (EncryptionTransport.ValidationMode)clientValidatesServerPubKeyProperty.enumValueIndex; + + switch (validationMode) + { + case EncryptionTransport.ValidationMode.List: + EditorGUILayout.PropertyField(clientTrustedPubKeySignaturesProperty); + break; + case EncryptionTransport.ValidationMode.Callback: + EditorGUILayout.HelpBox("Please set the EncryptionTransport.onClientValidateServerPubKey at runtime.", MessageType.Info); + break; + } + + EditorGUILayout.Separator(); + // Server Section + EditorGUILayout.LabelField("Server", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(serverLoadKeyPairFromFileProperty, new GUIContent("Load Keypair From File")); + if (serverLoadKeyPairFromFileProperty.boolValue) + { + EditorGUILayout.PropertyField(serverKeypairPathProperty, new GUIContent("Keypair File Path")); + } + if(GUILayout.Button("Generate Key Pair")) + { + EncryptionCredentials keyPair = EncryptionCredentials.Generate(); + string path = EditorUtility.SaveFilePanel("Select where to save the keypair", "", "server-keys.json", "json"); + if (!string.IsNullOrEmpty(path)) + { + keyPair.SaveToFile(path); + EditorUtility.DisplayDialog("KeyPair Saved", $"Successfully saved the keypair.\nThe fingerprint is {keyPair.PublicKeyFingerprint}, you can also retrieve it from the saved json file at any point.", "Ok"); + if (validationMode == EncryptionTransport.ValidationMode.List) + { + if (EditorUtility.DisplayDialog("Add key to trusted list?", "Do you also want to add the generated key to the trusted list?", "Yes", "No")) + { + clientTrustedPubKeySignaturesProperty.arraySize++; + clientTrustedPubKeySignaturesProperty.GetArrayElementAtIndex(clientTrustedPubKeySignaturesProperty.arraySize - 1).stringValue = keyPair.PublicKeyFingerprint; + } + } + } + } + + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportInspector.cs.meta b/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportInspector.cs.meta new file mode 100644 index 0000000..9aad40b --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/Editor/EncryptionTransportInspector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 871580d2094a46139279d651cec92b5d +timeCreated: 1708794004 \ No newline at end of file diff --git a/Assets/Mirror/Transports/Encryption/EncryptedConnection.cs b/Assets/Mirror/Transports/Encryption/EncryptedConnection.cs new file mode 100644 index 0000000..9515e74 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/EncryptedConnection.cs @@ -0,0 +1,595 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using UnityEngine.Profiling; + +namespace Mirror.Transports.Encryption +{ + public class EncryptedConnection + { + // 256-bit key + private const int KeyLength = 32; + // 512-bit salt for the key derivation function + private const int HkdfSaltSize = KeyLength * 2; + + // Info tag for the HKDF, this just adds more entropy + private static readonly byte[] HkdfInfo = Encoding.UTF8.GetBytes("Mirror/EncryptionTransport"); + + // fixed size of the unique per-packet nonce. Defaults to 12 bytes/96 bits (not recommended to be changed) + private const int NonceSize = 12; + + // this is the size of the "checksum" included in each encrypted payload + // 16 bytes/128 bytes is the recommended value for best security + // can be reduced to 12 bytes for a small space savings, but makes encryption slightly weaker. + // Setting it lower than 12 bytes is not recommended + private const int MacSizeBytes = 16; + + private const int MacSizeBits = MacSizeBytes * 8; + + // How much metadata overhead we have for regular packets + public const int Overhead = sizeof(OpCodes) + MacSizeBytes + NonceSize; + + // After how many seconds of not receiving a handshake packet we should time out + private const double DurationTimeout = 2; // 2s + + // After how many seconds to assume the last handshake packet got lost and to resend another one + private const double DurationResend = 0.05; // 50ms + + + // Static fields for allocation efficiency, makes this not thread safe + // It'd be as easy as using ThreadLocal though to fix that + + // Set up a global cipher instance, it is initialised/reset before use + // (AesFastEngine used to exist, but was removed due to side channel issues) + // use AesUtilities.CreateEngine here as it'll pick the hardware accelerated one if available (which is will not be unless on .net core) + private static readonly GcmBlockCipher Cipher = new GcmBlockCipher(AesUtilities.CreateEngine()); + + // Set up a global HKDF with a SHA-256 digest + private static readonly HkdfBytesGenerator Hkdf = new HkdfBytesGenerator(new Sha256Digest()); + + // Global byte array to store nonce sent by the remote side, they're used immediately after + private static readonly byte[] ReceiveNonce = new byte[NonceSize]; + + // Buffer for the remote salt, as bouncycastle needs to take a byte[] *rolls eyes* + private static byte[] _tmpRemoteSaltBuffer = new byte[HkdfSaltSize]; + // buffer for encrypt/decrypt operations, resized larger as needed + // this is also the buffer that will be returned to mirror via ArraySegment + // so any thread safety concerns would need to take extra care here + private static byte[] _tmpCryptBuffer = new byte[2048]; + + // packet headers + enum OpCodes : byte + { + // start at 1 to maybe filter out random noise + Data = 1, + HandshakeStart = 2, + HandshakeAck = 3, + HandshakeFin = 4, + } + + enum State + { + // Waiting for a handshake to arrive + // this is for _sendsFirst: + // - false: OpCodes.HandshakeStart + // - true: Opcodes.HandshakeAck + WaitingHandshake, + + // Waiting for a handshake reply/acknowledgement to arrive + // this is for _sendsFirst: + // - false: OpCodes.HandshakeFine + // - true: Opcodes.Data (implicitly) + WaitingHandshakeReply, + + // Both sides have confirmed the keys are exchanged and data can be sent freely + Ready + } + + private State _state = State.WaitingHandshake; + + // Key exchange confirmed and data can be sent freely + public bool IsReady => _state == State.Ready; + // Callback to send off encrypted data + private Action, int> _send; + // Callback when received data has been decrypted + private Action, int> _receive; + // Callback when the connection becomes ready + private Action _ready; + // On-error callback, disconnect expected + private Action _error; + // Optional callback to validate the remotes public key, validation on one side is necessary to ensure MITM resistance + // (usually client validates the server key) + private Func _validateRemoteKey; + // Our asymmetric credentials for the initial DH exchange + private EncryptionCredentials _credentials; + private byte[] _hkdfSalt; + + // After no handshake packet in this many seconds, the handshake fails + private double _handshakeTimeout; + // When to assume the last handshake packet got lost and to resend another one + private double _nextHandshakeResend; + + + // we can reuse the _cipherParameters here since the nonce is stored as the byte[] reference we pass in + // so we can update it without creating a new AeadParameters instance + // this might break in the future! (will cause bad data) + private byte[] _nonce = new byte[NonceSize]; + private AeadParameters _cipherParametersEncrypt; + private AeadParameters _cipherParametersDecrypt; + + + /* + * Specifies if we send the first key, then receive ack, then send fin + * Or the opposite if set to false + * + * The client does this, since the fin is not acked explicitly, but by receiving data to decrypt + */ + private readonly bool _sendsFirst; + + public EncryptedConnection(EncryptionCredentials credentials, + bool isClient, + Action, int> sendAction, + Action, int> receiveAction, + Action readyAction, + Action errorAction, + Func validateRemoteKey = null) + { + _credentials = credentials; + _sendsFirst = isClient; + if (!_sendsFirst) + { + // salt is controlled by the server + _hkdfSalt = GenerateSecureBytes(HkdfSaltSize); + } + _send = sendAction; + _receive = receiveAction; + _ready = readyAction; + _error = errorAction; + _validateRemoteKey = validateRemoteKey; + } + + // Generates a random starting nonce + private static byte[] GenerateSecureBytes(int size) + { + byte[] bytes = new byte[size]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(bytes); + } + + return bytes; + } + + public void OnReceiveRaw(ArraySegment data, int channel) + { + if (data.Count < 1) + { + _error(TransportError.Unexpected, "Received empty packet"); + return; + } + + using (NetworkReaderPooled reader = NetworkReaderPool.Get(data)) + { + OpCodes opcode = (OpCodes)reader.ReadByte(); + switch (opcode) + { + case OpCodes.Data: + // first sender ready is implicit when data is received + if (_sendsFirst && _state == State.WaitingHandshakeReply) + { + SetReady(); + } + else if (!IsReady) + { + _error(TransportError.Unexpected, "Unexpected data while not ready."); + } + + if (reader.Remaining < Overhead) + { + _error(TransportError.Unexpected, "received data packet smaller than metadata size"); + return; + } + + ArraySegment ciphertext = reader.ReadBytesSegment(reader.Remaining - NonceSize); + reader.ReadBytes(ReceiveNonce, NonceSize); + + Profiler.BeginSample("EncryptedConnection.Decrypt"); + ArraySegment plaintext = Decrypt(ciphertext); + Profiler.EndSample(); + if (plaintext.Count == 0) + { + // error + return; + } + _receive(plaintext, channel); + break; + case OpCodes.HandshakeStart: + if (_sendsFirst) + { + _error(TransportError.Unexpected, "Received HandshakeStart packet, we don't expect this."); + return; + } + + if (_state == State.WaitingHandshakeReply) + { + // this is fine, packets may arrive out of order + return; + } + + _state = State.WaitingHandshakeReply; + ResetTimeouts(); + CompleteExchange(reader.ReadBytesSegment(reader.Remaining), _hkdfSalt); + SendHandshakeAndPubKey(OpCodes.HandshakeAck); + break; + case OpCodes.HandshakeAck: + if (!_sendsFirst) + { + _error(TransportError.Unexpected, "Received HandshakeAck packet, we don't expect this."); + return; + } + + if (IsReady) + { + // this is fine, packets may arrive out of order + return; + } + + if (_state == State.WaitingHandshakeReply) + { + // this is fine, packets may arrive out of order + return; + } + + + _state = State.WaitingHandshakeReply; + ResetTimeouts(); + reader.ReadBytes(_tmpRemoteSaltBuffer, HkdfSaltSize); + CompleteExchange(reader.ReadBytesSegment(reader.Remaining), _tmpRemoteSaltBuffer); + SendHandshakeFin(); + break; + case OpCodes.HandshakeFin: + if (_sendsFirst) + { + _error(TransportError.Unexpected, "Received HandshakeFin packet, we don't expect this."); + return; + } + + if (IsReady) + { + // this is fine, packets may arrive out of order + return; + } + + if (_state != State.WaitingHandshakeReply) + { + _error(TransportError.Unexpected, + "Received HandshakeFin packet, we didn't expect this yet."); + return; + } + + SetReady(); + + break; + default: + _error(TransportError.InvalidReceive, $"Unhandled opcode {(byte)opcode:x}"); + break; + } + } + } + private void SetReady() + { + // done with credentials, null out the reference + _credentials = null; + + _state = State.Ready; + _ready(); + } + + private void ResetTimeouts() + { + _handshakeTimeout = 0; + _nextHandshakeResend = -1; + } + + public void Send(ArraySegment data, int channel) + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + writer.WriteByte((byte)OpCodes.Data); + Profiler.BeginSample("EncryptedConnection.Encrypt"); + ArraySegment encrypted = Encrypt(data); + Profiler.EndSample(); + + if (encrypted.Count == 0) + { + // error + return; + } + writer.WriteBytes(encrypted.Array, 0, encrypted.Count); + // write nonce after since Encrypt will update it + writer.WriteBytes(_nonce, 0, NonceSize); + _send(writer.ToArraySegment(), channel); + } + } + + private ArraySegment Encrypt(ArraySegment plaintext) + { + if (plaintext.Count == 0) + { + // Invalid + return new ArraySegment(); + } + // Need to make the nonce unique again before encrypting another message + UpdateNonce(); + // Re-initialize the cipher with our cached parameters + Cipher.Init(true, _cipherParametersEncrypt); + + // Calculate the expected output size, this should always be input size + mac size + int outSize = Cipher.GetOutputSize(plaintext.Count); +#if UNITY_EDITOR + // expecting the outSize to be input size + MacSize + if (outSize != plaintext.Count + MacSizeBytes) + { + throw new Exception($"Encrypt: Unexpected output size (Expected {plaintext.Count + MacSizeBytes}, got {outSize}"); + } +#endif + // Resize the static buffer to fit + EnsureSize(ref _tmpCryptBuffer, outSize); + int resultLen; + try + { + // Run the plain text through the cipher, ProcessBytes will only process full blocks + resultLen = + Cipher.ProcessBytes(plaintext.Array, plaintext.Offset, plaintext.Count, _tmpCryptBuffer, 0); + // Then run any potentially remaining partial blocks through with DoFinal (and calculate the mac) + resultLen += Cipher.DoFinal(_tmpCryptBuffer, resultLen); + } + // catch all Exception's since BouncyCastle is fairly noisy with both standard and their own exception types + // + catch (Exception e) + { + _error(TransportError.Unexpected, $"Unexpected exception while encrypting {e.GetType()}: {e.Message}"); + return new ArraySegment(); + } +#if UNITY_EDITOR + // expecting the result length to match the previously calculated input size + MacSize + if (resultLen != outSize) + { + throw new Exception($"Encrypt: resultLen did not match outSize (expected {outSize}, got {resultLen})"); + } +#endif + return new ArraySegment(_tmpCryptBuffer, 0, resultLen); + } + + private ArraySegment Decrypt(ArraySegment ciphertext) + { + if (ciphertext.Count <= MacSizeBytes) + { + _error(TransportError.Unexpected, $"Received too short data packet (min {{MacSizeBytes + 1}}, got {ciphertext.Count})"); + // Invalid + return new ArraySegment(); + } + // Re-initialize the cipher with our cached parameters + Cipher.Init(false, _cipherParametersDecrypt); + + // Calculate the expected output size, this should always be input size - mac size + int outSize = Cipher.GetOutputSize(ciphertext.Count); +#if UNITY_EDITOR + // expecting the outSize to be input size - MacSize + if (outSize != ciphertext.Count - MacSizeBytes) + { + throw new Exception($"Decrypt: Unexpected output size (Expected {ciphertext.Count - MacSizeBytes}, got {outSize}"); + } +#endif + // Resize the static buffer to fit + EnsureSize(ref _tmpCryptBuffer, outSize); + int resultLen; + try + { + // Run the ciphertext through the cipher, ProcessBytes will only process full blocks + resultLen = + Cipher.ProcessBytes(ciphertext.Array, ciphertext.Offset, ciphertext.Count, _tmpCryptBuffer, 0); + // Then run any potentially remaining partial blocks through with DoFinal (and calculate/check the mac) + resultLen += Cipher.DoFinal(_tmpCryptBuffer, resultLen); + } + // catch all Exception's since BouncyCastle is fairly noisy with both standard and their own exception types + catch (Exception e) + { + _error(TransportError.Unexpected, $"Unexpected exception while decrypting {e.GetType()}: {e.Message}. This usually signifies corrupt data"); + return new ArraySegment(); + } +#if UNITY_EDITOR + // expecting the result length to match the previously calculated input size + MacSize + if (resultLen != outSize) + { + throw new Exception($"Decrypt: resultLen did not match outSize (expected {outSize}, got {resultLen})"); + } +#endif + return new ArraySegment(_tmpCryptBuffer, 0, resultLen); + } + + private void UpdateNonce() + { + // increment the nonce by one + // we need to ensure the nonce is *always* unique and not reused + // easiest way to do this is by simply incrementing it + for (int i = 0; i < NonceSize; i++) + { + _nonce[i]++; + if (_nonce[i] != 0) + { + break; + } + } + } + + private static void EnsureSize(ref byte[] buffer, int size) + { + if (buffer.Length < size) + { + // double buffer to avoid constantly resizing by a few bytes + Array.Resize(ref buffer, Math.Max(size, buffer.Length * 2)); + } + } + + private void SendHandshakeAndPubKey(OpCodes opcode) + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + writer.WriteByte((byte)opcode); + if (opcode == OpCodes.HandshakeAck) + { + writer.WriteBytes(_hkdfSalt, 0, HkdfSaltSize); + } + writer.WriteBytes(_credentials.PublicKeySerialized, 0, _credentials.PublicKeySerialized.Length); + _send(writer.ToArraySegment(), Channels.Unreliable); + } + } + + private void SendHandshakeFin() + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + writer.WriteByte((byte)OpCodes.HandshakeFin); + _send(writer.ToArraySegment(), Channels.Unreliable); + } + } + + private void CompleteExchange(ArraySegment remotePubKeyRaw, byte[] salt) + { + AsymmetricKeyParameter remotePubKey; + try + { + remotePubKey = EncryptionCredentials.DeserializePublicKey(remotePubKeyRaw); + } + catch (Exception e) + { + _error(TransportError.Unexpected, $"Failed to deserialize public key of remote. {e.GetType()}: {e.Message}"); + return; + } + + if (_validateRemoteKey != null) + { + PubKeyInfo info = new PubKeyInfo + { + Fingerprint = EncryptionCredentials.PubKeyFingerprint(remotePubKeyRaw), + Serialized = remotePubKeyRaw, + Key = remotePubKey + }; + if (!_validateRemoteKey(info)) + { + _error(TransportError.Unexpected, $"Remote public key (fingerprint: {info.Fingerprint}) failed validation. "); + return; + } + } + + // Calculate a common symmetric key from our private key and the remotes public key + // This gives us the same key on the other side, with our public key and their remote + // It's like magic, but with math! + ECDHBasicAgreement ecdh = new ECDHBasicAgreement(); + ecdh.Init(_credentials.PrivateKey); + byte[] sharedSecret; + try + { + sharedSecret = ecdh.CalculateAgreement(remotePubKey).ToByteArrayUnsigned(); + } + catch + (Exception e) + { + _error(TransportError.Unexpected, $"Failed to calculate the ECDH key exchange. {e.GetType()}: {e.Message}"); + return; + } + + if (salt.Length != HkdfSaltSize) + { + _error(TransportError.Unexpected, $"Salt is expected to be {HkdfSaltSize} bytes long, got {salt.Length}."); + return; + } + + Hkdf.Init(new HkdfParameters(sharedSecret, salt, HkdfInfo)); + + // Allocate a buffer for the output key + byte[] keyRaw = new byte[KeyLength]; + + // Generate the output keying material + Hkdf.GenerateBytes(keyRaw, 0, keyRaw.Length); + + KeyParameter key = new KeyParameter(keyRaw); + + // generate a starting nonce + _nonce = GenerateSecureBytes(NonceSize); + + // we pass in the nonce array once (as it's stored by reference) so we can cache the AeadParameters instance + // instead of creating a new one each encrypt/decrypt + _cipherParametersEncrypt = new AeadParameters(key, MacSizeBits, _nonce); + _cipherParametersDecrypt = new AeadParameters(key, MacSizeBits, ReceiveNonce); + } + + /** + * non-ready connections need to be ticked for resending key data over unreliable + */ + public void TickNonReady(double time) + { + if (IsReady) + { + return; + } + + // Timeout reset + if (_handshakeTimeout == 0) + { + _handshakeTimeout = time + DurationTimeout; + } + else if (time > _handshakeTimeout) + { + _error?.Invoke(TransportError.Timeout, $"Timed out during {_state}, this probably just means the other side went away which is fine."); + return; + } + + // Timeout reset + if (_nextHandshakeResend < 0) + { + _nextHandshakeResend = time + DurationResend; + return; + } + + if (time < _nextHandshakeResend) + { + // Resend isn't due yet + return; + } + + _nextHandshakeResend = time + DurationResend; + switch (_state) + { + case State.WaitingHandshake: + if (_sendsFirst) + { + SendHandshakeAndPubKey(OpCodes.HandshakeStart); + } + + break; + case State.WaitingHandshakeReply: + if (_sendsFirst) + { + SendHandshakeFin(); + } + else + { + SendHandshakeAndPubKey(OpCodes.HandshakeAck); + } + + break; + case State.Ready: // IsReady is checked above & early-returned + default: + throw new ArgumentOutOfRangeException(); + } + } + } +} diff --git a/Assets/Mirror/Transports/Encryption/EncryptedConnection.cs.meta b/Assets/Mirror/Transports/Encryption/EncryptedConnection.cs.meta new file mode 100644 index 0000000..b5e5209 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/EncryptedConnection.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 28f3ac4ff1d346a895d0b4ff714fb57b +timeCreated: 1708111337 \ No newline at end of file diff --git a/Assets/Mirror/Transports/Encryption/EncryptionCredentials.cs b/Assets/Mirror/Transports/Encryption/EncryptionCredentials.cs new file mode 100644 index 0000000..2e0b042 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/EncryptionCredentials.cs @@ -0,0 +1,125 @@ +using System; +using System.IO; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Security; +using UnityEngine; + +namespace Mirror.Transports.Encryption +{ + public class EncryptionCredentials + { + const int PrivateKeyBits = 256; + // don't actually need to store this currently + // but we'll need to for loading/saving from file maybe? + // public ECPublicKeyParameters PublicKey; + + // The serialized public key, in DER format + public byte[] PublicKeySerialized; + public ECPrivateKeyParameters PrivateKey; + public string PublicKeyFingerprint; + + EncryptionCredentials() {} + + // TODO: load from file + public static EncryptionCredentials Generate() + { + var generator = new ECKeyPairGenerator(); + generator.Init(new KeyGenerationParameters(new SecureRandom(), PrivateKeyBits)); + AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair(); + var serialized = SerializePublicKey((ECPublicKeyParameters)keyPair.Public); + return new EncryptionCredentials + { + // see fields above + // PublicKey = (ECPublicKeyParameters)keyPair.Public, + PublicKeySerialized = serialized, + PublicKeyFingerprint = PubKeyFingerprint(new ArraySegment(serialized)), + PrivateKey = (ECPrivateKeyParameters)keyPair.Private + }; + } + + public static byte[] SerializePublicKey(AsymmetricKeyParameter publicKey) + { + // apparently the best way to transmit this public key over the network is to serialize it as a DER + SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey); + return publicKeyInfo.ToAsn1Object().GetDerEncoded(); + } + + public static AsymmetricKeyParameter DeserializePublicKey(ArraySegment pubKey) + { + // And then we do this to deserialize from the DER (from above) + // the "new MemoryStream" actually saves an allocation, since otherwise the ArraySegment would be converted + // to a byte[] first and then shoved through a MemoryStream + return PublicKeyFactory.CreateKey(new MemoryStream(pubKey.Array, pubKey.Offset, pubKey.Count, false)); + } + + public static byte[] SerializePrivateKey(AsymmetricKeyParameter privateKey) + { + // Serialize privateKey as a DER + PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey); + return privateKeyInfo.ToAsn1Object().GetDerEncoded(); + } + + public static AsymmetricKeyParameter DeserializePrivateKey(ArraySegment privateKey) + { + // And then we do this to deserialize from the DER (from above) + // the "new MemoryStream" actually saves an allocation, since otherwise the ArraySegment would be converted + // to a byte[] first and then shoved through a MemoryStream + return PrivateKeyFactory.CreateKey(new MemoryStream(privateKey.Array, privateKey.Offset, privateKey.Count, false)); + } + + public static string PubKeyFingerprint(ArraySegment publicKeyBytes) + { + Sha256Digest digest = new Sha256Digest(); + byte[] hash = new byte[digest.GetDigestSize()]; + digest.BlockUpdate(publicKeyBytes.Array, publicKeyBytes.Offset, publicKeyBytes.Count); + digest.DoFinal(hash, 0); + + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + + public void SaveToFile(string path) + { + string json = JsonUtility.ToJson(new SerializedPair + { + PublicKeyFingerprint = PublicKeyFingerprint, + PublicKey = Convert.ToBase64String(PublicKeySerialized), + PrivateKey= Convert.ToBase64String(SerializePrivateKey(PrivateKey)), + }); + File.WriteAllText(path, json); + } + + public static EncryptionCredentials LoadFromFile(string path) + { + string json = File.ReadAllText(path); + SerializedPair serializedPair = JsonUtility.FromJson(json); + + byte[] publicKeyBytes = Convert.FromBase64String(serializedPair.PublicKey); + byte[] privateKeyBytes = Convert.FromBase64String(serializedPair.PrivateKey); + + if (serializedPair.PublicKeyFingerprint != PubKeyFingerprint(new ArraySegment(publicKeyBytes))) + { + throw new Exception("Saved public key fingerprint does not match public key."); + } + return new EncryptionCredentials + { + PublicKeySerialized = publicKeyBytes, + PublicKeyFingerprint = serializedPair.PublicKeyFingerprint, + PrivateKey = (ECPrivateKeyParameters) DeserializePrivateKey(new ArraySegment(privateKeyBytes)) + }; + } + + private class SerializedPair + { + public string PublicKeyFingerprint; + public string PublicKey; + public string PrivateKey; + } + } +} diff --git a/Assets/Mirror/Transports/Encryption/EncryptionCredentials.cs.meta b/Assets/Mirror/Transports/Encryption/EncryptionCredentials.cs.meta new file mode 100644 index 0000000..38f1197 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/EncryptionCredentials.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: af6ae5f74f9548588cba5731643fabaf +timeCreated: 1708139579 \ No newline at end of file diff --git a/Assets/Mirror/Transports/Encryption/EncryptionTransport.cs b/Assets/Mirror/Transports/Encryption/EncryptionTransport.cs new file mode 100644 index 0000000..271d108 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/EncryptionTransport.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Profiling; +using UnityEngine.Serialization; + +namespace Mirror.Transports.Encryption +{ + [HelpURL("https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport")] + public class EncryptionTransport : Transport + { + public Transport inner; + + public enum ValidationMode + { + Off, + List, + Callback, + } + + public ValidationMode clientValidateServerPubKey; + [Tooltip("List of public key fingerprints the client will accept")] + public string[] clientTrustedPubKeySignatures; + public Func onClientValidateServerPubKey; + public bool serverLoadKeyPairFromFile; + public string serverKeypairPath = "./server-keys.json"; + + private EncryptedConnection _client; + + private Dictionary _serverConnections = new Dictionary(); + + private List _serverPendingConnections = + new List(); + + private EncryptionCredentials _credentials; + public string EncryptionPublicKeyFingerprint => _credentials?.PublicKeyFingerprint; + public byte[] EncryptionPublicKey => _credentials?.PublicKeySerialized; + + private void ServerRemoveFromPending(EncryptedConnection con) + { + for (int i = 0; i < _serverPendingConnections.Count; i++) + { + if (_serverPendingConnections[i] == con) + { + // remove by swapping with last + int lastIndex = _serverPendingConnections.Count - 1; + _serverPendingConnections[i] = _serverPendingConnections[lastIndex]; + _serverPendingConnections.RemoveAt(lastIndex); + break; + } + } + } + + private void HandleInnerServerDisconnected(int connId) + { + if (_serverConnections.TryGetValue(connId, out EncryptedConnection con)) + { + ServerRemoveFromPending(con); + _serverConnections.Remove(connId); + } + OnServerDisconnected?.Invoke(connId); + } + + private void HandleInnerServerError(int connId, TransportError type, string msg) + { + OnServerError?.Invoke(connId, type, $"inner: {msg}"); + } + + private void HandleInnerServerDataReceived(int connId, ArraySegment data, int channel) + { + if (_serverConnections.TryGetValue(connId, out EncryptedConnection c)) + { + c.OnReceiveRaw(data, channel); + } + } + + private void HandleInnerServerConnected(int connId) + { + Debug.Log($"[EncryptionTransport] New connection #{connId}"); + EncryptedConnection ec = null; + ec = new EncryptedConnection( + _credentials, + false, + (segment, channel) => inner.ServerSend(connId, segment, channel), + (segment, channel) => OnServerDataReceived?.Invoke(connId, segment, channel), + () => + { + Debug.Log($"[EncryptionTransport] Connection #{connId} is ready"); + ServerRemoveFromPending(ec); + OnServerConnected?.Invoke(connId); + }, + (type, msg) => + { + OnServerError?.Invoke(connId, type, msg); + ServerDisconnect(connId); + }); + _serverConnections.Add(connId, ec); + _serverPendingConnections.Add(ec); + } + + private void HandleInnerClientDisconnected() + { + _client = null; + OnClientDisconnected?.Invoke(); + } + + private void HandleInnerClientError(TransportError arg1, string arg2) + { + OnClientError?.Invoke(arg1, $"inner: {arg2}"); + } + + private void HandleInnerClientDataReceived(ArraySegment data, int channel) + { + _client?.OnReceiveRaw(data, channel); + } + + private void HandleInnerClientConnected() + { + _client = new EncryptedConnection( + _credentials, + true, + (segment, channel) => inner.ClientSend(segment, channel), + (segment, channel) => OnClientDataReceived?.Invoke(segment, channel), + () => + { + OnClientConnected?.Invoke(); + }, + (type, msg) => + { + OnClientError?.Invoke(type, msg); + ClientDisconnect(); + }, + HandleClientValidateServerPubKey); + } + + private bool HandleClientValidateServerPubKey(PubKeyInfo pubKeyInfo) + { + switch (clientValidateServerPubKey) + { + case ValidationMode.Off: + return true; + case ValidationMode.List: + return Array.IndexOf(clientTrustedPubKeySignatures, pubKeyInfo.Fingerprint) >= 0; + case ValidationMode.Callback: + return onClientValidateServerPubKey(pubKeyInfo); + default: + throw new ArgumentOutOfRangeException(); + } + } + + public override bool Available() => inner.Available(); + + public override bool ClientConnected() => _client != null && _client.IsReady; + + public override void ClientConnect(string address) + { + switch (clientValidateServerPubKey) + { + case ValidationMode.Off: + break; + case ValidationMode.List: + if (clientTrustedPubKeySignatures == null || clientTrustedPubKeySignatures.Length == 0) + { + OnClientError?.Invoke(TransportError.Unexpected, "Validate Server Public Key is set to List, but the clientTrustedPubKeySignatures list is empty."); + return; + } + break; + case ValidationMode.Callback: + if (onClientValidateServerPubKey == null) + { + OnClientError?.Invoke(TransportError.Unexpected, "Validate Server Public Key is set to Callback, but the onClientValidateServerPubKey handler is not set"); + return; + } + break; + default: + throw new ArgumentOutOfRangeException(); + } + _credentials = EncryptionCredentials.Generate(); + inner.OnClientConnected = HandleInnerClientConnected; + inner.OnClientDataReceived = HandleInnerClientDataReceived; + inner.OnClientDataSent = (bytes, channel) => OnClientDataSent?.Invoke(bytes, channel); + inner.OnClientError = HandleInnerClientError; + inner.OnClientDisconnected = HandleInnerClientDisconnected; + inner.ClientConnect(address); + } + + public override void ClientSend(ArraySegment segment, int channelId = Channels.Reliable) => + _client?.Send(segment, channelId); + + public override void ClientDisconnect() => inner.ClientDisconnect(); + + public override Uri ServerUri() => inner.ServerUri(); + + public override bool ServerActive() => inner.ServerActive(); + + public override void ServerStart() + { + if (serverLoadKeyPairFromFile) + { + _credentials = EncryptionCredentials.LoadFromFile(serverKeypairPath); + } + else + { + _credentials = EncryptionCredentials.Generate(); + } + inner.OnServerConnected = HandleInnerServerConnected; + inner.OnServerDataReceived = HandleInnerServerDataReceived; + inner.OnServerDataSent = (connId, bytes, channel) => OnServerDataSent?.Invoke(connId, bytes, channel); + inner.OnServerError = HandleInnerServerError; + inner.OnServerDisconnected = HandleInnerServerDisconnected; + inner.ServerStart(); + } + + public override void ServerSend(int connectionId, ArraySegment segment, int channelId = Channels.Reliable) + { + if (_serverConnections.TryGetValue(connectionId, out EncryptedConnection connection) && connection.IsReady) + { + connection.Send(segment, channelId); + } + } + + public override void ServerDisconnect(int connectionId) + { + // cleanup is done via inners disconnect event + inner.ServerDisconnect(connectionId); + } + + public override string ServerGetClientAddress(int connectionId) => inner.ServerGetClientAddress(connectionId); + + public override void ServerStop() => inner.ServerStop(); + + public override int GetMaxPacketSize(int channelId = Channels.Reliable) => + inner.GetMaxPacketSize(channelId) - EncryptedConnection.Overhead; + + public override void Shutdown() => inner.Shutdown(); + + public override void ClientEarlyUpdate() + { + inner.ClientEarlyUpdate(); + } + + public override void ClientLateUpdate() + { + inner.ClientLateUpdate(); + Profiler.BeginSample("EncryptionTransport.ServerLateUpdate"); + _client?.TickNonReady(NetworkTime.localTime); + Profiler.EndSample(); + } + + public override void ServerEarlyUpdate() + { + inner.ServerEarlyUpdate(); + } + + public override void ServerLateUpdate() + { + inner.ServerLateUpdate(); + Profiler.BeginSample("EncryptionTransport.ServerLateUpdate"); + // Reverse iteration as entries can be removed while updating + for (int i = _serverPendingConnections.Count - 1; i >= 0; i--) + { + _serverPendingConnections[i].TickNonReady(NetworkTime.time); + } + Profiler.EndSample(); + } + } + +} diff --git a/Assets/Mirror/Transports/Encryption/EncryptionTransport.cs.meta b/Assets/Mirror/Transports/Encryption/EncryptionTransport.cs.meta new file mode 100644 index 0000000..98a36ed --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/EncryptionTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0aa135acc32a4383ae9a5817f018cb06 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Encryption/PubKeyInfo.cs b/Assets/Mirror/Transports/Encryption/PubKeyInfo.cs new file mode 100644 index 0000000..d989061 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/PubKeyInfo.cs @@ -0,0 +1,9 @@ +using System; +using Org.BouncyCastle.Crypto; + +public struct PubKeyInfo +{ + public string Fingerprint; + public ArraySegment Serialized; + public AsymmetricKeyParameter Key; +} diff --git a/Assets/Mirror/Transports/Encryption/PubKeyInfo.cs.meta b/Assets/Mirror/Transports/Encryption/PubKeyInfo.cs.meta new file mode 100644 index 0000000..7b824c2 --- /dev/null +++ b/Assets/Mirror/Transports/Encryption/PubKeyInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e1e3744418024c02acf39f44c1d1bd20 +timeCreated: 1708874062 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP.meta b/Assets/Mirror/Transports/KCP.meta new file mode 100644 index 0000000..1727b05 --- /dev/null +++ b/Assets/Mirror/Transports/KCP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ea4ea5d03df6a49449fa679ac2390773 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/KcpTransport.cs b/Assets/Mirror/Transports/KCP/KcpTransport.cs new file mode 100644 index 0000000..1073747 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/KcpTransport.cs @@ -0,0 +1,371 @@ +//#if MIRROR <- commented out because MIRROR isn't defined on first import yet +using System; +using System.Linq; +using System.Net; +using Mirror; +using UnityEngine; +using UnityEngine.Serialization; + +namespace kcp2k +{ + [HelpURL("https://mirror-networking.gitbook.io/docs/transports/kcp-transport")] + [DisallowMultipleComponent] + public class KcpTransport : Transport, PortTransport + { + // scheme used by this transport + public const string Scheme = "kcp"; + + // common + [Header("Transport Configuration")] + [FormerlySerializedAs("Port")] + public ushort port = 7777; + public ushort Port { get => port; set => port=value; } + [Tooltip("DualMode listens to IPv6 and IPv4 simultaneously. Disable if the platform only supports IPv4.")] + public bool DualMode = true; + [Tooltip("NoDelay is recommended to reduce latency. This also scales better without buffers getting full.")] + public bool NoDelay = true; + [Tooltip("KCP internal update interval. 100ms is KCP default, but a lower interval is recommended to minimize latency and to scale to more networked entities.")] + public uint Interval = 10; + [Tooltip("KCP timeout in milliseconds. Note that KCP sends a ping automatically.")] + public int Timeout = 10000; + [Tooltip("Socket receive buffer size. Large buffer helps support more connections. Increase operating system socket buffer size limits if needed.")] + public int RecvBufferSize = 1024 * 1027 * 7; + [Tooltip("Socket send buffer size. Large buffer helps support more connections. Increase operating system socket buffer size limits if needed.")] + public int SendBufferSize = 1024 * 1027 * 7; + + [Header("Advanced")] + [Tooltip("KCP fastresend parameter. Faster resend for the cost of higher bandwidth. 0 in normal mode, 2 in turbo mode.")] + public int FastResend = 2; + [Tooltip("KCP congestion window. Restricts window size to reduce congestion. Results in only 2-3 MTU messages per Flush even on loopback. Best to keept his disabled.")] + /*public*/ bool CongestionWindow = false; // KCP 'NoCongestionWindow' is false by default. here we negate it for ease of use. + [Tooltip("KCP window size can be modified to support higher loads. This also increases max message size.")] + public uint ReceiveWindowSize = 4096; //Kcp.WND_RCV; 128 by default. Mirror sends a lot, so we need a lot more. + [Tooltip("KCP window size can be modified to support higher loads.")] + public uint SendWindowSize = 4096; //Kcp.WND_SND; 32 by default. Mirror sends a lot, so we need a lot more. + [Tooltip("KCP will try to retransmit lost messages up to MaxRetransmit (aka dead_link) before disconnecting.")] + public uint MaxRetransmit = Kcp.DEADLINK * 2; // default prematurely disconnects a lot of people (#3022). use 2x. + [Tooltip("Enable to automatically set client & server send/recv buffers to OS limit. Avoids issues with too small buffers under heavy load, potentially dropping connections. Increase the OS limit if this is still too small.")] + [FormerlySerializedAs("MaximizeSendReceiveBuffersToOSLimit")] + public bool MaximizeSocketBuffers = true; + + [Header("Allowed Max Message Sizes\nBased on Receive Window Size")] + [Tooltip("KCP reliable max message size shown for convenience. Can be changed via ReceiveWindowSize.")] + [ReadOnly] public int ReliableMaxMessageSize = 0; // readonly, displayed from OnValidate + [Tooltip("KCP unreliable channel max message size for convenience. Not changeable.")] + [ReadOnly] public int UnreliableMaxMessageSize = 0; // readonly, displayed from OnValidate + + // config is created from the serialized properties above. + // we can expose the config directly in the future. + // for now, let's not break people's old settings. + protected KcpConfig config; + + // use default MTU for this transport. + const int MTU = Kcp.MTU_DEF; + + // server & client + protected KcpServer server; + protected KcpClient client; + + // debugging + [Header("Debug")] + public bool debugLog; + // show statistics in OnGUI + public bool statisticsGUI; + // log statistics for headless servers that can't show them in GUI + public bool statisticsLog; + + // translate Kcp <-> Mirror channels + public static int FromKcpChannel(KcpChannel channel) => + channel == KcpChannel.Reliable ? Channels.Reliable : Channels.Unreliable; + + public static KcpChannel ToKcpChannel(int channel) => + channel == Channels.Reliable ? KcpChannel.Reliable : KcpChannel.Unreliable; + + public static TransportError ToTransportError(ErrorCode error) + { + switch(error) + { + case ErrorCode.DnsResolve: return TransportError.DnsResolve; + case ErrorCode.Timeout: return TransportError.Timeout; + case ErrorCode.Congestion: return TransportError.Congestion; + case ErrorCode.InvalidReceive: return TransportError.InvalidReceive; + case ErrorCode.InvalidSend: return TransportError.InvalidSend; + case ErrorCode.ConnectionClosed: return TransportError.ConnectionClosed; + case ErrorCode.Unexpected: return TransportError.Unexpected; + default: throw new InvalidCastException($"KCP: missing error translation for {error}"); + } + } + + protected virtual void Awake() + { + // logging + // Log.Info should use Debug.Log if enabled, or nothing otherwise + // (don't want to spam the console on headless servers) + if (debugLog) + Log.Info = Debug.Log; + else + Log.Info = _ => {}; + Log.Warning = Debug.LogWarning; + Log.Error = Debug.LogError; + + // create config from serialized settings + config = new KcpConfig(DualMode, RecvBufferSize, SendBufferSize, MTU, NoDelay, Interval, FastResend, CongestionWindow, SendWindowSize, ReceiveWindowSize, Timeout, MaxRetransmit); + + // client (NonAlloc version is not necessary anymore) + client = new KcpClient( + () => OnClientConnected.Invoke(), + (message, channel) => OnClientDataReceived.Invoke(message, FromKcpChannel(channel)), + () => OnClientDisconnected?.Invoke(), // may be null in StopHost(): https://github.com/MirrorNetworking/Mirror/issues/3708 + (error, reason) => OnClientError.Invoke(ToTransportError(error), reason), + config + ); + + // server + server = new KcpServer( + (connectionId) => OnServerConnected.Invoke(connectionId), + (connectionId, message, channel) => OnServerDataReceived.Invoke(connectionId, message, FromKcpChannel(channel)), + (connectionId) => OnServerDisconnected.Invoke(connectionId), + (connectionId, error, reason) => OnServerError.Invoke(connectionId, ToTransportError(error), reason), + config + ); + + if (statisticsLog) + InvokeRepeating(nameof(OnLogStatistics), 1, 1); + + Log.Info("KcpTransport initialized!"); + } + + protected virtual void OnValidate() + { + // show max message sizes in inspector for convenience. + // 'config' isn't available in edit mode yet, so use MTU define. + ReliableMaxMessageSize = KcpPeer.ReliableMaxMessageSize(MTU, ReceiveWindowSize); + UnreliableMaxMessageSize = KcpPeer.UnreliableMaxMessageSize(MTU); + } + + // all except WebGL + // Do not change this back to using Application.platform + // because that doesn't work in the Editor! + public override bool Available() => +#if UNITY_WEBGL + false; +#else + true; +#endif + + // client + public override bool ClientConnected() => client.connected; + public override void ClientConnect(string address) + { + client.Connect(address, Port); + } + public override void ClientConnect(Uri uri) + { + if (uri.Scheme != Scheme) + throw new ArgumentException($"Invalid url {uri}, use {Scheme}://host:port instead", nameof(uri)); + + int serverPort = uri.IsDefaultPort ? Port : uri.Port; + client.Connect(uri.Host, (ushort)serverPort); + } + public override void ClientSend(ArraySegment segment, int channelId) + { + client.Send(segment, ToKcpChannel(channelId)); + + // call event. might be null if no statistics are listening etc. + OnClientDataSent?.Invoke(segment, channelId); + } + public override void ClientDisconnect() => client.Disconnect(); + // process incoming in early update + public override void ClientEarlyUpdate() + { + // only process messages while transport is enabled. + // scene change messsages disable it to stop processing. + // (see also: https://github.com/vis2k/Mirror/pull/379) + if (enabled) client.TickIncoming(); + } + // process outgoing in late update + public override void ClientLateUpdate() => client.TickOutgoing(); + + // server + public override Uri ServerUri() + { + UriBuilder builder = new UriBuilder(); + builder.Scheme = Scheme; + builder.Host = Dns.GetHostName(); + builder.Port = Port; + return builder.Uri; + } + public override bool ServerActive() => server.IsActive(); + public override void ServerStart() => server.Start(Port); + public override void ServerSend(int connectionId, ArraySegment segment, int channelId) + { + server.Send(connectionId, segment, ToKcpChannel(channelId)); + + // call event. might be null if no statistics are listening etc. + OnServerDataSent?.Invoke(connectionId, segment, channelId); + } + public override void ServerDisconnect(int connectionId) => server.Disconnect(connectionId); + public override string ServerGetClientAddress(int connectionId) + { + IPEndPoint endPoint = server.GetClientEndPoint(connectionId); + return endPoint != null + // Map to IPv4 if "IsIPv4MappedToIPv6" + // "::ffff:127.0.0.1" -> "127.0.0.1" + ? (endPoint.Address.IsIPv4MappedToIPv6 + ? endPoint.Address.MapToIPv4().ToString() + : endPoint.Address.ToString()) + : ""; + } + public override void ServerStop() => server.Stop(); + public override void ServerEarlyUpdate() + { + // only process messages while transport is enabled. + // scene change messsages disable it to stop processing. + // (see also: https://github.com/vis2k/Mirror/pull/379) + if (enabled) server.TickIncoming(); + } + // process outgoing in late update + public override void ServerLateUpdate() => server.TickOutgoing(); + + // common + public override void Shutdown() {} + + // max message size + public override int GetMaxPacketSize(int channelId = Channels.Reliable) + { + // switch to kcp channel. + // unreliable or reliable. + // default to reliable just to be sure. + switch (channelId) + { + case Channels.Unreliable: + return KcpPeer.UnreliableMaxMessageSize(config.Mtu); + default: + return KcpPeer.ReliableMaxMessageSize(config.Mtu, ReceiveWindowSize); + } + } + + // kcp reliable channel max packet size is MTU * WND_RCV + // this allows 144kb messages. but due to head of line blocking, all + // other messages would have to wait until the maxed size one is + // delivered. batching 144kb messages each time would be EXTREMELY slow + // and fill the send queue nearly immediately when using it over the + // network. + // => instead we always use MTU sized batches. + // => people can still send maxed size if needed. + public override int GetBatchThreshold(int channelId) => + KcpPeer.UnreliableMaxMessageSize(config.Mtu); + + // server statistics + // LONG to avoid int overflows with connections.Sum. + // see also: https://github.com/vis2k/Mirror/pull/2777 + public long GetAverageMaxSendRate() => + server.connections.Count > 0 + ? server.connections.Values.Sum(conn => conn.MaxSendRate) / server.connections.Count + : 0; + public long GetAverageMaxReceiveRate() => + server.connections.Count > 0 + ? server.connections.Values.Sum(conn => conn.MaxReceiveRate) / server.connections.Count + : 0; + long GetTotalSendQueue() => + server.connections.Values.Sum(conn => conn.SendQueueCount); + long GetTotalReceiveQueue() => + server.connections.Values.Sum(conn => conn.ReceiveQueueCount); + long GetTotalSendBuffer() => + server.connections.Values.Sum(conn => conn.SendBufferCount); + long GetTotalReceiveBuffer() => + server.connections.Values.Sum(conn => conn.ReceiveBufferCount); + + // PrettyBytes function from DOTSNET + // pretty prints bytes as KB/MB/GB/etc. + // long to support > 2GB + // divides by floats to return "2.5MB" etc. + public static string PrettyBytes(long bytes) + { + // bytes + if (bytes < 1024) + return $"{bytes} B"; + // kilobytes + else if (bytes < 1024L * 1024L) + return $"{(bytes / 1024f):F2} KB"; + // megabytes + else if (bytes < 1024 * 1024L * 1024L) + return $"{(bytes / (1024f * 1024f)):F2} MB"; + // gigabytes + return $"{(bytes / (1024f * 1024f * 1024f)):F2} GB"; + } + + protected virtual void OnGUIStatistics() + { + GUILayout.BeginArea(new Rect(5, 110, 300, 300)); + + if (ServerActive()) + { + GUILayout.BeginVertical("Box"); + GUILayout.Label("SERVER"); + GUILayout.Label($" connections: {server.connections.Count}"); + GUILayout.Label($" MaxSendRate (avg): {PrettyBytes(GetAverageMaxSendRate())}/s"); + GUILayout.Label($" MaxRecvRate (avg): {PrettyBytes(GetAverageMaxReceiveRate())}/s"); + GUILayout.Label($" SendQueue: {GetTotalSendQueue()}"); + GUILayout.Label($" ReceiveQueue: {GetTotalReceiveQueue()}"); + GUILayout.Label($" SendBuffer: {GetTotalSendBuffer()}"); + GUILayout.Label($" ReceiveBuffer: {GetTotalReceiveBuffer()}"); + GUILayout.EndVertical(); + } + + if (ClientConnected()) + { + GUILayout.BeginVertical("Box"); + GUILayout.Label("CLIENT"); + GUILayout.Label($" MaxSendRate: {PrettyBytes(client.MaxSendRate)}/s"); + GUILayout.Label($" MaxRecvRate: {PrettyBytes(client.MaxReceiveRate)}/s"); + GUILayout.Label($" SendQueue: {client.SendQueueCount}"); + GUILayout.Label($" ReceiveQueue: {client.ReceiveQueueCount}"); + GUILayout.Label($" SendBuffer: {client.SendBufferCount}"); + GUILayout.Label($" ReceiveBuffer: {client.ReceiveBufferCount}"); + GUILayout.EndVertical(); + } + + GUILayout.EndArea(); + } + +// OnGUI allocates even if it does nothing. avoid in release. +#if UNITY_EDITOR || DEVELOPMENT_BUILD + protected virtual void OnGUI() + { + if (statisticsGUI) OnGUIStatistics(); + } +#endif + + protected virtual void OnLogStatistics() + { + if (ServerActive()) + { + string log = "kcp SERVER @ time: " + NetworkTime.localTime + "\n"; + log += $" connections: {server.connections.Count}\n"; + log += $" MaxSendRate (avg): {PrettyBytes(GetAverageMaxSendRate())}/s\n"; + log += $" MaxRecvRate (avg): {PrettyBytes(GetAverageMaxReceiveRate())}/s\n"; + log += $" SendQueue: {GetTotalSendQueue()}\n"; + log += $" ReceiveQueue: {GetTotalReceiveQueue()}\n"; + log += $" SendBuffer: {GetTotalSendBuffer()}\n"; + log += $" ReceiveBuffer: {GetTotalReceiveBuffer()}\n\n"; + Log.Info(log); + } + + if (ClientConnected()) + { + string log = "kcp CLIENT @ time: " + NetworkTime.localTime + "\n"; + log += $" MaxSendRate: {PrettyBytes(client.MaxSendRate)}/s\n"; + log += $" MaxRecvRate: {PrettyBytes(client.MaxReceiveRate)}/s\n"; + log += $" SendQueue: {client.SendQueueCount}\n"; + log += $" ReceiveQueue: {client.ReceiveQueueCount}\n"; + log += $" SendBuffer: {client.SendBufferCount}\n"; + log += $" ReceiveBuffer: {client.ReceiveBufferCount}\n\n"; + Log.Info(log); + } + } + + public override string ToString() => $"KCP [{port}]"; + } +} +//#endif MIRROR <- commented out because MIRROR isn't defined on first import yet diff --git a/Assets/Mirror/Transports/KCP/KcpTransport.cs.meta b/Assets/Mirror/Transports/KCP/KcpTransport.cs.meta new file mode 100644 index 0000000..f7280c8 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/KcpTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b0fecffa3f624585964b0d0eb21b18e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/ThreadedKcpTransport.cs b/Assets/Mirror/Transports/KCP/ThreadedKcpTransport.cs new file mode 100644 index 0000000..4bb6596 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/ThreadedKcpTransport.cs @@ -0,0 +1,327 @@ +// Threaded version of our KCP transport. +// Elevates a few milliseconds of transport computations into a worker thread. +// +//#if MIRROR <- commented out because MIRROR isn't defined on first import yet +using System; +using System.Net; +using Mirror; +using UnityEngine; +using UnityEngine.Serialization; + +namespace kcp2k +{ + [HelpURL("https://mirror-networking.gitbook.io/docs/transports/kcp-transport")] + [DisallowMultipleComponent] + public class ThreadedKcpTransport : ThreadedTransport, PortTransport + { + // scheme used by this transport + public const string Scheme = "kcp"; + + // common + [Header("Transport Configuration")] + [FormerlySerializedAs("Port")] + public ushort port = 7777; + public ushort Port { get => port; set => port=value; } + [Tooltip("DualMode listens to IPv6 and IPv4 simultaneously. Disable if the platform only supports IPv4.")] + public bool DualMode = true; + [Tooltip("NoDelay is recommended to reduce latency. This also scales better without buffers getting full.")] + public bool NoDelay = true; + [Tooltip("KCP internal update interval. 100ms is KCP default, but a lower interval is recommended to minimize latency and to scale to more networked entities.")] + public uint Interval = 10; + [Tooltip("KCP timeout in milliseconds. Note that KCP sends a ping automatically.")] + public int Timeout = 10000; + [Tooltip("Socket receive buffer size. Large buffer helps support more connections. Increase operating system socket buffer size limits if needed.")] + public int RecvBufferSize = 1024 * 1027 * 7; + [Tooltip("Socket send buffer size. Large buffer helps support more connections. Increase operating system socket buffer size limits if needed.")] + public int SendBufferSize = 1024 * 1027 * 7; + + [Header("Advanced")] + [Tooltip("KCP fastresend parameter. Faster resend for the cost of higher bandwidth. 0 in normal mode, 2 in turbo mode.")] + public int FastResend = 2; + [Tooltip("KCP congestion window. Restricts window size to reduce congestion. Results in only 2-3 MTU messages per Flush even on loopback. Best to keept his disabled.")] + /*public*/ bool CongestionWindow = false; // KCP 'NoCongestionWindow' is false by default. here we negate it for ease of use. + [Tooltip("KCP window size can be modified to support higher loads. This also increases max message size.")] + public uint ReceiveWindowSize = 4096; //Kcp.WND_RCV; 128 by default. Mirror sends a lot, so we need a lot more. + [Tooltip("KCP window size can be modified to support higher loads.")] + public uint SendWindowSize = 4096; //Kcp.WND_SND; 32 by default. Mirror sends a lot, so we need a lot more. + [Tooltip("KCP will try to retransmit lost messages up to MaxRetransmit (aka dead_link) before disconnecting.")] + public uint MaxRetransmit = Kcp.DEADLINK * 2; // default prematurely disconnects a lot of people (#3022). use 2x. + [Tooltip("Enable to automatically set client & server send/recv buffers to OS limit. Avoids issues with too small buffers under heavy load, potentially dropping connections. Increase the OS limit if this is still too small.")] + [FormerlySerializedAs("MaximizeSendReceiveBuffersToOSLimit")] + public bool MaximizeSocketBuffers = true; + + [Header("Allowed Max Message Sizes\nBased on Receive Window Size")] + [Tooltip("KCP reliable max message size shown for convenience. Can be changed via ReceiveWindowSize.")] + [ReadOnly] public int ReliableMaxMessageSize = 0; // readonly, displayed from OnValidate + [Tooltip("KCP unreliable channel max message size for convenience. Not changeable.")] + [ReadOnly] public int UnreliableMaxMessageSize = 0; // readonly, displayed from OnValidate + + // config is created from the serialized properties above. + // we can expose the config directly in the future. + // for now, let's not break people's old settings. + protected KcpConfig config; + + // use default MTU for this transport. + const int MTU = Kcp.MTU_DEF; + + // server & client + KcpServer server; // USED IN WORKER THREAD. DON'T TOUCH FROM MAIN THREAD! + KcpClient client; // USED IN WORKER THREAD. DON'T TOUCH FROM MAIN THREAD! + + // copy MonoBehaviour.enabled for thread safe access + volatile bool enabledCopy = true; + + // debugging + [Header("Debug")] + public bool debugLog; + // show statistics in OnGUI + public bool statisticsGUI; + // log statistics for headless servers that can't show them in GUI + public bool statisticsLog; + + protected override void Awake() + { + // logging + // Log.Info should use Debug.Log if enabled, or nothing otherwise + // (don't want to spam the console on headless servers) + // THREAD SAFE thanks to ThreadLog.cs + if (debugLog) + Log.Info = Debug.Log; + else + Log.Info = _ => {}; + Log.Warning = Debug.LogWarning; + Log.Error = Debug.LogError; + + // create config from serialized settings + config = new KcpConfig(DualMode, RecvBufferSize, SendBufferSize, MTU, NoDelay, Interval, FastResend, CongestionWindow, SendWindowSize, ReceiveWindowSize, Timeout, MaxRetransmit); + + // client (NonAlloc version is not necessary anymore) + client = new KcpClient( + OnThreadedClientConnected, + (message, channel) => OnThreadedClientReceive(message, KcpTransport.FromKcpChannel(channel)), + OnThreadedClientDisconnected, + (error, reason) => OnThreadedClientError(KcpTransport.ToTransportError(error), reason), + config + ); + + // server + server = new KcpServer( + OnThreadedServerConnected, + (connectionId, message, channel) => OnThreadedServerReceive(connectionId, message, KcpTransport.FromKcpChannel(channel)), + OnThreadedServerDisconnected, + (connectionId, error, reason) => OnThreadedServerError(connectionId, KcpTransport.ToTransportError(error), reason), + config + ); + + if (statisticsLog) + InvokeRepeating(nameof(OnLogStatistics), 1, 1); + + // call base after creating kcp. + // it'll be used by the created thread immediately. + base.Awake(); + + Log.Info("ThreadedKcpTransport initialized!"); + } + + protected virtual void OnValidate() + { + // show max message sizes in inspector for convenience. + // 'config' isn't available in edit mode yet, so use MTU define. + ReliableMaxMessageSize = KcpPeer.ReliableMaxMessageSize(MTU, ReceiveWindowSize); + UnreliableMaxMessageSize = KcpPeer.UnreliableMaxMessageSize(MTU); + } + + // copy MonoBehaviour.enabled for thread safe use + void OnEnable() => enabledCopy = true; + void OnDisable() => enabledCopy = true; + + // all except WebGL + // Do not change this back to using Application.platform + // because that doesn't work in the Editor! + public override bool Available() => +#if UNITY_WEBGL + false; +#else + true; +#endif + + protected override void ThreadedClientConnect(string address) => client.Connect(address, Port); + protected override void ThreadedClientConnect(Uri uri) + { + if (uri.Scheme != Scheme) + throw new ArgumentException($"Invalid url {uri}, use {Scheme}://host:port instead", nameof(uri)); + + int serverPort = uri.IsDefaultPort ? Port : uri.Port; + client.Connect(uri.Host, (ushort)serverPort); + } + protected override void ThreadedClientSend(ArraySegment segment, int channelId) + { + client.Send(segment, KcpTransport.ToKcpChannel(channelId)); + + // thread safe version for statistics + OnThreadedClientSend(segment, channelId); + } + protected override void ThreadedClientDisconnect() => client.Disconnect(); + // process incoming in early update + protected override void ThreadedClientEarlyUpdate() + { + // only process messages while transport is enabled. + // scene change messsages disable it to stop processing. + // (see also: https://github.com/vis2k/Mirror/pull/379) + // => enabledCopy for thread safe use + if (enabledCopy) client.TickIncoming(); + } + // process outgoing in late update + protected override void ThreadedClientLateUpdate() => client.TickOutgoing(); + + // server thread overrides + public override Uri ServerUri() + { + UriBuilder builder = new UriBuilder(); + builder.Scheme = Scheme; + builder.Host = Dns.GetHostName(); + builder.Port = Port; + return builder.Uri; + } + protected override void ThreadedServerStart() => server.Start(Port); + protected override void ThreadedServerSend(int connectionId, ArraySegment segment, int channelId) + { + server.Send(connectionId, segment, KcpTransport.ToKcpChannel(channelId)); + + // thread safe version for statistics + OnThreadedServerSend(connectionId, segment, channelId); + } + protected override void ThreadedServerDisconnect(int connectionId) => server.Disconnect(connectionId); + /* NOT THREAD SAFE. ThreadedTransport version throws NotImplementedException for this. + public override string ServerGetClientAddress(int connectionId) + { + IPEndPoint endPoint = server.GetClientEndPoint(connectionId); + return endPoint != null + // Map to IPv4 if "IsIPv4MappedToIPv6" + // "::ffff:127.0.0.1" -> "127.0.0.1" + ? (endPoint.Address.IsIPv4MappedToIPv6 + ? endPoint.Address.MapToIPv4().ToString() + : endPoint.Address.ToString()) + : ""; + } + */ + protected override void ThreadedServerStop() => server.Stop(); + protected override void ThreadedServerEarlyUpdate() + { + // only process messages while transport is enabled. + // scene change messsages disable it to stop processing. + // (see also: https://github.com/vis2k/Mirror/pull/379) + // => enabledCopy for thread safe use + if (enabledCopy) server.TickIncoming(); + } + // process outgoing in late update + protected override void ThreadedServerLateUpdate() => server.TickOutgoing(); + + protected override void ThreadedShutdown() {} + + // max message size + public override int GetMaxPacketSize(int channelId = Channels.Reliable) + { + // switch to kcp channel. + // unreliable or reliable. + // default to reliable just to be sure. + switch (channelId) + { + case Channels.Unreliable: + return KcpPeer.UnreliableMaxMessageSize(config.Mtu); + default: + return KcpPeer.ReliableMaxMessageSize(config.Mtu, ReceiveWindowSize); + } + } + + // kcp reliable channel max packet size is MTU * WND_RCV + // this allows 144kb messages. but due to head of line blocking, all + // other messages would have to wait until the maxed size one is + // delivered. batching 144kb messages each time would be EXTREMELY slow + // and fill the send queue nearly immediately when using it over the + // network. + // => instead we always use MTU sized batches. + // => people can still send maxed size if needed. + public override int GetBatchThreshold(int channelId) => + KcpPeer.UnreliableMaxMessageSize(config.Mtu); + + protected virtual void OnGUIStatistics() + { + // TODO not thread safe + /* + GUILayout.BeginArea(new Rect(5, 110, 300, 300)); + + if (ServerActive()) + { + GUILayout.BeginVertical("Box"); + GUILayout.Label("SERVER"); + GUILayout.Label($" connections: {server.connections.Count}"); + GUILayout.Label($" MaxSendRate (avg): {KcpTransport.PrettyBytes(GetAverageMaxSendRate())}/s"); + GUILayout.Label($" MaxRecvRate (avg): {KcpTransport.PrettyBytes(GetAverageMaxReceiveRate())}/s"); + GUILayout.Label($" SendQueue: {GetTotalSendQueue()}"); + GUILayout.Label($" ReceiveQueue: {GetTotalReceiveQueue()}"); + GUILayout.Label($" SendBuffer: {GetTotalSendBuffer()}"); + GUILayout.Label($" ReceiveBuffer: {GetTotalReceiveBuffer()}"); + GUILayout.EndVertical(); + } + + if (ClientConnected()) + { + GUILayout.BeginVertical("Box"); + GUILayout.Label("CLIENT"); + GUILayout.Label($" MaxSendRate: {KcpTransport.PrettyBytes(client.peer.MaxSendRate)}/s"); + GUILayout.Label($" MaxRecvRate: {KcpTransport.PrettyBytes(client.peer.MaxReceiveRate)}/s"); + GUILayout.Label($" SendQueue: {client.peer.SendQueueCount}"); + GUILayout.Label($" ReceiveQueue: {client.peer.ReceiveQueueCount}"); + GUILayout.Label($" SendBuffer: {client.peer.SendBufferCount}"); + GUILayout.Label($" ReceiveBuffer: {client.peer.ReceiveBufferCount}"); + GUILayout.EndVertical(); + } + + GUILayout.EndArea(); + */ + } + +// OnGUI allocates even if it does nothing. avoid in release. +#if UNITY_EDITOR || DEVELOPMENT_BUILD + protected virtual void OnGUI() + { + if (statisticsGUI) OnGUIStatistics(); + } +#endif + + protected virtual void OnLogStatistics() + { + // TODO not thread safe + /* + if (ServerActive()) + { + string log = "kcp SERVER @ time: " + NetworkTime.localTime + "\n"; + log += $" connections: {server.connections.Count}\n"; + log += $" MaxSendRate (avg): {KcpTransport.PrettyBytes(GetAverageMaxSendRate())}/s\n"; + log += $" MaxRecvRate (avg): {KcpTransport.PrettyBytes(GetAverageMaxReceiveRate())}/s\n"; + log += $" SendQueue: {GetTotalSendQueue()}\n"; + log += $" ReceiveQueue: {GetTotalReceiveQueue()}\n"; + log += $" SendBuffer: {GetTotalSendBuffer()}\n"; + log += $" ReceiveBuffer: {GetTotalReceiveBuffer()}\n\n"; + Log.Info(log); + } + + if (ClientConnected()) + { + string log = "kcp CLIENT @ time: " + NetworkTime.localTime + "\n"; + log += $" MaxSendRate: {KcpTransport.PrettyBytes(client.peer.MaxSendRate)}/s\n"; + log += $" MaxRecvRate: {KcpTransport.PrettyBytes(client.peer.MaxReceiveRate)}/s\n"; + log += $" SendQueue: {client.peer.SendQueueCount}\n"; + log += $" ReceiveQueue: {client.peer.ReceiveQueueCount}\n"; + log += $" SendBuffer: {client.peer.SendBufferCount}\n"; + log += $" ReceiveBuffer: {client.peer.ReceiveBufferCount}\n\n"; + Log.Info(log); + } + */ + } + + public override string ToString() => $"ThreadedKCP {port}"; + } +} +//#endif MIRROR <- commented out because MIRROR isn't defined on first import yet diff --git a/Assets/Mirror/Transports/KCP/ThreadedKcpTransport.cs.meta b/Assets/Mirror/Transports/KCP/ThreadedKcpTransport.cs.meta new file mode 100644 index 0000000..660f7af --- /dev/null +++ b/Assets/Mirror/Transports/KCP/ThreadedKcpTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7e416e0486524f0d9580be7e13388f4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k.meta b/Assets/Mirror/Transports/KCP/kcp2k.meta new file mode 100644 index 0000000..1dceadf --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 71a1c8e8c022d4731a481c1808f37e5d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/KCP.asmdef b/Assets/Mirror/Transports/KCP/kcp2k/KCP.asmdef new file mode 100644 index 0000000..66d2148 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/KCP.asmdef @@ -0,0 +1,16 @@ +{ + "name": "kcp2k", + "rootNamespace": "", + "references": [ + "GUID:30817c1a0e6d646d99c048fc403f5979" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/KCP.asmdef.meta b/Assets/Mirror/Transports/KCP/kcp2k/KCP.asmdef.meta new file mode 100644 index 0000000..1d70e80 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/KCP.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6806a62c384838046a3c66c44f06d75f +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/LICENSE.txt b/Assets/Mirror/Transports/KCP/kcp2k/LICENSE.txt new file mode 100644 index 0000000..c77582e --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/LICENSE.txt @@ -0,0 +1,24 @@ +MIT License + +Copyright (c) 2016 limpo1989 +Copyright (c) 2020 Paul Pacheco +Copyright (c) 2020 Lymdun +Copyright (c) 2020 vis2k + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/LICENSE.txt.meta b/Assets/Mirror/Transports/KCP/kcp2k/LICENSE.txt.meta new file mode 100644 index 0000000..49dc767 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/LICENSE.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9a3e8369060cf4e94ac117603de47aa6 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt b/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt new file mode 100644 index 0000000..e2ae916 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt @@ -0,0 +1,256 @@ +V1.40 [2024-01-03] +- added [KCP] to all log messages +- fix: #3704 remove old fix for #2353 which caused log spam and isn't needed anymore since the + original Mirror issue is long gone +- fix: KcpClient.RawSend now returns if socket wasn't created yet +- fix: https://github.com/MirrorNetworking/Mirror/issues/3591 KcpPeer.SendDisconnect now rapid + fires several unreliable messages instead of sending reliable. Fixes disconnect message not + going through if the connection is closed & removed immediately after. + +V1.39 [2023-10-31] +- fix: https://github.com/MirrorNetworking/Mirror/issues/3611 Windows UDP socket exceptions + on server if one of the clients died + +V1.38 [2023-10-29] +- fix: #54 mismatching cookie race condition. cookie is now included in all messages. +- feature: Exposed local end point on KcpClient/Server +- refactor: KcpPeer refactored as abstract class to remove KcpServer initialization workarounds + +V1.37 [2023-07-31] +- fix: #47 KcpServer.Stop now clears connections so they aren't carried over to the next session +- fix: KcpPeer doesn't log 'received unreliable message while not authenticated' anymore. + +V1.36 [2023-06-08] +- fix: #49 KcpPeer.RawInput message size check now considers cookie as well +- kcp.cs cleanups + +V1.35 [2023-04-05] +- fix: KcpClients now need to validate with a secure cookie in order to protect against + UDP spoofing. fixes: + https://github.com/MirrorNetworking/Mirror/issues/3286 + [disclosed by IncludeSec] +- KcpClient/Server: change callbacks to protected so inheriting classes can use them too +- KcpClient/Server: change config visibility to protected + +V1.34 [2023-03-15] +- Send/SendTo/Receive/ReceiveFrom NonBlocking extensions. + to encapsulate WouldBlock allocations, exceptions, etc. + allows for reuse when overwriting KcpServer/Client (i.e. for relays). + +V1.33 [2023-03-14] +- perf: KcpServer/Client RawReceive now call socket.Poll to avoid non-blocking + socket's allocating a new SocketException in case they WouldBlock. + fixes https://github.com/MirrorNetworking/Mirror/issues/3413 +- perf: KcpServer/Client RawSend now call socket.Poll to avoid non-blocking + socket's allocating a new SocketException in case they WouldBlock. + fixes https://github.com/MirrorNetworking/Mirror/issues/3413 + +V1.32 [2023-03-12] +- fix: KcpPeer RawInput now doesn't disconnect in case of random internet noise + +V1.31 [2023-03-05] +- KcpClient: Tick/Incoming/Outgoing can now be overwritten (virtual) +- breaking: KcpClient now takes KcpConfig in constructor instead of in Connect. + cleaner, and prepares for KcpConfig.MTU setting. +- KcpConfig now includes MTU; KcpPeer now works with KcpConfig's MTU, KcpServer/Client + buffers are now created with config's MTU. + +V1.30 [2023-02-20] +- fix: set send/recv buffer sizes directly instead of iterating to find the limit. + fixes: https://github.com/MirrorNetworking/Mirror/issues/3390 +- fix: server & client sockets are now always non-blocking to ensure main thread never + blocks on socket.recv/send. Send() now also handles WouldBlock. +- fix: socket.Receive/From directly with non-blocking sockets and handle WouldBlock, + instead of socket.Poll. faster, more obvious, and fixes Poll() looping forever while + socket is in error state. fixes: https://github.com/MirrorNetworking/Mirror/issues/2733 + +V1.29 [2023-01-28] +- fix: KcpServer.CreateServerSocket now handles NotSupportedException when setting DualMode + https://github.com/MirrorNetworking/Mirror/issues/3358 + +V1.28 [2023-01-28] +- fix: KcpClient.Connect now resolves hostname before creating peer + https://github.com/MirrorNetworking/Mirror/issues/3361 + +V1.27 [2023-01-08] +- KcpClient.Connect: invoke own events directly instead of going through peer, + which calls our own events anyway +- fix: KcpPeer/Client/Server callbacks are readonly and assigned in constructor + to ensure they are safe to use at all times. + fixes https://github.com/MirrorNetworking/Mirror/issues/3337 + +V1.26 [2022-12-22] +- KcpPeer.RawInput: fix compile error in old Unity Mono versions +- fix: KcpServer sets up a new connection's OnError immediately. + fixes KcpPeer throwing NullReferenceException when attempting to call OnError + after authentication errors. +- improved log messages + +V1.25 [2022-12-14] +- breaking: removed where-allocation. use IL2CPP on servers instead. +- breaking: KcpConfig to simplify configuration +- high level cleanups + +V1.24 [2022-12-14] +- KcpClient: fixed NullReferenceException when connection without a server. + added test coverage to ensure this never happens again. + +V1.23 [2022-12-07] +- KcpClient: rawReceiveBuffer exposed +- fix: KcpServer RawSend uses connection.remoteEndPoint instead of the helper + 'newClientEP'. fixes clients receiving the wrong messages meant for others. + https://github.com/MirrorNetworking/Mirror/issues/3296 + +V1.22 [2022-11-30] +- high level refactor, part two. + +V1.21 [2022-11-24] +- high level refactor, part one. + - KcpPeer instead of KcpConnection, KcpClientConnection, KcpServerConnection + - RawSend/Receive can now easily be overwritten in KcpClient/Server. + for non-alloc, relays, etc. + +V1.20 [2022-11-22] +- perf: KcpClient receive allocation was removed entirely. + reduces Mirror benchmark client sided allocations from 4.9 KB / 1.7 KB (non-alloc) to 0B. +- fix: KcpConnection.Disconnect does not check socket.Connected anymore. + UDP sockets don't have a connection. + fixes Disconnects not being sent to clients in netcore. +- KcpConnection.SendReliable: added OnError instead of logs + +V1.19 [2022-05-12] +- feature: OnError ErrorCodes + +V1.18 [2022-05-08] +- feature: OnError to allow higher level to show popups etc. +- feature: KcpServer.GetClientAddress is now GetClientEndPoint in order to + expose more details +- ResolveHostname: include exception in log for easier debugging +- fix: KcpClientConnection.RawReceive now logs the SocketException even if + it was expected. makes debugging easier. +- fix: KcpServer.TickIncoming now logs the SocketException even if it was + expected. makes debugging easier. +- fix: KcpClientConnection.RawReceive now calls Disconnect() if the other end + has closed the connection. better than just remaining in a state with unusable + sockets. + +V1.17 [2022-01-09] +- perf: server/client MaximizeSendReceiveBuffersToOSLimit option to set send/recv + buffer sizes to OS limit. avoids drops due to small buffers under heavy load. + +V1.16 [2022-01-06] +- fix: SendUnreliable respects ArraySegment.Offset +- fix: potential bug with negative length (see PR #2) +- breaking: removed pause handling because it's not necessary for Mirror anymore + +V1.15 [2021-12-11] +- feature: feature: MaxRetransmits aka dead_link now configurable +- dead_link disconnect message improved to show exact retransmit count + +V1.14 [2021-11-30] +- fix: Send() now throws an exception for messages which require > 255 fragments +- fix: ReliableMaxMessageSize is now limited to messages which require <= 255 fragments + +V1.13 [2021-11-28] +- fix: perf: uncork max message size from 144 KB to as much as we want based on + receive window size. + fixes https://github.com/vis2k/kcp2k/issues/22 + fixes https://github.com/skywind3000/kcp/pull/291 +- feature: OnData now includes channel it was received on + +V1.12 [2021-07-16] +- Tests: don't depend on Unity anymore +- fix: #26 - Kcp now catches exception if host couldn't be resolved, and calls + OnDisconnected to let the user now. +- fix: KcpServer.DualMode is now configurable in the constructor instead of + using #if UNITY_SWITCH. makes it run on all other non dual mode platforms too. +- fix: where-allocation made optional via virtuals and inheriting + KcpServer/Client/Connection NonAlloc classes. fixes a bug where some platforms + might not support where-allocation. + +V1.11 rollback [2021-06-01] +- perf: Segment MemoryStream initial capacity set to MTU to avoid early runtime + resizing/allocations + +V1.10 [2021-05-28] +- feature: configurable Timeout +- allocations explained with comments (C# ReceiveFrom / IPEndPoint.GetHashCode) +- fix: #17 KcpConnection.ReceiveNextReliable now assigns message default so it + works in .net too +- fix: Segment pool is not static anymore. Each kcp instance now has it's own + Pool. fixes #18 concurrency issues + +V1.9 [2021-03-02] +- Tick() split into TickIncoming()/TickOutgoing() to use in Mirror's new update + functions. allows to minimize latency. + => original Tick() is still supported for convenience. simply processes both! + +V1.8 [2021-02-14] +- fix: Unity IPv6 errors on Nintendo Switch +- fix: KcpConnection now disconnects if data message was received without content. + previously it would call OnData with an empty ArraySegment, causing all kinds of + weird behaviour in Mirror/DOTSNET. Added tests too. +- fix: KcpConnection.SendData: don't allow sending empty messages anymore. disconnect + and log a warning to make it completely obvious. + +V1.7 [2021-01-13] +- fix: unreliable messages reset timeout now too +- perf: KcpConnection OnCheckEnabled callback changed to a simple 'paused' boolean. + This is faster than invoking a Func every time and allows us to fix #8 more + easily later by calling .Pause/.Unpause from OnEnable/OnDisable in MirrorTransport. +- fix #8: Unpause now resets timeout to fix a bug where Mirror would pause kcp, + change the scene which took >10s, then unpause and kcp would detect the lack of + any messages for >10s as timeout. Added test to make sure it never happens again. +- MirrorTransport: statistics logging for headless servers +- Mirror Transport: Send/Receive window size increased once more from 2048 to 4096. + +V1.6 [2021-01-10] +- Unreliable channel added! +- perf: KcpHeader byte added to every kcp message to indicate + Handshake/Data/Ping/Disconnect instead of scanning each message for Hello/Byte/Ping + content via SegmentEquals. It's a lot cleaner, should be faster and should avoid + edge cases where a message content would equal Hello/Ping/Bye sequence accidentally. +- Kcp.Input: offset moved to parameters for cases where it's needed +- Kcp.SetMtu from original Kcp.c + +V1.5 [2021-01-07] +- KcpConnection.MaxSend/ReceiveRate calculation based on the article +- MirrorTransport: large send/recv window size defaults to avoid high latencies caused + by packets not being processed fast enough +- MirrorTransport: show MaxSend/ReceiveRate in debug gui +- MirrorTransport: don't Log.Info to console in headless mode if debug log is disabled + +V1.4 [2020-11-27] +- fix: OnCheckEnabled added. KcpConnection message processing while loop can now + be interrupted immediately. fixes Mirror Transport scene changes which need to stop + processing any messages immediately after a scene message) +- perf: Mirror KcpTransport: FastResend enabled by default. turbo mode according to: + https://github.com/skywind3000/kcp/blob/master/README.en.md#protocol-configuration +- perf: Mirror KcpTransport: CongestionControl disabled by default (turbo mode) + +V1.3 [2020-11-17] +- Log.Info/Warning/Error so logging doesn't depend on UnityEngine anymore +- fix: Server.Tick catches SocketException which happens if Android client is killed +- MirrorTransport: debugLog option added that can be checked in Unity Inspector +- Utils.Clamp so Kcp.cs doesn't depend on UnityEngine +- Utils.SegmentsEqual: use Linq SequenceEqual so it doesn't depend on UnityEngine +=> kcp2k can now be used in any C# project even without Unity + +V1.2 [2020-11-10] +- more tests added +- fix: raw receive buffers are now all of MTU size +- fix: raw receive detects error where buffer was too small for msgLength and + result in excess data being dropped silently +- KcpConnection.MaxMessageSize added for use in high level +- KcpConnection.MaxMessageSize increased from 1200 bytes to to maximum allowed + message size of 145KB for kcp (based on mtu, overhead, wnd_rcv) + +V1.1 [2020-10-30] +- high level cleanup, fixes, improvements + +V1.0 [2020-10-22] +- Kcp.cs now mirrors original Kcp.c behaviour + (this fixes dozens of bugs) + +V0.1 +- initial kcp-csharp based version \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt.meta b/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt.meta new file mode 100644 index 0000000..2a07daa --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ed3f2cf1bbf1b4d53a6f2c103d311f71 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/empty.meta b/Assets/Mirror/Transports/KCP/kcp2k/empty.meta new file mode 100644 index 0000000..ae61673 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/empty.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d9ce2267cb8a4a1c9632025287e8da88 +timeCreated: 1669162433 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/empty/KcpServerNonAlloc.cs b/Assets/Mirror/Transports/KCP/kcp2k/empty/KcpServerNonAlloc.cs new file mode 100644 index 0000000..4623b53 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/empty/KcpServerNonAlloc.cs @@ -0,0 +1 @@ +// removed 2022-12-13 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/empty/KcpServerNonAlloc.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/empty/KcpServerNonAlloc.cs.meta new file mode 100644 index 0000000..a878cc1 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/empty/KcpServerNonAlloc.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 54b8398dcd544c8a93bcad846214cc40 +timeCreated: 1626432191 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel.meta new file mode 100644 index 0000000..1c11c3d --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5a54d18b954cb4407a28b633fc32ea6d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Common.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Common.cs new file mode 100644 index 0000000..e96246a --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Common.cs @@ -0,0 +1,75 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Security.Cryptography; + +namespace kcp2k +{ + public static class Common + { + // helper function to resolve host to IPAddress + public static bool ResolveHostname(string hostname, out IPAddress[] addresses) + { + try + { + // NOTE: dns lookup is blocking. this can take a second. + addresses = Dns.GetHostAddresses(hostname); + return addresses.Length >= 1; + } + catch (SocketException exception) + { + Log.Info($"[KCP] Failed to resolve host: {hostname} reason: {exception}"); + addresses = null; + return false; + } + } + + // if connections drop under heavy load, increase to OS limit. + // if still not enough, increase the OS limit. + public static void ConfigureSocketBuffers(Socket socket, int recvBufferSize, int sendBufferSize) + { + // log initial size for comparison. + // remember initial size for log comparison + int initialReceive = socket.ReceiveBufferSize; + int initialSend = socket.SendBufferSize; + + // set to configured size + try + { + socket.ReceiveBufferSize = recvBufferSize; + socket.SendBufferSize = sendBufferSize; + } + catch (SocketException) + { + Log.Warning($"[KCP] failed to set Socket RecvBufSize = {recvBufferSize} SendBufSize = {sendBufferSize}"); + } + + + Log.Info($"[KCP] RecvBuf = {initialReceive}=>{socket.ReceiveBufferSize} ({socket.ReceiveBufferSize/initialReceive}x) SendBuf = {initialSend}=>{socket.SendBufferSize} ({socket.SendBufferSize/initialSend}x)"); + } + + // generate a connection hash from IP+Port. + // + // NOTE: IPEndPoint.GetHashCode() allocates. + // it calls m_Address.GetHashCode(). + // m_Address is an IPAddress. + // GetHashCode() allocates for IPv6: + // https://github.com/mono/mono/blob/bdd772531d379b4e78593587d15113c37edd4a64/mcs/class/referencesource/System/net/System/Net/IPAddress.cs#L699 + // + // => using only newClientEP.Port wouldn't work, because + // different connections can have the same port. + public static int ConnectionHash(EndPoint endPoint) => + endPoint.GetHashCode(); + + // cookies need to be generated with a secure random generator. + // we don't want them to be deterministic / predictable. + // RNG is cached to avoid runtime allocations. + static readonly RNGCryptoServiceProvider cryptoRandom = new RNGCryptoServiceProvider(); + static readonly byte[] cryptoRandomBuffer = new byte[4]; + public static uint GenerateCookie() + { + cryptoRandom.GetBytes(cryptoRandomBuffer); + return BitConverter.ToUInt32(cryptoRandomBuffer, 0); + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Common.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Common.cs.meta new file mode 100644 index 0000000..e349d86 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Common.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9ced451c2954435f88cf718bcba020cb +timeCreated: 1669135138 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/ErrorCode.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/ErrorCode.cs new file mode 100644 index 0000000..15b872f --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/ErrorCode.cs @@ -0,0 +1,15 @@ +// kcp specific error codes to allow for error switching, localization, +// translation to Mirror errors, etc. +namespace kcp2k +{ + public enum ErrorCode : byte + { + DnsResolve, // failed to resolve a host name + Timeout, // ping timeout or dead link + Congestion, // more messages than transport / network can process + InvalidReceive, // recv invalid packet (possibly intentional attack) + InvalidSend, // user tried to send invalid data + ConnectionClosed, // connection closed voluntarily or lost involuntarily + Unexpected // unexpected error / exception, requires fix. + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/ErrorCode.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/ErrorCode.cs.meta new file mode 100644 index 0000000..42f163f --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/ErrorCode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3abbeffc1d794f11a45b7fcf110353f5 +timeCreated: 1652320712 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Extensions.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Extensions.cs new file mode 100644 index 0000000..20725a9 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Extensions.cs @@ -0,0 +1,166 @@ +using System; +using System.Net; +using System.Net.Sockets; + +namespace kcp2k +{ + public static class Extensions + { + // ArraySegment as HexString for convenience + public static string ToHexString(this ArraySegment segment) => + BitConverter.ToString(segment.Array, segment.Offset, segment.Count); + + // non-blocking UDP send. + // allows for reuse when overwriting KcpServer/Client (i.e. for relays). + // => wrapped with Poll to avoid WouldBlock allocating new SocketException. + // => wrapped with try-catch to ignore WouldBlock exception. + // make sure to set socket.Blocking = false before using this! + public static bool SendToNonBlocking(this Socket socket, ArraySegment data, EndPoint remoteEP) + { + try + { + // when using non-blocking sockets, SendTo may return WouldBlock. + // in C#, WouldBlock throws a SocketException, which is expected. + // unfortunately, creating the SocketException allocates in C#. + // let's poll first to avoid the WouldBlock allocation. + // note that this entirely to avoid allocations. + // non-blocking UDP doesn't need Poll in other languages. + // and the code still works without the Poll call. + if (!socket.Poll(0, SelectMode.SelectWrite)) return false; + + // send to the the endpoint. + // do not send to 'newClientEP', as that's always reused. + // fixes https://github.com/MirrorNetworking/Mirror/issues/3296 + socket.SendTo(data.Array, data.Offset, data.Count, SocketFlags.None, remoteEP); + return true; + } + catch (SocketException e) + { + // for non-blocking sockets, SendTo may throw WouldBlock. + // in that case, simply drop the message. it's UDP, it's fine. + if (e.SocketErrorCode == SocketError.WouldBlock) return false; + + // otherwise it's a real socket error. throw it. + throw; + } + } + + // non-blocking UDP send. + // allows for reuse when overwriting KcpServer/Client (i.e. for relays). + // => wrapped with Poll to avoid WouldBlock allocating new SocketException. + // => wrapped with try-catch to ignore WouldBlock exception. + // make sure to set socket.Blocking = false before using this! + public static bool SendNonBlocking(this Socket socket, ArraySegment data) + { + try + { + // when using non-blocking sockets, SendTo may return WouldBlock. + // in C#, WouldBlock throws a SocketException, which is expected. + // unfortunately, creating the SocketException allocates in C#. + // let's poll first to avoid the WouldBlock allocation. + // note that this entirely to avoid allocations. + // non-blocking UDP doesn't need Poll in other languages. + // and the code still works without the Poll call. + if (!socket.Poll(0, SelectMode.SelectWrite)) return false; + + // SendTo allocates. we used bound Send. + socket.Send(data.Array, data.Offset, data.Count, SocketFlags.None); + return true; + } + catch (SocketException e) + { + // for non-blocking sockets, SendTo may throw WouldBlock. + // in that case, simply drop the message. it's UDP, it's fine. + if (e.SocketErrorCode == SocketError.WouldBlock) return false; + + // otherwise it's a real socket error. throw it. + throw; + } + } + + // non-blocking UDP receive. + // allows for reuse when overwriting KcpServer/Client (i.e. for relays). + // => wrapped with Poll to avoid WouldBlock allocating new SocketException. + // => wrapped with try-catch to ignore WouldBlock exception. + // make sure to set socket.Blocking = false before using this! + public static bool ReceiveFromNonBlocking(this Socket socket, byte[] recvBuffer, out ArraySegment data, ref EndPoint remoteEP) + { + data = default; + + try + { + // when using non-blocking sockets, ReceiveFrom may return WouldBlock. + // in C#, WouldBlock throws a SocketException, which is expected. + // unfortunately, creating the SocketException allocates in C#. + // let's poll first to avoid the WouldBlock allocation. + // note that this entirely to avoid allocations. + // non-blocking UDP doesn't need Poll in other languages. + // and the code still works without the Poll call. + if (!socket.Poll(0, SelectMode.SelectRead)) return false; + + // NOTE: ReceiveFrom allocates. + // we pass our IPEndPoint to ReceiveFrom. + // receive from calls newClientEP.Create(socketAddr). + // IPEndPoint.Create always returns a new IPEndPoint. + // https://github.com/mono/mono/blob/f74eed4b09790a0929889ad7fc2cf96c9b6e3757/mcs/class/System/System.Net.Sockets/Socket.cs#L1761 + // + // throws SocketException if datagram was larger than buffer. + // https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.receive?view=net-6.0 + int size = socket.ReceiveFrom(recvBuffer, 0, recvBuffer.Length, SocketFlags.None, ref remoteEP); + data = new ArraySegment(recvBuffer, 0, size); + return true; + } + catch (SocketException e) + { + // for non-blocking sockets, Receive throws WouldBlock if there is + // no message to read. that's okay. only log for other errors. + if (e.SocketErrorCode == SocketError.WouldBlock) return false; + + // otherwise it's a real socket error. throw it. + throw; + } + } + + // non-blocking UDP receive. + // allows for reuse when overwriting KcpServer/Client (i.e. for relays). + // => wrapped with Poll to avoid WouldBlock allocating new SocketException. + // => wrapped with try-catch to ignore WouldBlock exception. + // make sure to set socket.Blocking = false before using this! + public static bool ReceiveNonBlocking(this Socket socket, byte[] recvBuffer, out ArraySegment data) + { + data = default; + + try + { + // when using non-blocking sockets, ReceiveFrom may return WouldBlock. + // in C#, WouldBlock throws a SocketException, which is expected. + // unfortunately, creating the SocketException allocates in C#. + // let's poll first to avoid the WouldBlock allocation. + // note that this entirely to avoid allocations. + // non-blocking UDP doesn't need Poll in other languages. + // and the code still works without the Poll call. + if (!socket.Poll(0, SelectMode.SelectRead)) return false; + + // ReceiveFrom allocates. we used bound Receive. + // returns amount of bytes written into buffer. + // throws SocketException if datagram was larger than buffer. + // https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.receive?view=net-6.0 + // + // throws SocketException if datagram was larger than buffer. + // https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.receive?view=net-6.0 + int size = socket.Receive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None); + data = new ArraySegment(recvBuffer, 0, size); + return true; + } + catch (SocketException e) + { + // for non-blocking sockets, Receive throws WouldBlock if there is + // no message to read. that's okay. only log for other errors. + if (e.SocketErrorCode == SocketError.WouldBlock) return false; + + // otherwise it's a real socket error. throw it. + throw; + } + } + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Extensions.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Extensions.cs.meta new file mode 100644 index 0000000..36d3193 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Extensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c0649195e5ba4fcf8e0e1231fee7d5f6 +timeCreated: 1641701011 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpChannel.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpChannel.cs new file mode 100644 index 0000000..c085e17 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpChannel.cs @@ -0,0 +1,10 @@ +namespace kcp2k +{ + // channel type and header for raw messages + public enum KcpChannel : byte + { + // don't react on 0x00. might help to filter out random noise. + Reliable = 1, + Unreliable = 2 + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpChannel.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpChannel.cs.meta new file mode 100644 index 0000000..2721025 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpChannel.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9e852b2532fb248d19715cfebe371db3 +timeCreated: 1610081248 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs new file mode 100644 index 0000000..38bfc14 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs @@ -0,0 +1,291 @@ +// kcp client logic abstracted into a class. +// for use in Mirror, DOTSNET, testing, etc. +using System; +using System.Net; +using System.Net.Sockets; + +namespace kcp2k +{ + public class KcpClient : KcpPeer + { + // IO + protected Socket socket; + public EndPoint remoteEndPoint; + + // expose local endpoint for users / relays / nat traversal etc. + public EndPoint LocalEndPoint => socket?.LocalEndPoint; + + // config + protected readonly KcpConfig config; + + // raw receive buffer always needs to be of 'MTU' size, even if + // MaxMessageSize is larger. kcp always sends in MTU segments and having + // a buffer smaller than MTU would silently drop excess data. + // => we need the MTU to fit channel + message! + // => protected because someone may overwrite RawReceive but still wants + // to reuse the buffer. + protected readonly byte[] rawReceiveBuffer; + + // callbacks + // even for errors, to allow liraries to show popups etc. + // instead of logging directly. + // (string instead of Exception for ease of use and to avoid user panic) + // + // events are readonly, set in constructor. + // this ensures they are always initialized when used. + // fixes https://github.com/MirrorNetworking/Mirror/issues/3337 and more + protected readonly Action OnConnectedCallback; + protected readonly Action, KcpChannel> OnDataCallback; + protected readonly Action OnDisconnectedCallback; + protected readonly Action OnErrorCallback; + + // state + bool active = false; // active between when connect() and disconnect() are called + public bool connected; + + public KcpClient(Action OnConnected, + Action, KcpChannel> OnData, + Action OnDisconnected, + Action OnError, + KcpConfig config) + : base(config, 0) // client has no cookie yet + { + // initialize callbacks first to ensure they can be used safely. + OnConnectedCallback = OnConnected; + OnDataCallback = OnData; + OnDisconnectedCallback = OnDisconnected; + OnErrorCallback = OnError; + this.config = config; + + // create mtu sized receive buffer + rawReceiveBuffer = new byte[config.Mtu]; + } + + // callbacks /////////////////////////////////////////////////////////// + // some callbacks need to wrapped with some extra logic + protected override void OnAuthenticated() + { + Log.Info($"[KCP] Client: OnConnected"); + connected = true; + OnConnectedCallback(); + } + + protected override void OnData(ArraySegment message, KcpChannel channel) => + OnDataCallback(message, channel); + + protected override void OnError(ErrorCode error, string message) => + OnErrorCallback(error, message); + + protected override void OnDisconnected() + { + Log.Info($"[KCP] Client: OnDisconnected"); + connected = false; + socket?.Close(); + socket = null; + remoteEndPoint = null; + OnDisconnectedCallback(); + active = false; + } + + //////////////////////////////////////////////////////////////////////// + public void Connect(string address, ushort port) + { + if (connected) + { + Log.Warning("[KCP] Client: already connected!"); + return; + } + + // resolve host name before creating peer. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3361 + if (!Common.ResolveHostname(address, out IPAddress[] addresses)) + { + // pass error to user callback. no need to log it manually. + OnError(ErrorCode.DnsResolve, $"Failed to resolve host: {address}"); + OnDisconnectedCallback(); + return; + } + + // create fresh peer for each new session + // client doesn't need secure cookie. + Reset(config); + + Log.Info($"[KCP] Client: connect to {address}:{port}"); + + // create socket + remoteEndPoint = new IPEndPoint(addresses[0], port); + socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); + active = true; + + // recv & send are called from main thread. + // need to ensure this never blocks. + // even a 1ms block per connection would stop us from scaling. + socket.Blocking = false; + + // configure buffer sizes + Common.ConfigureSocketBuffers(socket, config.RecvBufferSize, config.SendBufferSize); + + // bind to endpoint so we can use send/recv instead of sendto/recvfrom. + socket.Connect(remoteEndPoint); + + // immediately send a hello message to the server. + // server will call OnMessage and add the new connection. + // note that this still has cookie=0 until we receive the server's hello. + SendHello(); + } + + // io - input. + // virtual so it may be modified for relays, etc. + // call this while it returns true, to process all messages this tick. + // returned ArraySegment is valid until next call to RawReceive. + protected virtual bool RawReceive(out ArraySegment segment) + { + segment = default; + if (socket == null) return false; + + try + { + return socket.ReceiveNonBlocking(rawReceiveBuffer, out segment); + } + // for non-blocking sockets, Receive throws WouldBlock if there is + // no message to read. that's okay. only log for other errors. + catch (SocketException e) + { + // the other end closing the connection is not an 'error'. + // but connections should never just end silently. + // at least log a message for easier debugging. + // for example, his can happen when connecting without a server. + // see test: ConnectWithoutServer(). + Log.Info($"[KCP] Client.RawReceive: looks like the other end has closed the connection. This is fine: {e}"); + base.Disconnect(); + return false; + } + } + + // io - output. + // virtual so it may be modified for relays, etc. + protected override void RawSend(ArraySegment data) + { + // only if socket was connected / created yet. + // users may call send functions without having connected, causing NRE. + if (socket == null) return; + + try + { + socket.SendNonBlocking(data); + } + catch (SocketException e) + { + // SendDisconnect() sometimes gets a SocketException with + // 'Connection Refused' if the other end already closed. + // this is not an 'error', it's expected to happen. + // but connections should never just end silently. + // at least log a message for easier debugging. + Log.Info($"[KCP] Client.RawSend: looks like the other end has closed the connection. This is fine: {e}"); + // base.Disconnect(); <- don't call this, would deadlock if SendDisconnect() already throws + } + } + + public void Send(ArraySegment segment, KcpChannel channel) + { + if (!connected) + { + Log.Warning("[KCP] Client: can't send because not connected!"); + return; + } + + SendData(segment, channel); + } + + // insert raw IO. usually from socket.Receive. + // offset is useful for relays, where we may parse a header and then + // feed the rest to kcp. + public void RawInput(ArraySegment segment) + { + // ensure valid size: at least 1 byte for channel + 4 bytes for cookie + if (segment.Count <= 5) return; + + // parse channel + // byte channel = segment[0]; ArraySegment[i] isn't supported in some older Unity Mono versions + byte channel = segment.Array[segment.Offset + 0]; + + // server messages always contain the security cookie. + // parse it, assign if not assigned, warn if suddenly different. + Utils.Decode32U(segment.Array, segment.Offset + 1, out uint messageCookie); + if (messageCookie == 0) + { + Log.Error($"[KCP] Client: received message with cookie=0, this should never happen. Server should always include the security cookie."); + } + + if (cookie == 0) + { + cookie = messageCookie; + Log.Info($"[KCP] Client: received initial cookie: {cookie}"); + } + else if (cookie != messageCookie) + { + Log.Warning($"[KCP] Client: dropping message with mismatching cookie: {messageCookie} expected: {cookie}."); + return; + } + + // parse message + ArraySegment message = new ArraySegment(segment.Array, segment.Offset + 1+4, segment.Count - 1-4); + + switch (channel) + { + case (byte)KcpChannel.Reliable: + { + OnRawInputReliable(message); + break; + } + case (byte)KcpChannel.Unreliable: + { + OnRawInputUnreliable(message); + break; + } + default: + { + // invalid channel indicates random internet noise. + // servers may receive random UDP data. + // just ignore it, but log for easier debugging. + Log.Warning($"[KCP] Client: invalid channel header: {channel}, likely internet noise"); + break; + } + } + } + + // process incoming messages. should be called before updating the world. + // virtual because relay may need to inject their own ping or similar. + public override void TickIncoming() + { + // recv on socket first, then process incoming + // (even if we didn't receive anything. need to tick ping etc.) + // (connection is null if not active) + if (active) + { + while (RawReceive(out ArraySegment segment)) + RawInput(segment); + } + + // RawReceive may have disconnected peer. active check again. + if (active) base.TickIncoming(); + } + + // process outgoing messages. should be called after updating the world. + // virtual because relay may need to inject their own ping or similar. + public override void TickOutgoing() + { + // process outgoing while active + if (active) base.TickOutgoing(); + } + + // process incoming and outgoing for convenience + // => ideally call ProcessIncoming() before updating the world and + // ProcessOutgoing() after updating the world for minimum latency + public virtual void Tick() + { + TickIncoming(); + TickOutgoing(); + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs.meta new file mode 100644 index 0000000..e55306b --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6aa069a28ed24fedb533c102d9742b36 +timeCreated: 1603786960 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpConfig.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpConfig.cs new file mode 100644 index 0000000..382d06b --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpConfig.cs @@ -0,0 +1,97 @@ +// common config struct, instead of passing 10 parameters manually every time. +using System; + +namespace kcp2k +{ + // [Serializable] to show it in Unity inspector. + // 'class' so we can set defaults easily. + [Serializable] + public class KcpConfig + { + // socket configuration //////////////////////////////////////////////// + // DualMode uses both IPv6 and IPv4. not all platforms support it. + // (Nintendo Switch, etc.) + public bool DualMode; + + // UDP servers use only one socket. + // maximize buffer to handle as many connections as possible. + // + // M1 mac pro: + // recv buffer default: 786896 (771 KB) + // send buffer default: 9216 (9 KB) + // max configurable: ~7 MB + public int RecvBufferSize; + public int SendBufferSize; + + // kcp configuration /////////////////////////////////////////////////// + // configurable MTU in case kcp sits on top of other abstractions like + // encrypted transports, relays, etc. + public int Mtu; + + // NoDelay is recommended to reduce latency. This also scales better + // without buffers getting full. + public bool NoDelay; + + // KCP internal update interval. 100ms is KCP default, but a lower + // interval is recommended to minimize latency and to scale to more + // networked entities. + public uint Interval; + + // KCP fastresend parameter. Faster resend for the cost of higher + // bandwidth. + public int FastResend; + + // KCP congestion window heavily limits messages flushed per update. + // congestion window may actually be broken in kcp: + // - sending max sized message @ M1 mac flushes 2-3 messages per update + // - even with super large send/recv window, it requires thousands of + // update calls + // best to leave this disabled, as it may significantly increase latency. + public bool CongestionWindow; + + // KCP window size can be modified to support higher loads. + // for example, Mirror Benchmark requires: + // 128, 128 for 4k monsters + // 512, 512 for 10k monsters + // 8192, 8192 for 20k monsters + public uint SendWindowSize; + public uint ReceiveWindowSize; + + // timeout in milliseconds + public int Timeout; + + // maximum retransmission attempts until dead_link + public uint MaxRetransmits; + + // constructor ///////////////////////////////////////////////////////// + // constructor with defaults for convenience. + // makes it easy to define "new KcpConfig(DualMode=false)" etc. + public KcpConfig( + bool DualMode = true, + int RecvBufferSize = 1024 * 1024 * 7, + int SendBufferSize = 1024 * 1024 * 7, + int Mtu = Kcp.MTU_DEF, + bool NoDelay = true, + uint Interval = 10, + int FastResend = 0, + bool CongestionWindow = false, + uint SendWindowSize = Kcp.WND_SND, + uint ReceiveWindowSize = Kcp.WND_RCV, + int Timeout = KcpPeer.DEFAULT_TIMEOUT, + uint MaxRetransmits = Kcp.DEADLINK) + { + this.DualMode = DualMode; + this.RecvBufferSize = RecvBufferSize; + this.SendBufferSize = SendBufferSize; + this.Mtu = Mtu; + this.NoDelay = NoDelay; + this.Interval = Interval; + this.FastResend = FastResend; + this.CongestionWindow = CongestionWindow; + this.SendWindowSize = SendWindowSize; + this.ReceiveWindowSize = ReceiveWindowSize; + this.Timeout = Timeout; + this.MaxRetransmits = MaxRetransmits; + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpConfig.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpConfig.cs.meta new file mode 100644 index 0000000..a687e23 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpConfig.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 99692f99c45c4b47b0500e7abbfd12da +timeCreated: 1670946969 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpHeader.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpHeader.cs new file mode 100644 index 0000000..0990cbd --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpHeader.cs @@ -0,0 +1,26 @@ +namespace kcp2k +{ + // header for messages processed by kcp. + // this is NOT for the raw receive messages(!) because handshake/disconnect + // need to be sent reliably. it's not enough to have those in rawreceive + // because those messages might get lost without being resent! + public enum KcpHeaderReliable : byte + { + // don't react on 0x00. might help to filter out random noise. + Hello = 1, + // ping goes over reliable & KcpHeader for now. could go over unreliable + // too. there is no real difference except that this is easier because + // we already have a KcpHeader for reliable messages. + // ping is only used to keep it alive, so latency doesn't matter. + Ping = 2, + Data = 3, + } + + public enum KcpHeaderUnreliable : byte + { + // users may send unreliable messages + Data = 4, + // disconnect always goes through rapid fire unreliable (glenn fielder) + Disconnect = 5, + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpHeader.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpHeader.cs.meta new file mode 100644 index 0000000..9e81c94 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpHeader.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 91b5edac31224a49bd76f960ae018942 +timeCreated: 1610081248 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpPeer.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpPeer.cs new file mode 100644 index 0000000..6df1619 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpPeer.cs @@ -0,0 +1,775 @@ +// Kcp Peer, similar to UDP Peer but wrapped with reliability, channels, +// timeouts, authentication, state, etc. +// +// still IO agnostic to work with udp, nonalloc, relays, native, etc. +using System; +using System.Diagnostics; +using System.Net.Sockets; + +namespace kcp2k +{ + public abstract class KcpPeer + { + // kcp reliability algorithm + internal Kcp kcp; + + // security cookie to prevent UDP spoofing. + // credits to IncludeSec for disclosing the issue. + // + // server passes the expected cookie to the client's KcpPeer. + // KcpPeer sends cookie to the connected client. + // KcpPeer only accepts packets which contain the cookie. + // => cookie can be a random number, but it needs to be cryptographically + // secure random that can't be easily predicted. + // => cookie can be hash(ip, port) BUT only if salted to be not predictable + internal uint cookie; + + // state: connected as soon as we create the peer. + // leftover from KcpConnection. remove it after refactoring later. + protected KcpState state = KcpState.Connected; + + // If we don't receive anything these many milliseconds + // then consider us disconnected + public const int DEFAULT_TIMEOUT = 10000; + public int timeout; + uint lastReceiveTime; + + // internal time. + // StopWatch offers ElapsedMilliSeconds and should be more precise than + // Unity's time.deltaTime over long periods. + readonly Stopwatch watch = new Stopwatch(); + + // buffer to receive kcp's processed messages (avoids allocations). + // IMPORTANT: this is for KCP messages. so it needs to be of size: + // 1 byte header + MaxMessageSize content + readonly byte[] kcpMessageBuffer;// = new byte[1 + ReliableMaxMessageSize]; + + // send buffer for handing user messages to kcp for processing. + // (avoids allocations). + // IMPORTANT: needs to be of size: + // 1 byte header + MaxMessageSize content + readonly byte[] kcpSendBuffer;// = new byte[1 + ReliableMaxMessageSize]; + + // raw send buffer is exactly MTU. + readonly byte[] rawSendBuffer; + + // send a ping occasionally so we don't time out on the other end. + // for example, creating a character in an MMO could easily take a + // minute of no data being sent. which doesn't mean we want to time out. + // same goes for slow paced card games etc. + public const int PING_INTERVAL = 1000; + uint lastPingTime; + + // if we send more than kcp can handle, we will get ever growing + // send/recv buffers and queues and minutes of latency. + // => if a connection can't keep up, it should be disconnected instead + // to protect the server under heavy load, and because there is no + // point in growing to gigabytes of memory or minutes of latency! + // => 2k isn't enough. we reach 2k when spawning 4k monsters at once + // easily, but it does recover over time. + // => 10k seems safe. + // + // note: we have a ChokeConnectionAutoDisconnects test for this too! + internal const int QueueDisconnectThreshold = 10000; + + // getters for queue and buffer counts, used for debug info + public int SendQueueCount => kcp.snd_queue.Count; + public int ReceiveQueueCount => kcp.rcv_queue.Count; + public int SendBufferCount => kcp.snd_buf.Count; + public int ReceiveBufferCount => kcp.rcv_buf.Count; + + // we need to subtract the channel and cookie bytes from every + // MaxMessageSize calculation. + // we also need to tell kcp to use MTU-1 to leave space for the byte. + public const int CHANNEL_HEADER_SIZE = 1; + public const int COOKIE_HEADER_SIZE = 4; + public const int METADATA_SIZE = CHANNEL_HEADER_SIZE + COOKIE_HEADER_SIZE; + + // reliable channel (= kcp) MaxMessageSize so the outside knows largest + // allowed message to send. the calculation in Send() is not obvious at + // all, so let's provide the helper here. + // + // kcp does fragmentation, so max message is way larger than MTU. + // + // -> runtime MTU changes are disabled: mss is always MTU_DEF-OVERHEAD + // -> Send() checks if fragment count < rcv_wnd, so we use rcv_wnd - 1. + // NOTE that original kcp has a bug where WND_RCV default is used + // instead of configured rcv_wnd, limiting max message size to 144 KB + // https://github.com/skywind3000/kcp/pull/291 + // we fixed this in kcp2k. + // -> we add 1 byte KcpHeader enum to each message, so -1 + // + // IMPORTANT: max message is MTU * rcv_wnd, in other words it completely + // fills the receive window! due to head of line blocking, + // all other messages have to wait while a maxed size message + // is being delivered. + // => in other words, DO NOT use max size all the time like + // for batching. + // => sending UNRELIABLE max message size most of the time is + // best for performance (use that one for batching!) + static int ReliableMaxMessageSize_Unconstrained(int mtu, uint rcv_wnd) => + (mtu - Kcp.OVERHEAD - METADATA_SIZE) * ((int)rcv_wnd - 1) - 1; + + // kcp encodes 'frg' as 1 byte. + // max message size can only ever allow up to 255 fragments. + // WND_RCV gives 127 fragments. + // WND_RCV * 2 gives 255 fragments. + // so we can limit max message size by limiting rcv_wnd parameter. + public static int ReliableMaxMessageSize(int mtu, uint rcv_wnd) => + ReliableMaxMessageSize_Unconstrained(mtu, Math.Min(rcv_wnd, Kcp.FRG_MAX)); + + // unreliable max message size is simply MTU - channel header - kcp header + public static int UnreliableMaxMessageSize(int mtu) => + mtu - METADATA_SIZE - 1; + + // maximum send rate per second can be calculated from kcp parameters + // source: https://translate.google.com/translate?sl=auto&tl=en&u=https://wetest.qq.com/lab/view/391.html + // + // KCP can send/receive a maximum of WND*MTU per interval. + // multiple by 1000ms / interval to get the per-second rate. + // + // example: + // WND(32) * MTU(1400) = 43.75KB + // => 43.75KB * 1000 / INTERVAL(10) = 4375KB/s + // + // returns bytes/second! + public uint MaxSendRate => kcp.snd_wnd * kcp.mtu * 1000 / kcp.interval; + public uint MaxReceiveRate => kcp.rcv_wnd * kcp.mtu * 1000 / kcp.interval; + + // calculate max message sizes based on mtu and wnd only once + public readonly int unreliableMax; + public readonly int reliableMax; + + // SetupKcp creates and configures a new KCP instance. + // => useful to start from a fresh state every time the client connects + // => NoDelay, interval, wnd size are the most important configurations. + // let's force require the parameters so we don't forget it anywhere. + protected KcpPeer(KcpConfig config, uint cookie) + { + // initialize variable state in extra function so we can reuse it + // when reconnecting to reset state + Reset(config); + + // set the cookie after resetting state so it's not overwritten again. + // with log message for debugging in case of cookie issues. + this.cookie = cookie; + Log.Info($"[KCP] {GetType()}: created with cookie={cookie}"); + + // create mtu sized send buffer + rawSendBuffer = new byte[config.Mtu]; + + // calculate max message sizes once + unreliableMax = UnreliableMaxMessageSize(config.Mtu); + reliableMax = ReliableMaxMessageSize(config.Mtu, config.ReceiveWindowSize); + + // create message buffers AFTER window size is set + // see comments on buffer definition for the "+1" part + kcpMessageBuffer = new byte[1 + reliableMax]; + kcpSendBuffer = new byte[1 + reliableMax]; + } + + // Reset all state once. + // useful for KcpClient to reconned with a fresh kcp state. + protected void Reset(KcpConfig config) + { + // reset state + cookie = 0; + state = KcpState.Connected; + lastReceiveTime = 0; + lastPingTime = 0; + watch.Restart(); // start at 0 each time + + // set up kcp over reliable channel (that's what kcp is for) + kcp = new Kcp(0, RawSendReliable); + + // set nodelay. + // note that kcp uses 'nocwnd' internally so we negate the parameter + kcp.SetNoDelay(config.NoDelay ? 1u : 0u, config.Interval, config.FastResend, !config.CongestionWindow); + kcp.SetWindowSize(config.SendWindowSize, config.ReceiveWindowSize); + + // IMPORTANT: high level needs to add 1 channel byte to each raw + // message. so while Kcp.MTU_DEF is perfect, we actually need to + // tell kcp to use MTU-1 so we can still put the header into the + // message afterwards. + kcp.SetMtu((uint)config.Mtu - METADATA_SIZE); + + // set maximum retransmits (aka dead_link) + kcp.dead_link = config.MaxRetransmits; + timeout = config.Timeout; + } + + // callbacks /////////////////////////////////////////////////////////// + // events are abstract, guaranteed to be implemented. + // this ensures they are always initialized when used. + // fixes https://github.com/MirrorNetworking/Mirror/issues/3337 and more + protected abstract void OnAuthenticated(); + protected abstract void OnData(ArraySegment message, KcpChannel channel); + protected abstract void OnDisconnected(); + + // error callback instead of logging. + // allows libraries to show popups etc. + // (string instead of Exception for ease of use and to avoid user panic) + protected abstract void OnError(ErrorCode error, string message); + protected abstract void RawSend(ArraySegment data); + + //////////////////////////////////////////////////////////////////////// + + void HandleTimeout(uint time) + { + // note: we are also sending a ping regularly, so timeout should + // only ever happen if the connection is truly gone. + if (time >= lastReceiveTime + timeout) + { + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.Timeout, $"{GetType()}: Connection timed out after not receiving any message for {timeout}ms. Disconnecting."); + Disconnect(); + } + } + + void HandleDeadLink() + { + // kcp has 'dead_link' detection. might as well use it. + if (kcp.state == -1) + { + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.Timeout, $"{GetType()}: dead_link detected: a message was retransmitted {kcp.dead_link} times without ack. Disconnecting."); + Disconnect(); + } + } + + // send a ping occasionally in order to not time out on the other end. + void HandlePing(uint time) + { + // enough time elapsed since last ping? + if (time >= lastPingTime + PING_INTERVAL) + { + // ping again and reset time + //Log.Debug("[KCP] sending ping..."); + SendPing(); + lastPingTime = time; + } + } + + void HandleChoked() + { + // disconnect connections that can't process the load. + // see QueueSizeDisconnect comments. + // => include all of kcp's buffers and the unreliable queue! + int total = kcp.rcv_queue.Count + kcp.snd_queue.Count + + kcp.rcv_buf.Count + kcp.snd_buf.Count; + if (total >= QueueDisconnectThreshold) + { + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.Congestion, + $"{GetType()}: disconnecting connection because it can't process data fast enough.\n" + + $"Queue total {total}>{QueueDisconnectThreshold}. rcv_queue={kcp.rcv_queue.Count} snd_queue={kcp.snd_queue.Count} rcv_buf={kcp.rcv_buf.Count} snd_buf={kcp.snd_buf.Count}\n" + + $"* Try to Enable NoDelay, decrease INTERVAL, disable Congestion Window (= enable NOCWND!), increase SEND/RECV WINDOW or compress data.\n" + + $"* Or perhaps the network is simply too slow on our end, or on the other end."); + + // let's clear all pending sends before disconnting with 'Bye'. + // otherwise a single Flush in Disconnect() won't be enough to + // flush thousands of messages to finally deliver 'Bye'. + // this is just faster and more robust. + kcp.snd_queue.Clear(); + + Disconnect(); + } + } + + // reads the next reliable message type & content from kcp. + // -> to avoid buffering, unreliable messages call OnData directly. + bool ReceiveNextReliable(out KcpHeaderReliable header, out ArraySegment message) + { + message = default; + header = KcpHeaderReliable.Ping; + + int msgSize = kcp.PeekSize(); + if (msgSize <= 0) return false; + + // only allow receiving up to buffer sized messages. + // otherwise we would get BlockCopy ArgumentException anyway. + if (msgSize > kcpMessageBuffer.Length) + { + // we don't allow sending messages > Max, so this must be an + // attacker. let's disconnect to avoid allocation attacks etc. + // pass error to user callback. no need to log it manually. + OnError(ErrorCode.InvalidReceive, $"{GetType()}: possible allocation attack for msgSize {msgSize} > buffer {kcpMessageBuffer.Length}. Disconnecting the connection."); + Disconnect(); + return false; + } + + // receive from kcp + int received = kcp.Receive(kcpMessageBuffer, msgSize); + if (received < 0) + { + // if receive failed, close everything + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.InvalidReceive, $"{GetType()}: Receive failed with error={received}. closing connection."); + Disconnect(); + return false; + } + + // extract header & content without header + header = (KcpHeaderReliable)kcpMessageBuffer[0]; + message = new ArraySegment(kcpMessageBuffer, 1, msgSize - 1); + lastReceiveTime = (uint)watch.ElapsedMilliseconds; + return true; + } + + void TickIncoming_Connected(uint time) + { + // detect common events & ping + HandleTimeout(time); + HandleDeadLink(); + HandlePing(time); + HandleChoked(); + + // any reliable kcp message received? + if (ReceiveNextReliable(out KcpHeaderReliable header, out ArraySegment message)) + { + // message type FSM. no default so we never miss a case. + switch (header) + { + case KcpHeaderReliable.Hello: + { + // we were waiting for a Hello message. + // it proves that the other end speaks our protocol. + + // log with previously parsed cookie + Log.Info($"[KCP] {GetType()}: received hello with cookie={cookie}"); + state = KcpState.Authenticated; + OnAuthenticated(); + break; + } + case KcpHeaderReliable.Ping: + { + // ping keeps kcp from timing out. do nothing. + break; + } + case KcpHeaderReliable.Data: + { + // everything else is not allowed during handshake! + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.InvalidReceive, $"[KCP] {GetType()}: received invalid header {header} while Connected. Disconnecting the connection."); + Disconnect(); + break; + } + } + } + } + + void TickIncoming_Authenticated(uint time) + { + // detect common events & ping + HandleTimeout(time); + HandleDeadLink(); + HandlePing(time); + HandleChoked(); + + // process all received messages + while (ReceiveNextReliable(out KcpHeaderReliable header, out ArraySegment message)) + { + // message type FSM. no default so we never miss a case. + switch (header) + { + case KcpHeaderReliable.Hello: + { + // should never receive another hello after auth + // GetType() shows Server/ClientConn instead of just Connection. + Log.Warning($"{GetType()}: received invalid header {header} while Authenticated. Disconnecting the connection."); + Disconnect(); + break; + } + case KcpHeaderReliable.Data: + { + // call OnData IF the message contained actual data + if (message.Count > 0) + { + //Log.Warning($"Kcp recv msg: {BitConverter.ToString(message.Array, message.Offset, message.Count)}"); + OnData(message, KcpChannel.Reliable); + } + // empty data = attacker, or something went wrong + else + { + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.InvalidReceive, $"{GetType()}: received empty Data message while Authenticated. Disconnecting the connection."); + Disconnect(); + } + break; + } + case KcpHeaderReliable.Ping: + { + // ping keeps kcp from timing out. do nothing. + break; + } + } + } + } + + public virtual void TickIncoming() + { + uint time = (uint)watch.ElapsedMilliseconds; + + try + { + switch (state) + { + case KcpState.Connected: + { + TickIncoming_Connected(time); + break; + } + case KcpState.Authenticated: + { + TickIncoming_Authenticated(time); + break; + } + case KcpState.Disconnected: + { + // do nothing while disconnected + break; + } + } + } + // TODO KcpConnection is IO agnostic. move this to outside later. + catch (SocketException exception) + { + // this is ok, the connection was closed + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.ConnectionClosed, $"{GetType()}: Disconnecting because {exception}. This is fine."); + Disconnect(); + } + catch (ObjectDisposedException exception) + { + // fine, socket was closed + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.ConnectionClosed, $"{GetType()}: Disconnecting because {exception}. This is fine."); + Disconnect(); + } + catch (Exception exception) + { + // unexpected + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.Unexpected, $"{GetType()}: unexpected Exception: {exception}"); + Disconnect(); + } + } + + public virtual void TickOutgoing() + { + uint time = (uint)watch.ElapsedMilliseconds; + + try + { + switch (state) + { + case KcpState.Connected: + case KcpState.Authenticated: + { + // update flushes out messages + kcp.Update(time); + break; + } + case KcpState.Disconnected: + { + // do nothing while disconnected + break; + } + } + } + // TODO KcpConnection is IO agnostic. move this to outside later. + catch (SocketException exception) + { + // this is ok, the connection was closed + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.ConnectionClosed, $"{GetType()}: Disconnecting because {exception}. This is fine."); + Disconnect(); + } + catch (ObjectDisposedException exception) + { + // fine, socket was closed + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.ConnectionClosed, $"{GetType()}: Disconnecting because {exception}. This is fine."); + Disconnect(); + } + catch (Exception exception) + { + // unexpected + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.Unexpected, $"{GetType()}: unexpected exception: {exception}"); + Disconnect(); + } + } + + protected void OnRawInputReliable(ArraySegment message) + { + // input into kcp, but skip channel byte + int input = kcp.Input(message.Array, message.Offset, message.Count); + if (input != 0) + { + // GetType() shows Server/ClientConn instead of just Connection. + Log.Warning($"[KCP] {GetType()}: Input failed with error={input} for buffer with length={message.Count - 1}"); + } + } + + protected void OnRawInputUnreliable(ArraySegment message) + { + // need at least one byte for the KcpHeader enum + if (message.Count < 1) return; + + // parse header and subtract it from message content. + // (above we already ensure it's at least 1 byte long) + KcpHeaderUnreliable header = (KcpHeaderUnreliable)message.Array[message.Offset + 0]; + message = new ArraySegment(message.Array, message.Offset + 1, message.Count - 1); + + switch (header) + { + case KcpHeaderUnreliable.Data: + { + // ideally we would queue all unreliable messages and + // then process them in ReceiveNext() together with the + // reliable messages, but: + // -> queues/allocations/pools are slow and complex. + // -> DOTSNET 10k is actually slower if we use pooled + // unreliable messages for transform messages. + // + // DOTSNET 10k benchmark: + // reliable-only: 170 FPS + // unreliable queued: 130-150 FPS + // unreliable direct: 183 FPS(!) + // + // DOTSNET 50k benchmark: + // reliable-only: FAILS (queues keep growing) + // unreliable direct: 18-22 FPS(!) + // + // -> all unreliable messages are DATA messages anyway. + // -> let's skip the magic and call OnData directly if + // the current state allows it. + if (state == KcpState.Authenticated) + { + OnData(message, KcpChannel.Unreliable); + + // set last receive time to avoid timeout. + // -> we do this in ANY case even if not enabled. + // a message is a message. + // -> we set last receive time for both reliable and + // unreliable messages. both count. + // otherwise a connection might time out even + // though unreliable were received, but no + // reliable was received. + lastReceiveTime = (uint)watch.ElapsedMilliseconds; + } + else + { + // it's common to receive unreliable messages before being + // authenticated, for example: + // - random internet noise + // - game server may send an unreliable message after authenticating, + // and the unreliable message arrives on the client before the + // 'auth_ok' message. this can be avoided by sending a final + // 'ready' message after being authenticated, but this would + // add another 'round trip time' of latency to the handshake. + // + // it's best to simply ignore invalid unreliable messages here. + // Log.Info($"{GetType()}: received unreliable message while not authenticated."); + } + break; + } + case KcpHeaderUnreliable.Disconnect: + { + // GetType() shows Server/ClientConn instead of just Connection. + Log.Info($"[KCP] {GetType()}: received disconnect message"); + Disconnect(); + break; + } + } + } + + // raw send called by kcp + void RawSendReliable(byte[] data, int length) + { + // write channel header + // from 0, with 1 byte + rawSendBuffer[0] = (byte)KcpChannel.Reliable; + + // write handshake cookie to protect against UDP spoofing. + // from 1, with 4 bytes + Utils.Encode32U(rawSendBuffer, 1, cookie); // allocation free + + // write data + // from 5, with N bytes + Buffer.BlockCopy(data, 0, rawSendBuffer, 1+4, length); + + // IO send + ArraySegment segment = new ArraySegment(rawSendBuffer, 0, length + 1+4); + RawSend(segment); + } + + void SendReliable(KcpHeaderReliable header, ArraySegment content) + { + // 1 byte header + content needs to fit into send buffer + if (1 + content.Count > kcpSendBuffer.Length) // TODO + { + // otherwise content is larger than MaxMessageSize. let user know! + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.InvalidSend, $"{GetType()}: Failed to send reliable message of size {content.Count} because it's larger than ReliableMaxMessageSize={reliableMax}"); + return; + } + + // write channel header + kcpSendBuffer[0] = (byte)header; + + // write data (if any) + if (content.Count > 0) + Buffer.BlockCopy(content.Array, content.Offset, kcpSendBuffer, 1, content.Count); + + // send to kcp for processing + int sent = kcp.Send(kcpSendBuffer, 0, 1 + content.Count); + if (sent < 0) + { + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.InvalidSend, $"{GetType()}: Send failed with error={sent} for content with length={content.Count}"); + } + } + + void SendUnreliable(KcpHeaderUnreliable header, ArraySegment content) + { + // message size needs to be <= unreliable max size + if (content.Count > unreliableMax) + { + // otherwise content is larger than MaxMessageSize. let user know! + // GetType() shows Server/ClientConn instead of just Connection. + Log.Error($"[KCP] {GetType()}: Failed to send unreliable message of size {content.Count} because it's larger than UnreliableMaxMessageSize={unreliableMax}"); + return; + } + + // write channel header + // from 0, with 1 byte + rawSendBuffer[0] = (byte)KcpChannel.Unreliable; + + // write handshake cookie to protect against UDP spoofing. + // from 1, with 4 bytes + Utils.Encode32U(rawSendBuffer, 1, cookie); // allocation free + + // write kcp header + rawSendBuffer[5] = (byte)header; + + // write data (if any) + // from 6, with N bytes + if (content.Count > 0) + Buffer.BlockCopy(content.Array, content.Offset, rawSendBuffer, 1 + 4 + 1, content.Count); + + // IO send + ArraySegment segment = new ArraySegment(rawSendBuffer, 0, content.Count + 1 + 4 + 1); + RawSend(segment); + } + + // server & client need to send handshake at different times, so we need + // to expose the function. + // * client should send it immediately. + // * server should send it as reply to client's handshake, not before + // (server should not reply to random internet messages with handshake) + // => handshake info needs to be delivered, so it goes over reliable. + public void SendHello() + { + // send an empty message with 'Hello' header. + // cookie is automatically included in all messages. + + // GetType() shows Server/ClientConn instead of just Connection. + Log.Info($"[KCP] {GetType()}: sending handshake to other end with cookie={cookie}"); + SendReliable(KcpHeaderReliable.Hello, default); + } + + public void SendData(ArraySegment data, KcpChannel channel) + { + // sending empty segments is not allowed. + // nobody should ever try to send empty data. + // it means that something went wrong, e.g. in Mirror/DOTSNET. + // let's make it obvious so it's easy to debug. + if (data.Count == 0) + { + // pass error to user callback. no need to log it manually. + // GetType() shows Server/ClientConn instead of just Connection. + OnError(ErrorCode.InvalidSend, $"{GetType()}: tried sending empty message. This should never happen. Disconnecting."); + Disconnect(); + return; + } + + switch (channel) + { + case KcpChannel.Reliable: + SendReliable(KcpHeaderReliable.Data, data); + break; + case KcpChannel.Unreliable: + SendUnreliable(KcpHeaderUnreliable.Data, data); + break; + } + } + + // ping goes through kcp to keep it from timing out, so it goes over the + // reliable channel. + void SendPing() => SendReliable(KcpHeaderReliable.Ping, default); + + // send disconnect message + void SendDisconnect() + { + // sending over reliable to ensure delivery seems like a good idea: + // but if we close the connection immediately, it often doesn't get + // fully delivered: https://github.com/MirrorNetworking/Mirror/issues/3591 + // SendReliable(KcpHeader.Disconnect, default); + // + // instead, rapid fire a few unreliable messages. + // they are sent immediately even if we close the connection after. + // this way we don't need to keep the connection alive for a while. + // (glenn fiedler method) + for (int i = 0; i < 5; ++i) + SendUnreliable(KcpHeaderUnreliable.Disconnect, default); + } + + // disconnect this connection + public virtual void Disconnect() + { + // only if not disconnected yet + if (state == KcpState.Disconnected) + return; + + // send a disconnect message + try + { + SendDisconnect(); + } + // TODO KcpConnection is IO agnostic. move this to outside later. + catch (SocketException) + { + // this is ok, the connection was already closed + } + catch (ObjectDisposedException) + { + // this is normal when we stop the server + // the socket is stopped so we can't send anything anymore + // to the clients + + // the clients will eventually timeout and realize they + // were disconnected + } + + // set as Disconnected, call event + // GetType() shows Server/ClientConn instead of just Connection. + Log.Info($"[KCP] {GetType()}: Disconnected."); + state = KcpState.Disconnected; + OnDisconnected(); + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpPeer.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpPeer.cs.meta new file mode 100644 index 0000000..fa5dcff --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpPeer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3915c7c62b72d4dc2a9e4e76c94fc484 +timeCreated: 1602600432 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs new file mode 100644 index 0000000..5b8ce4d --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs @@ -0,0 +1,411 @@ +// kcp server logic abstracted into a class. +// for use in Mirror, DOTSNET, testing, etc. +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; + +namespace kcp2k +{ + public class KcpServer + { + // callbacks + // even for errors, to allow liraries to show popups etc. + // instead of logging directly. + // (string instead of Exception for ease of use and to avoid user panic) + // + // events are readonly, set in constructor. + // this ensures they are always initialized when used. + // fixes https://github.com/MirrorNetworking/Mirror/issues/3337 and more + protected readonly Action OnConnected; + protected readonly Action, KcpChannel> OnData; + protected readonly Action OnDisconnected; + protected readonly Action OnError; + + // configuration + protected readonly KcpConfig config; + + // state + protected Socket socket; + EndPoint newClientEP; + + // expose local endpoint for users / relays / nat traversal etc. + public EndPoint LocalEndPoint => socket?.LocalEndPoint; + + // raw receive buffer always needs to be of 'MTU' size, even if + // MaxMessageSize is larger. kcp always sends in MTU segments and having + // a buffer smaller than MTU would silently drop excess data. + // => we need the mtu to fit channel + message! + protected readonly byte[] rawReceiveBuffer; + + // connections where connectionId is EndPoint.GetHashCode + public Dictionary connections = + new Dictionary(); + + public KcpServer(Action OnConnected, + Action, KcpChannel> OnData, + Action OnDisconnected, + Action OnError, + KcpConfig config) + { + // initialize callbacks first to ensure they can be used safely. + this.OnConnected = OnConnected; + this.OnData = OnData; + this.OnDisconnected = OnDisconnected; + this.OnError = OnError; + this.config = config; + + // create mtu sized receive buffer + rawReceiveBuffer = new byte[config.Mtu]; + + // create newClientEP either IPv4 or IPv6 + newClientEP = config.DualMode + ? new IPEndPoint(IPAddress.IPv6Any, 0) + : new IPEndPoint(IPAddress.Any, 0); + } + + public virtual bool IsActive() => socket != null; + + static Socket CreateServerSocket(bool DualMode, ushort port) + { + if (DualMode) + { + // IPv6 socket with DualMode @ "::" : port + Socket socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); + + // enabling DualMode may throw: + // https://learn.microsoft.com/en-us/dotnet/api/System.Net.Sockets.Socket.DualMode?view=net-7.0 + // attempt it, otherwise log but continue + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3358 + try + { + socket.DualMode = true; + } + catch (NotSupportedException e) + { + Log.Warning($"[KCP] Failed to set Dual Mode, continuing with IPv6 without Dual Mode. Error: {e}"); + } + + // for windows sockets, there's a rare issue where when using + // a server socket with multiple clients, if one of the clients + // is closed, the single server socket throws exceptions when + // sending/receiving. even if the socket is made for N clients. + // + // this actually happened to one of our users: + // https://github.com/MirrorNetworking/Mirror/issues/3611 + // + // here's the in-depth explanation & solution: + // + // "As you may be aware, if a host receives a packet for a UDP + // port that is not currently bound, it may send back an ICMP + // "Port Unreachable" message. Whether or not it does this is + // dependent on the firewall, private/public settings, etc. + // On localhost, however, it will pretty much always send this + // packet back. + // + // Now, on Windows (and only on Windows), by default, a received + // ICMP Port Unreachable message will close the UDP socket that + // sent it; hence, the next time you try to receive on the + // socket, it will throw an exception because the socket has + // been closed by the OS. + // + // Obviously, this causes a headache in the multi-client, + // single-server socket set-up you have here, but luckily there + // is a fix: + // + // You need to utilise the not-often-required SIO_UDP_CONNRESET + // Winsock control code, which turns off this built-in behaviour + // of automatically closing the socket. + // + // Note that this ioctl code is only supported on Windows + // (XP and later), not on Linux, since it is provided by the + // Winsock extensions. Of course, since the described behavior + // is only the default behavior on Windows, this omission is not + // a major loss. If you are attempting to create a + // cross-platform library, you should cordon this off as + // Windows-specific code." + // https://stackoverflow.com/questions/74327225/why-does-sending-via-a-udpclient-cause-subsequent-receiving-to-fail + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + const uint IOC_IN = 0x80000000U; + const uint IOC_VENDOR = 0x18000000U; + const int SIO_UDP_CONNRESET = unchecked((int)(IOC_IN | IOC_VENDOR | 12)); + socket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0x00 }, null); + } + + socket.Bind(new IPEndPoint(IPAddress.IPv6Any, port)); + return socket; + } + else + { + // IPv4 socket @ "0.0.0.0" : port + Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + socket.Bind(new IPEndPoint(IPAddress.Any, port)); + return socket; + } + } + + public virtual void Start(ushort port) + { + // only start once + if (socket != null) + { + Log.Warning("[KCP] Server: already started!"); + return; + } + + // listen + socket = CreateServerSocket(config.DualMode, port); + + // recv & send are called from main thread. + // need to ensure this never blocks. + // even a 1ms block per connection would stop us from scaling. + socket.Blocking = false; + + // configure buffer sizes + Common.ConfigureSocketBuffers(socket, config.RecvBufferSize, config.SendBufferSize); + } + + public void Send(int connectionId, ArraySegment segment, KcpChannel channel) + { + if (connections.TryGetValue(connectionId, out KcpServerConnection connection)) + { + connection.SendData(segment, channel); + } + } + + public void Disconnect(int connectionId) + { + if (connections.TryGetValue(connectionId, out KcpServerConnection connection)) + { + connection.Disconnect(); + } + } + + // expose the whole IPEndPoint, not just the IP address. some need it. + public IPEndPoint GetClientEndPoint(int connectionId) + { + if (connections.TryGetValue(connectionId, out KcpServerConnection connection)) + { + return connection.remoteEndPoint as IPEndPoint; + } + return null; + } + + // io - input. + // virtual so it may be modified for relays, nonalloc workaround, etc. + // https://github.com/vis2k/where-allocation + // bool return because not all receives may be valid. + // for example, relay may expect a certain header. + protected virtual bool RawReceiveFrom(out ArraySegment segment, out int connectionId) + { + segment = default; + connectionId = 0; + if (socket == null) return false; + + try + { + if (socket.ReceiveFromNonBlocking(rawReceiveBuffer, out segment, ref newClientEP)) + { + // set connectionId to hash from endpoint + connectionId = Common.ConnectionHash(newClientEP); + return true; + } + } + catch (SocketException e) + { + // NOTE: SocketException is not a subclass of IOException. + // the other end closing the connection is not an 'error'. + // but connections should never just end silently. + // at least log a message for easier debugging. + Log.Info($"[KCP] Server: ReceiveFrom failed: {e}"); + } + + return false; + } + + // io - out. + // virtual so it may be modified for relays, nonalloc workaround, etc. + // relays may need to prefix connId (and remoteEndPoint would be same for all) + protected virtual void RawSend(int connectionId, ArraySegment data) + { + // get the connection's endpoint + if (!connections.TryGetValue(connectionId, out KcpServerConnection connection)) + { + Log.Warning($"[KCP] Server: RawSend invalid connectionId={connectionId}"); + return; + } + + try + { + socket.SendToNonBlocking(data, connection.remoteEndPoint); + } + catch (SocketException e) + { + Log.Error($"[KCP] Server: SendTo failed: {e}"); + } + } + + protected virtual KcpServerConnection CreateConnection(int connectionId) + { + // generate a random cookie for this connection to avoid UDP spoofing. + // needs to be random, but without allocations to avoid GC. + uint cookie = Common.GenerateCookie(); + + // create empty connection without peer first. + // we need it to set up peer callbacks. + // afterwards we assign the peer. + // events need to be wrapped with connectionIds + KcpServerConnection connection = new KcpServerConnection( + OnConnectedCallback, + (message, channel) => OnData(connectionId, message, channel), + OnDisconnectedCallback, + (error, reason) => OnError(connectionId, error, reason), + (data) => RawSend(connectionId, data), + config, + cookie, + newClientEP); + + return connection; + + // setup authenticated event that also adds to connections + void OnConnectedCallback(KcpServerConnection conn) + { + // add to connections dict after being authenticated. + connections.Add(connectionId, conn); + Log.Info($"[KCP] Server: added connection({connectionId})"); + + // setup Data + Disconnected events only AFTER the + // handshake. we don't want to fire OnServerDisconnected + // every time we receive invalid random data from the + // internet. + + // setup data event + + // finally, call mirror OnConnected event + Log.Info($"[KCP] Server: OnConnected({connectionId})"); + OnConnected(connectionId); + } + + void OnDisconnectedCallback() + { + // flag for removal + // (can't remove directly because connection is updated + // and event is called while iterating all connections) + connectionsToRemove.Add(connectionId); + + // call mirror event + Log.Info($"[KCP] Server: OnDisconnected({connectionId})"); + OnDisconnected(connectionId); + } + } + + // receive + add + process once. + // best to call this as long as there is more data to receive. + void ProcessMessage(ArraySegment segment, int connectionId) + { + //Log.Info($"[KCP] server raw recv {msgLength} bytes = {BitConverter.ToString(buffer, 0, msgLength)}"); + + // is this a new connection? + if (!connections.TryGetValue(connectionId, out KcpServerConnection connection)) + { + // create a new KcpConnection based on last received + // EndPoint. can be overwritten for where-allocation. + connection = CreateConnection(connectionId); + + // DO NOT add to connections yet. only if the first message + // is actually the kcp handshake. otherwise it's either: + // * random data from the internet + // * or from a client connection that we just disconnected + // but that hasn't realized it yet, still sending data + // from last session that we should absolutely ignore. + // + // + // TODO this allocates a new KcpConnection for each new + // internet connection. not ideal, but C# UDP Receive + // already allocated anyway. + // + // expecting a MAGIC byte[] would work, but sending the raw + // UDP message without kcp's reliability will have low + // probability of being received. + // + // for now, this is fine. + + + // now input the message & process received ones + // connected event was set up. + // tick will process the first message and adds the + // connection if it was the handshake. + connection.RawInput(segment); + connection.TickIncoming(); + + // again, do not add to connections. + // if the first message wasn't the kcp handshake then + // connection will simply be garbage collected. + } + // existing connection: simply input the message into kcp + else + { + connection.RawInput(segment); + } + } + + // process incoming messages. should be called before updating the world. + // virtual because relay may need to inject their own ping or similar. + readonly HashSet connectionsToRemove = new HashSet(); + public virtual void TickIncoming() + { + // input all received messages into kcp + while (RawReceiveFrom(out ArraySegment segment, out int connectionId)) + { + ProcessMessage(segment, connectionId); + } + + // process inputs for all server connections + // (even if we didn't receive anything. need to tick ping etc.) + foreach (KcpServerConnection connection in connections.Values) + { + connection.TickIncoming(); + } + + // remove disconnected connections + // (can't do it in connection.OnDisconnected because Tick is called + // while iterating connections) + foreach (int connectionId in connectionsToRemove) + { + connections.Remove(connectionId); + } + connectionsToRemove.Clear(); + } + + // process outgoing messages. should be called after updating the world. + // virtual because relay may need to inject their own ping or similar. + public virtual void TickOutgoing() + { + // flush all server connections + foreach (KcpServerConnection connection in connections.Values) + { + connection.TickOutgoing(); + } + } + + // process incoming and outgoing for convenience. + // => ideally call ProcessIncoming() before updating the world and + // ProcessOutgoing() after updating the world for minimum latency + public virtual void Tick() + { + TickIncoming(); + TickOutgoing(); + } + + public virtual void Stop() + { + // need to clear connections, otherwise they are in next session. + // fixes https://github.com/vis2k/kcp2k/pull/47 + connections.Clear(); + socket?.Close(); + socket = null; + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs.meta new file mode 100644 index 0000000..ef720d4 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9759159c6589494a9037f5e130a867ed +timeCreated: 1603787747 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServerConnection.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServerConnection.cs new file mode 100644 index 0000000..8011663 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServerConnection.cs @@ -0,0 +1,124 @@ +// server needs to store a separate KcpPeer for each connection. +// as well as remoteEndPoint so we know where to send data to. +using System; +using System.Net; + +namespace kcp2k +{ + public class KcpServerConnection : KcpPeer + { + public readonly EndPoint remoteEndPoint; + + // callbacks + // even for errors, to allow liraries to show popups etc. + // instead of logging directly. + // (string instead of Exception for ease of use and to avoid user panic) + // + // events are readonly, set in constructor. + // this ensures they are always initialized when used. + // fixes https://github.com/MirrorNetworking/Mirror/issues/3337 and more + protected readonly Action OnConnectedCallback; + protected readonly Action, KcpChannel> OnDataCallback; + protected readonly Action OnDisconnectedCallback; + protected readonly Action OnErrorCallback; + protected readonly Action> RawSendCallback; + + public KcpServerConnection( + Action OnConnected, + Action, KcpChannel> OnData, + Action OnDisconnected, + Action OnError, + Action> OnRawSend, + KcpConfig config, + uint cookie, + EndPoint remoteEndPoint) + : base(config, cookie) + { + OnConnectedCallback = OnConnected; + OnDataCallback = OnData; + OnDisconnectedCallback = OnDisconnected; + OnErrorCallback = OnError; + RawSendCallback = OnRawSend; + + this.remoteEndPoint = remoteEndPoint; + } + + // callbacks /////////////////////////////////////////////////////////// + protected override void OnAuthenticated() + { + // once we receive the first client hello, + // immediately reply with hello so the client knows the security cookie. + SendHello(); + OnConnectedCallback(this); + } + + protected override void OnData(ArraySegment message, KcpChannel channel) => + OnDataCallback(message, channel); + + protected override void OnDisconnected() => + OnDisconnectedCallback(); + + protected override void OnError(ErrorCode error, string message) => + OnErrorCallback(error, message); + + protected override void RawSend(ArraySegment data) => + RawSendCallback(data); + //////////////////////////////////////////////////////////////////////// + + // insert raw IO. usually from socket.Receive. + // offset is useful for relays, where we may parse a header and then + // feed the rest to kcp. + public void RawInput(ArraySegment segment) + { + // ensure valid size: at least 1 byte for channel + 4 bytes for cookie + if (segment.Count <= 5) return; + + // parse channel + // byte channel = segment[0]; ArraySegment[i] isn't supported in some older Unity Mono versions + byte channel = segment.Array[segment.Offset + 0]; + + // all server->client messages include the server's security cookie. + // all client->server messages except for the initial 'hello' include it too. + // parse the cookie and make sure it matches (except for initial hello). + Utils.Decode32U(segment.Array, segment.Offset + 1, out uint messageCookie); + + // compare cookie to protect against UDP spoofing. + // messages won't have a cookie until after handshake. + // so only compare if we are authenticated. + // simply drop the message if the cookie doesn't match. + if (state == KcpState.Authenticated) + { + if (messageCookie != cookie) + { + Log.Warning($"[KCP] ServerConnection: dropped message with invalid cookie: {messageCookie} expected: {cookie} state: {state}"); + return; + } + } + + // parse message + ArraySegment message = new ArraySegment(segment.Array, segment.Offset + 1+4, segment.Count - 1-4); + + switch (channel) + { + case (byte)KcpChannel.Reliable: + { + OnRawInputReliable(message); + break; + } + case (byte)KcpChannel.Unreliable: + { + OnRawInputUnreliable(message); + break; + } + default: + { + // invalid channel indicates random internet noise. + // servers may receive random UDP data. + // just ignore it, but log for easier debugging. + Log.Warning($"[KCP] ServerConnection: invalid channel header: {channel}, likely internet noise"); + break; + } + } + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServerConnection.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServerConnection.cs.meta new file mode 100644 index 0000000..10d9803 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServerConnection.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 80a9b1ce9a6f14abeb32bfa9921d097b +timeCreated: 1602601483 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpState.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpState.cs new file mode 100644 index 0000000..9d01d64 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpState.cs @@ -0,0 +1,4 @@ +namespace kcp2k +{ + public enum KcpState { Connected, Authenticated, Disconnected } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpState.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpState.cs.meta new file mode 100644 index 0000000..9eddc68 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 81a02c141a88d45d4a2f5ef68c6da75f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Log.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Log.cs new file mode 100644 index 0000000..c28d8b8 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Log.cs @@ -0,0 +1,14 @@ +// A simple logger class that uses Console.WriteLine by default. +// Can also do Logger.LogMethod = Debug.Log for Unity etc. +// (this way we don't have to depend on UnityEngine) +using System; + +namespace kcp2k +{ + public static class Log + { + public static Action Info = Console.WriteLine; + public static Action Warning = Console.WriteLine; + public static Action Error = Console.Error.WriteLine; + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Log.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Log.cs.meta new file mode 100644 index 0000000..333bee5 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/Log.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b5e1de98d6d84c3793a61cf7d8da9a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp.meta b/Assets/Mirror/Transports/KCP/kcp2k/kcp.meta new file mode 100644 index 0000000..a7d6e11 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5cafb8851a0084f3e94a580c207b3923 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/AckItem.cs b/Assets/Mirror/Transports/KCP/kcp2k/kcp/AckItem.cs new file mode 100644 index 0000000..820f451 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/AckItem.cs @@ -0,0 +1,8 @@ +namespace kcp2k +{ + internal struct AckItem + { + internal uint serialNumber; + internal uint timestamp; + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/AckItem.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/kcp/AckItem.cs.meta new file mode 100644 index 0000000..301e2eb --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/AckItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 71f47cb11125d429e84e188a150f3ae5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/AssemblyInfo.cs b/Assets/Mirror/Transports/KCP/kcp2k/kcp/AssemblyInfo.cs new file mode 100644 index 0000000..5fe5547 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("kcp2k.Tests")] \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/AssemblyInfo.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/kcp/AssemblyInfo.cs.meta new file mode 100644 index 0000000..6b442a9 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/AssemblyInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: aec6a15ac7bd43129317ea1f01f19782 +timeCreated: 1602665988 \ No newline at end of file diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/Kcp.cs b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Kcp.cs new file mode 100644 index 0000000..851faaa --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Kcp.cs @@ -0,0 +1,1118 @@ +// Kcp based on https://github.com/skywind3000/kcp +// Kept as close to original as possible. +using System; +using System.Collections.Generic; + +namespace kcp2k +{ + public class Kcp + { + // original Kcp has a define option, which is not defined by default: + // #define FASTACK_CONSERVE + + public const int RTO_NDL = 30; // no delay min rto + public const int RTO_MIN = 100; // normal min rto + public const int RTO_DEF = 200; // default RTO + public const int RTO_MAX = 60000; // maximum RTO + public const int CMD_PUSH = 81; // cmd: push data + public const int CMD_ACK = 82; // cmd: ack + public const int CMD_WASK = 83; // cmd: window probe (ask) + public const int CMD_WINS = 84; // cmd: window size (tell/insert) + public const int ASK_SEND = 1; // need to send CMD_WASK + public const int ASK_TELL = 2; // need to send CMD_WINS + public const int WND_SND = 32; // default send window + public const int WND_RCV = 128; // default receive window. must be >= max fragment size + public const int MTU_DEF = 1200; // default MTU (reduced to 1200 to fit all cases: https://en.wikipedia.org/wiki/Maximum_transmission_unit ; steam uses 1200 too!) + public const int ACK_FAST = 3; + public const int INTERVAL = 100; + public const int OVERHEAD = 24; + public const int FRG_MAX = byte.MaxValue; // kcp encodes 'frg' as byte. so we can only ever send up to 255 fragments. + public const int DEADLINK = 20; // default maximum amount of 'xmit' retransmissions until a segment is considered lost + public const int THRESH_INIT = 2; + public const int THRESH_MIN = 2; + public const int PROBE_INIT = 7000; // 7 secs to probe window size + public const int PROBE_LIMIT = 120000; // up to 120 secs to probe window + public const int FASTACK_LIMIT = 5; // max times to trigger fastack + + // kcp members. + internal int state; + readonly uint conv; // conversation + internal uint mtu; + internal uint mss; // maximum segment size := MTU - OVERHEAD + internal uint snd_una; // unacknowledged. e.g. snd_una is 9 it means 8 has been confirmed, 9 and 10 have been sent + internal uint snd_nxt; // forever growing send counter for sequence numbers + internal uint rcv_nxt; // forever growing receive counter for sequence numbers + internal uint ssthresh; // slow start threshold + internal int rx_rttval; // average deviation of rtt, used to measure the jitter of rtt + internal int rx_srtt; // smoothed round trip time (a weighted average of rtt) + internal int rx_rto; + internal int rx_minrto; + internal uint snd_wnd; // send window + internal uint rcv_wnd; // receive window + internal uint rmt_wnd; // remote window + internal uint cwnd; // congestion window + internal uint probe; + internal uint interval; + internal uint ts_flush; // last flush timestamp in milliseconds + internal uint xmit; + internal uint nodelay; // not a bool. original Kcp has '<2 else' check. + internal bool updated; + internal uint ts_probe; // probe timestamp + internal uint probe_wait; + internal uint dead_link; // maximum amount of 'xmit' retransmissions until a segment is considered lost + internal uint incr; + internal uint current; // current time (milliseconds). set by Update. + + internal int fastresend; + internal int fastlimit; + internal bool nocwnd; // congestion control, negated. heavily restricts send/recv window sizes. + internal readonly Queue snd_queue = new Queue(16); // send queue + internal readonly Queue rcv_queue = new Queue(16); // receive queue + // snd_buffer needs index removals. + // C# LinkedList allocates for each entry, so let's keep List for now. + internal readonly List snd_buf = new List(16); // send buffer + // rcv_buffer needs index insertions and backwards iteration. + // C# LinkedList allocates for each entry, so let's keep List for now. + internal readonly List rcv_buf = new List(16); // receive buffer + internal readonly List acklist = new List(16); + + // memory buffer + // size depends on MTU. + // MTU can be changed at runtime, which resizes the buffer. + internal byte[] buffer; + + // output function of type + readonly Action output; + + // segment pool to avoid allocations in C#. + // this is not part of the original C code. + readonly Pool SegmentPool = new Pool( + // create new segment + () => new Segment(), + // reset segment before reuse + (segment) => segment.Reset(), + // initial capacity + 32 + ); + + // ikcp_create + // create a new kcp control object, 'conv' must equal in two endpoint + // from the same connection. + public Kcp(uint conv, Action output) + { + this.conv = conv; + this.output = output; + snd_wnd = WND_SND; + rcv_wnd = WND_RCV; + rmt_wnd = WND_RCV; + mtu = MTU_DEF; + mss = mtu - OVERHEAD; + rx_rto = RTO_DEF; + rx_minrto = RTO_MIN; + interval = INTERVAL; + ts_flush = INTERVAL; + ssthresh = THRESH_INIT; + fastlimit = FASTACK_LIMIT; + dead_link = DEADLINK; + buffer = new byte[(mtu + OVERHEAD) * 3]; + } + + // ikcp_segment_new + // we keep the original function and add our pooling to it. + // this way we'll never miss it anywhere. + Segment SegmentNew() => SegmentPool.Take(); + + // ikcp_segment_delete + // we keep the original function and add our pooling to it. + // this way we'll never miss it anywhere. + void SegmentDelete(Segment seg) => SegmentPool.Return(seg); + + // calculate how many packets are waiting to be sent + public int WaitSnd => snd_buf.Count + snd_queue.Count; + + // ikcp_wnd_unused + // returns the remaining space in receive window (rcv_wnd - rcv_queue) + internal uint WndUnused() + { + if (rcv_queue.Count < rcv_wnd) + return rcv_wnd - (uint)rcv_queue.Count; + return 0; + } + + // ikcp_recv + // receive data from kcp state machine + // returns number of bytes read. + // returns negative on error. + // note: pass negative length to peek. + public int Receive(byte[] buffer, int len) + { + // kcp's ispeek feature is not supported. + // this makes 'merge fragment' code significantly easier because + // we can iterate while queue.Count > 0 and dequeue each time. + // if we had to consider ispeek then count would always be > 0 and + // we would have to remove only after the loop. + // + //bool ispeek = len < 0; + if (len < 0) + throw new NotSupportedException("Receive ispeek for negative len is not supported!"); + + if (rcv_queue.Count == 0) + return -1; + + if (len < 0) len = -len; + + int peeksize = PeekSize(); + + if (peeksize < 0) + return -2; + + if (peeksize > len) + return -3; + + bool recover = rcv_queue.Count >= rcv_wnd; + + // merge fragment. + int offset = 0; + len = 0; + // original KCP iterates rcv_queue and deletes if !ispeek. + // removing from a c# queue while iterating is not possible, but + // we can change to 'while Count > 0' and remove every time. + // (we can remove every time because we removed ispeek support!) + while (rcv_queue.Count > 0) + { + // unlike original kcp, we dequeue instead of just getting the + // entry. this is fine because we remove it in ANY case. + Segment seg = rcv_queue.Dequeue(); + + // copy segment data into our buffer + Buffer.BlockCopy(seg.data.GetBuffer(), 0, buffer, offset, (int)seg.data.Position); + offset += (int)seg.data.Position; + + len += (int)seg.data.Position; + uint fragment = seg.frg; + + // note: ispeek is not supported in order to simplify this loop + + // unlike original kcp, we don't need to remove seg from queue + // because we already dequeued it. + // simply delete it + SegmentDelete(seg); + + if (fragment == 0) + break; + } + + // move available data from rcv_buf -> rcv_queue + int removed = 0; + foreach (Segment seg in rcv_buf) + { + if (seg.sn == rcv_nxt && rcv_queue.Count < rcv_wnd) + { + // can't remove while iterating. remember how many to remove + // and do it after the loop. + // note: don't return segment. we only add it to rcv_queue + ++removed; + // add + rcv_queue.Enqueue(seg); + // increase sequence number for next segment + rcv_nxt++; + } + else + { + break; + } + } + rcv_buf.RemoveRange(0, removed); + + // fast recover + if (rcv_queue.Count < rcv_wnd && recover) + { + // ready to send back CMD_WINS in flush + // tell remote my window size + probe |= ASK_TELL; + } + + return len; + } + + // ikcp_peeksize + // check the size of next message in the recv queue. + // returns -1 if there is no message, or if the message is still incomplete. + public int PeekSize() + { + int length = 0; + + // empty queue? + if (rcv_queue.Count == 0) return -1; + + // peek the first segment + Segment seq = rcv_queue.Peek(); + + // seg.frg is 0 if the message requires no fragmentation. + // in that case, the segment's size is the final message size. + if (seq.frg == 0) return (int)seq.data.Position; + + // check if all fragment parts were received yet. + // seg.frg is the n-th fragment, but in reverse. + // this way the first received segment tells us how many fragments there are for the message. + // for example, if a message contains 3 segments: + // first segment: .frg is 2 (index in reverse) + // second segment: .frg is 1 (index in reverse) + // third segment: .frg is 0 (index in reverse) + if (rcv_queue.Count < seq.frg + 1) return -1; + + // recv_queue contains all the fragments necessary to reconstruct the message. + // sum all fragment's sizes to get the full message size. + foreach (Segment seg in rcv_queue) + { + length += (int)seg.data.Position; + if (seg.frg == 0) break; + } + + return length; + } + + // ikcp_send + // splits message into MTU sized fragments, adds them to snd_queue. + public int Send(byte[] buffer, int offset, int len) + { + // fragment count + int count; + + if (len < 0) return -1; + + // streaming mode: removed. we never want to send 'hello' and + // receive 'he' 'll' 'o'. we want to always receive 'hello'. + + // calculate amount of fragments necessary for 'len' + if (len <= mss) count = 1; + else count = (int)((len + mss - 1) / mss); + + // IMPORTANT kcp encodes 'frg' as 1 byte. + // so we can only support up to 255 fragments. + // (which limits max message size to around 288 KB) + // this is difficult to debug. let's make this 100% obvious. + if (count > FRG_MAX) + throw new Exception($"Send len={len} requires {count} fragments, but kcp can only handle up to {FRG_MAX} fragments."); + + // original kcp uses WND_RCV const instead of rcv_wnd runtime: + // https://github.com/skywind3000/kcp/pull/291/files + // which always limits max message size to 144 KB: + //if (count >= WND_RCV) return -2; + // using configured rcv_wnd uncorks max message size to 'any': + if (count >= rcv_wnd) return -2; + + if (count == 0) count = 1; + + // fragment + for (int i = 0; i < count; i++) + { + int size = len > (int)mss ? (int)mss : len; + Segment seg = SegmentNew(); + + if (len > 0) + { + seg.data.Write(buffer, offset, size); + } + // seg.len = size: WriteBytes sets segment.Position! + + // set fragment number. + // if the message requires no fragmentation, then + // seg.frg becomes 1-0-1 = 0 + seg.frg = (uint)(count - i - 1); + snd_queue.Enqueue(seg); + offset += size; + len -= size; + } + + return 0; + } + + // ikcp_update_ack + void UpdateAck(int rtt) // round trip time + { + // https://tools.ietf.org/html/rfc6298 + if (rx_srtt == 0) + { + rx_srtt = rtt; + rx_rttval = rtt / 2; + } + else + { + int delta = rtt - rx_srtt; + if (delta < 0) delta = -delta; + rx_rttval = (3 * rx_rttval + delta) / 4; + rx_srtt = (7 * rx_srtt + rtt) / 8; + if (rx_srtt < 1) rx_srtt = 1; + } + int rto = rx_srtt + Math.Max((int)interval, 4 * rx_rttval); + rx_rto = Utils.Clamp(rto, rx_minrto, RTO_MAX); + } + + // ikcp_shrink_buf + internal void ShrinkBuf() + { + if (snd_buf.Count > 0) + { + Segment seg = snd_buf[0]; + snd_una = seg.sn; + } + else + { + snd_una = snd_nxt; + } + } + + // ikcp_parse_ack + // removes the segment with 'sn' from send buffer + internal void ParseAck(uint sn) + { + if (Utils.TimeDiff(sn, snd_una) < 0 || Utils.TimeDiff(sn, snd_nxt) >= 0) + return; + + // for-int so we can erase while iterating + for (int i = 0; i < snd_buf.Count; ++i) + { + // is this the segment? + Segment seg = snd_buf[i]; + if (sn == seg.sn) + { + // remove and return + snd_buf.RemoveAt(i); + SegmentDelete(seg); + break; + } + if (Utils.TimeDiff(sn, seg.sn) < 0) + { + break; + } + } + } + + // ikcp_parse_una + // removes all unacknowledged segments with sequence numbers < una from send buffer + internal void ParseUna(uint una) + { + int removed = 0; + foreach (Segment seg in snd_buf) + { + // if (Utils.TimeDiff(una, seg.sn) > 0) + if (seg.sn < una) + { + // can't remove while iterating. remember how many to remove + // and do it after the loop. + ++removed; + SegmentDelete(seg); + } + else + { + break; + } + } + snd_buf.RemoveRange(0, removed); + } + + // ikcp_parse_fastack + internal void ParseFastack(uint sn, uint ts) // serial number, timestamp + { + // sn needs to be between snd_una and snd_nxt + // if !(snd_una <= sn && sn < snd_nxt) return; + + // if (Utils.TimeDiff(sn, snd_una) < 0) + if (sn < snd_una) + return; + + // if (Utils.TimeDiff(sn, snd_nxt) >= 0) + if (sn >= snd_nxt) + return; + + foreach (Segment seg in snd_buf) + { + // if (Utils.TimeDiff(sn, seg.sn) < 0) + if (sn < seg.sn) + { + break; + } + else if (sn != seg.sn) + { +#if !FASTACK_CONSERVE + seg.fastack++; +#else + if (Utils.TimeDiff(ts, seg.ts) >= 0) + seg.fastack++; +#endif + } + } + } + + // ikcp_ack_push + // appends an ack. + void AckPush(uint sn, uint ts) // serial number, timestamp + { + acklist.Add(new AckItem{ serialNumber = sn, timestamp = ts }); + } + + // ikcp_parse_data + void ParseData(Segment newseg) + { + uint sn = newseg.sn; + + if (Utils.TimeDiff(sn, rcv_nxt + rcv_wnd) >= 0 || + Utils.TimeDiff(sn, rcv_nxt) < 0) + { + SegmentDelete(newseg); + return; + } + + InsertSegmentInReceiveBuffer(newseg); + MoveReceiveBufferReadySegmentsToQueue(); + } + + // inserts the segment into rcv_buf, ordered by seg.sn. + // drops the segment if one with the same seg.sn already exists. + // goes through receive buffer in reverse order for performance. + // + // note: see KcpTests.InsertSegmentInReceiveBuffer test! + // note: 'insert or delete' can be done in different ways, but let's + // keep consistency with original C kcp. + internal void InsertSegmentInReceiveBuffer(Segment newseg) + { + bool repeat = false; // 'duplicate' + + // original C iterates backwards, so we need to do that as well. + // note if rcv_buf.Count == 0, i becomes -1 and no looping happens. + int i; + for (i = rcv_buf.Count - 1; i >= 0; i--) + { + Segment seg = rcv_buf[i]; + if (seg.sn == newseg.sn) + { + // duplicate segment found. nothing will be added. + repeat = true; + break; + } + if (Utils.TimeDiff(newseg.sn, seg.sn) > 0) + { + // this entry's sn is < newseg.sn, so let's stop + break; + } + } + + // no duplicate? then insert. + if (!repeat) + { + rcv_buf.Insert(i + 1, newseg); + } + // duplicate. just delete it. + else + { + SegmentDelete(newseg); + } + } + + // move ready segments from rcv_buf -> rcv_queue. + // moves only the ready segments which are in rcv_nxt sequence order. + // some may still be missing an inserted later. + void MoveReceiveBufferReadySegmentsToQueue() + { + int removed = 0; + foreach (Segment seg in rcv_buf) + { + // move segments while they are in 'rcv_nxt' sequence order. + // some may still be missing and inserted later, in this case it stops immediately + // because segments always need to be received in the exact sequence order. + if (seg.sn == rcv_nxt && rcv_queue.Count < rcv_wnd) + { + // can't remove while iterating. remember how many to remove + // and do it after the loop. + ++removed; + rcv_queue.Enqueue(seg); + // increase sequence number for next segment + rcv_nxt++; + } + else + { + break; + } + } + rcv_buf.RemoveRange(0, removed); + } + + // ikcp_input + // used when you receive a low level packet (e.g. UDP packet) + // => original kcp uses offset=0, we made it a parameter so that high + // level can skip the channel byte more easily + public int Input(byte[] data, int offset, int size) + { + uint prev_una = snd_una; + uint maxack = 0; + uint latest_ts = 0; + int flag = 0; + + if (data == null || size < OVERHEAD) return -1; + + while (true) + { + // enough data left to decode segment (aka OVERHEAD bytes)? + if (size < OVERHEAD) break; + + // decode segment + offset += Utils.Decode32U(data, offset, out uint conv_); + if (conv_ != conv) return -1; + + offset += Utils.Decode8u(data, offset, out byte cmd); + // IMPORTANT kcp encodes 'frg' as 1 byte. + // so we can only support up to 255 fragments. + // (which limits max message size to around 288 KB) + offset += Utils.Decode8u(data, offset, out byte frg); + offset += Utils.Decode16U(data, offset, out ushort wnd); + offset += Utils.Decode32U(data, offset, out uint ts); + offset += Utils.Decode32U(data, offset, out uint sn); + offset += Utils.Decode32U(data, offset, out uint una); + offset += Utils.Decode32U(data, offset, out uint len); + + // reduce remaining size by what was read + size -= OVERHEAD; + + // enough remaining to read 'len' bytes of the actual payload? + // note: original kcp casts uint len to int for <0 check. + if (size < len || (int)len < 0) return -2; + + // validate command type + if (cmd != CMD_PUSH && cmd != CMD_ACK && + cmd != CMD_WASK && cmd != CMD_WINS) + return -3; + + rmt_wnd = wnd; + ParseUna(una); + ShrinkBuf(); + + if (cmd == CMD_ACK) + { + if (Utils.TimeDiff(current, ts) >= 0) + { + UpdateAck(Utils.TimeDiff(current, ts)); + } + ParseAck(sn); + ShrinkBuf(); + if (flag == 0) + { + flag = 1; + maxack = sn; + latest_ts = ts; + } + else + { + if (Utils.TimeDiff(sn, maxack) > 0) + { +#if !FASTACK_CONSERVE + maxack = sn; + latest_ts = ts; +#else + if (Utils.TimeDiff(ts, latest_ts) > 0) + { + maxack = sn; + latest_ts = ts; + } +#endif + } + } + } + else if (cmd == CMD_PUSH) + { + if (Utils.TimeDiff(sn, rcv_nxt + rcv_wnd) < 0) + { + AckPush(sn, ts); + if (Utils.TimeDiff(sn, rcv_nxt) >= 0) + { + Segment seg = SegmentNew(); + seg.conv = conv_; + seg.cmd = cmd; + seg.frg = frg; + seg.wnd = wnd; + seg.ts = ts; + seg.sn = sn; + seg.una = una; + if (len > 0) + { + seg.data.Write(data, offset, (int)len); + } + ParseData(seg); + } + } + } + else if (cmd == CMD_WASK) + { + // ready to send back CMD_WINS in flush + // tell remote my window size + probe |= ASK_TELL; + } + else if (cmd == CMD_WINS) + { + // do nothing + } + else + { + return -3; + } + + offset += (int)len; + size -= (int)len; + } + + if (flag != 0) + { + ParseFastack(maxack, latest_ts); + } + + // cwnd update when packet arrived + if (Utils.TimeDiff(snd_una, prev_una) > 0) + { + if (cwnd < rmt_wnd) + { + if (cwnd < ssthresh) + { + cwnd++; + incr += mss; + } + else + { + if (incr < mss) incr = mss; + incr += (mss * mss) / incr + (mss / 16); + if ((cwnd + 1) * mss <= incr) + { + cwnd = (incr + mss - 1) / ((mss > 0) ? mss : 1); + } + } + if (cwnd > rmt_wnd) + { + cwnd = rmt_wnd; + incr = rmt_wnd * mss; + } + } + } + + return 0; + } + + // flush helper function + void MakeSpace(ref int size, int space) + { + if (size + space > mtu) + { + output(buffer, size); + size = 0; + } + } + + // flush helper function + void FlushBuffer(int size) + { + // flush buffer up to 'offset' (<= MTU) + if (size > 0) + { + output(buffer, size); + } + } + + // ikcp_flush + // flush remain ack segments. + // flush may output multiple <= MTU messages from MakeSpace / FlushBuffer. + // the amount of messages depends on the sliding window. + // configured by send/receive window sizes + congestion control. + // with congestion control, the window will be extremely small(!). + public void Flush() + { + int size = 0; // amount of bytes to flush. 'buffer ptr' in C. + bool lost = false; // lost segments + + // update needs to be called before flushing + if (!updated) return; + + // kcp only stack allocates a segment here for performance, leaving + // its data buffer null because this segment's data buffer is never + // used. that's fine in C, but in C# our segment is a class so we + // need to allocate and most importantly, not forget to deallocate + // it before returning. + Segment seg = SegmentNew(); + seg.conv = conv; + seg.cmd = CMD_ACK; + seg.wnd = WndUnused(); + seg.una = rcv_nxt; + + // flush acknowledges + foreach (AckItem ack in acklist) + { + MakeSpace(ref size, OVERHEAD); + // ikcp_ack_get assigns ack[i] to seg.sn, seg.ts + seg.sn = ack.serialNumber; + seg.ts = ack.timestamp; + size += seg.Encode(buffer, size); + } + acklist.Clear(); + + // probe window size (if remote window size equals zero) + if (rmt_wnd == 0) + { + if (probe_wait == 0) + { + probe_wait = PROBE_INIT; + ts_probe = current + probe_wait; + } + else + { + if (Utils.TimeDiff(current, ts_probe) >= 0) + { + if (probe_wait < PROBE_INIT) + probe_wait = PROBE_INIT; + probe_wait += probe_wait / 2; + if (probe_wait > PROBE_LIMIT) + probe_wait = PROBE_LIMIT; + ts_probe = current + probe_wait; + probe |= ASK_SEND; + } + } + } + else + { + ts_probe = 0; + probe_wait = 0; + } + + // flush window probing commands + if ((probe & ASK_SEND) != 0) + { + seg.cmd = CMD_WASK; + MakeSpace(ref size, OVERHEAD); + size += seg.Encode(buffer, size); + } + + // flush window probing commands + if ((probe & ASK_TELL) != 0) + { + seg.cmd = CMD_WINS; + MakeSpace(ref size, OVERHEAD); + size += seg.Encode(buffer, size); + } + + probe = 0; + + // calculate the window size which is currently safe to send. + // it's send window, or remote window, whatever is smaller. + // for our max + uint cwnd_ = Math.Min(snd_wnd, rmt_wnd); + + // double negative: if congestion window is enabled: + // limit window size to cwnd. + // + // note this may heavily limit window sizes. + // for our max message size test with super large windows of 32k, + // 'congestion window' limits it down from 32.000 to 2. + if (!nocwnd) cwnd_ = Math.Min(cwnd, cwnd_); + + // move cwnd_ 'window size' messages from snd_queue to snd_buf + // 'snd_nxt' is what we want to send. + // 'snd_una' is what hasn't been acked yet. + // copy up to 'cwnd_' difference between them (sliding window) + while (Utils.TimeDiff(snd_nxt, snd_una + cwnd_) < 0) + { + if (snd_queue.Count == 0) break; + + Segment newseg = snd_queue.Dequeue(); + + newseg.conv = conv; + newseg.cmd = CMD_PUSH; + newseg.wnd = seg.wnd; + newseg.ts = current; + newseg.sn = snd_nxt; + snd_nxt += 1; // increase sequence number for next segment + newseg.una = rcv_nxt; + newseg.resendts = current; + newseg.rto = rx_rto; + newseg.fastack = 0; + newseg.xmit = 0; + snd_buf.Add(newseg); + } + + // calculate resent + uint resent = fastresend > 0 ? (uint)fastresend : 0xffffffff; + uint rtomin = nodelay == 0 ? (uint)rx_rto >> 3 : 0; + + // flush data segments + int change = 0; + foreach (Segment segment in snd_buf) + { + bool needsend = false; + + // initial transmit + if (segment.xmit == 0) + { + needsend = true; + segment.xmit++; + segment.rto = rx_rto; + segment.resendts = current + (uint)segment.rto + rtomin; + } + // RTO + else if (Utils.TimeDiff(current, segment.resendts) >= 0) + { + needsend = true; + segment.xmit++; + xmit++; + if (nodelay == 0) + { + segment.rto += Math.Max(segment.rto, rx_rto); + } + else + { + int step = (nodelay < 2) ? segment.rto : rx_rto; + segment.rto += step / 2; + } + segment.resendts = current + (uint)segment.rto; + lost = true; + } + // fast retransmit + else if (segment.fastack >= resent) + { + if (segment.xmit <= fastlimit || fastlimit <= 0) + { + needsend = true; + segment.xmit++; + segment.fastack = 0; + segment.resendts = current + (uint)segment.rto; + change++; + } + } + + if (needsend) + { + segment.ts = current; + segment.wnd = seg.wnd; + segment.una = rcv_nxt; + + int need = OVERHEAD + (int)segment.data.Position; + MakeSpace(ref size, need); + + size += segment.Encode(buffer, size); + + if (segment.data.Position > 0) + { + Buffer.BlockCopy(segment.data.GetBuffer(), 0, buffer, size, (int)segment.data.Position); + size += (int)segment.data.Position; + } + + // dead link happens if a message was resent N times, but an + // ack was still not received. + if (segment.xmit >= dead_link) + { + state = -1; + } + } + } + + // kcp stackallocs 'seg'. our C# segment is a class though, so we + // need to properly delete and return it to the pool now that we are + // done with it. + SegmentDelete(seg); + + // flush remaining segments + FlushBuffer(size); + + // update ssthresh + // rate halving, https://tools.ietf.org/html/rfc6937 + if (change > 0) + { + uint inflight = snd_nxt - snd_una; + ssthresh = inflight / 2; + if (ssthresh < THRESH_MIN) + ssthresh = THRESH_MIN; + cwnd = ssthresh + resent; + incr = cwnd * mss; + } + + // congestion control, https://tools.ietf.org/html/rfc5681 + if (lost) + { + // original C uses 'cwnd', not kcp->cwnd! + ssthresh = cwnd_ / 2; + if (ssthresh < THRESH_MIN) + ssthresh = THRESH_MIN; + cwnd = 1; + incr = mss; + } + + if (cwnd < 1) + { + cwnd = 1; + incr = mss; + } + } + + // ikcp_update + // update state (call it repeatedly, every 10ms-100ms), or you can ask + // Check() when to call it again (without Input/Send calling). + // + // 'current' - current timestamp in millisec. pass it to Kcp so that + // Kcp doesn't have to do any stopwatch/deltaTime/etc. code + // + // time as uint, likely to minimize bandwidth. + // uint.max = 4294967295 ms = 1193 hours = 49 days + public void Update(uint currentTimeMilliSeconds) + { + current = currentTimeMilliSeconds; + + // not updated yet? then set updated and last flush time. + if (!updated) + { + updated = true; + ts_flush = current; + } + + // slap is time since last flush in milliseconds + int slap = Utils.TimeDiff(current, ts_flush); + + // hard limit: if 10s elapsed, always flush no matter what + if (slap >= 10000 || slap < -10000) + { + ts_flush = current; + slap = 0; + } + + // last flush is increased by 'interval' each time. + // so slap >= is a strange way to check if interval has elapsed yet. + if (slap >= 0) + { + // increase last flush time by one interval + ts_flush += interval; + + // if last flush is still behind, increase it to current + interval + // if (Utils.TimeDiff(current, ts_flush) >= 0) // original kcp.c + if (current >= ts_flush) // less confusing + { + ts_flush = current + interval; + } + Flush(); + } + } + + // ikcp_check + // Determine when should you invoke update + // Returns when you should invoke update in millisec, if there is no + // input/send calling. you can call update in that time, instead of + // call update repeatly. + // + // Important to reduce unnecessary update invoking. use it to schedule + // update (e.g. implementing an epoll-like mechanism, or optimize update + // when handling massive kcp connections). + public uint Check(uint current_) + { + uint ts_flush_ = ts_flush; + // int tm_flush = 0x7fffffff; original kcp: useless assignment + int tm_packet = 0x7fffffff; + + if (!updated) + { + return current_; + } + + if (Utils.TimeDiff(current_, ts_flush_) >= 10000 || + Utils.TimeDiff(current_, ts_flush_) < -10000) + { + ts_flush_ = current_; + } + + if (Utils.TimeDiff(current_, ts_flush_) >= 0) + { + return current_; + } + + int tm_flush = Utils.TimeDiff(ts_flush_, current_); + + foreach (Segment seg in snd_buf) + { + int diff = Utils.TimeDiff(seg.resendts, current_); + if (diff <= 0) + { + return current_; + } + if (diff < tm_packet) tm_packet = diff; + } + + uint minimal = (uint)(tm_packet < tm_flush ? tm_packet : tm_flush); + if (minimal >= interval) minimal = interval; + + return current_ + minimal; + } + + // ikcp_setmtu + // Change MTU (Maximum Transmission Unit) size. + public void SetMtu(uint mtu) + { + if (mtu < 50 || mtu < OVERHEAD) + throw new ArgumentException("MTU must be higher than 50 and higher than OVERHEAD"); + + buffer = new byte[(mtu + OVERHEAD) * 3]; + this.mtu = mtu; + mss = mtu - OVERHEAD; + } + + // ikcp_interval + public void SetInterval(uint interval) + { + // clamp interval between 10 and 5000 + if (interval > 5000) interval = 5000; + else if (interval < 10) interval = 10; + this.interval = interval; + } + + // ikcp_nodelay + // configuration: https://github.com/skywind3000/kcp/blob/master/README.en.md#protocol-configuration + // nodelay : Whether nodelay mode is enabled, 0 is not enabled; 1 enabled. + // interval :Protocol internal work interval, in milliseconds, such as 10 ms or 20 ms. + // resend :Fast retransmission mode, 0 represents off by default, 2 can be set (2 ACK spans will result in direct retransmission) + // nc :Whether to turn off flow control, 0 represents “Do not turn off” by default, 1 represents “Turn off”. + // Normal Mode: ikcp_nodelay(kcp, 0, 40, 0, 0); + // Turbo Mode: ikcp_nodelay(kcp, 1, 10, 2, 1); + public void SetNoDelay(uint nodelay, uint interval = INTERVAL, int resend = 0, bool nocwnd = false) + { + this.nodelay = nodelay; + if (nodelay != 0) + { + rx_minrto = RTO_NDL; + } + else + { + rx_minrto = RTO_MIN; + } + + if (interval >= 0) + { + // clamp interval between 10 and 5000 + if (interval > 5000) interval = 5000; + else if (interval < 10) interval = 10; + this.interval = interval; + } + + if (resend >= 0) + { + fastresend = resend; + } + + this.nocwnd = nocwnd; + } + + // ikcp_wndsize + public void SetWindowSize(uint sendWindow, uint receiveWindow) + { + if (sendWindow > 0) + { + snd_wnd = sendWindow; + } + + if (receiveWindow > 0) + { + // must >= max fragment size + rcv_wnd = Math.Max(receiveWindow, WND_RCV); + } + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/Kcp.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Kcp.cs.meta new file mode 100644 index 0000000..935b423 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Kcp.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a59b1cae10a334faf807432ab472f212 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/Pool.cs b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Pool.cs new file mode 100644 index 0000000..81b5289 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Pool.cs @@ -0,0 +1,46 @@ +// Pool to avoid allocations (from libuv2k & Mirror) +using System; +using System.Collections.Generic; + +namespace kcp2k +{ + public class Pool + { + // Mirror is single threaded, no need for concurrent collections + readonly Stack objects = new Stack(); + + // some types might need additional parameters in their constructor, so + // we use a Func generator + readonly Func objectGenerator; + + // some types might need additional cleanup for returned objects + readonly Action objectResetter; + + public Pool(Func objectGenerator, Action objectResetter, int initialCapacity) + { + this.objectGenerator = objectGenerator; + this.objectResetter = objectResetter; + + // allocate an initial pool so we have fewer (if any) + // allocations in the first few frames (or seconds). + for (int i = 0; i < initialCapacity; ++i) + objects.Push(objectGenerator()); + } + + // take an element from the pool, or create a new one if empty + public T Take() => objects.Count > 0 ? objects.Pop() : objectGenerator(); + + // return an element to the pool + public void Return(T item) + { + objectResetter(item); + objects.Push(item); + } + + // clear the pool + public void Clear() => objects.Clear(); + + // count to see how many objects are in the pool. useful for tests. + public int Count => objects.Count; + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/Pool.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Pool.cs.meta new file mode 100644 index 0000000..5eba0e0 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Pool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 35c07818fc4784bb4ba472c8e5029002 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/Segment.cs b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Segment.cs new file mode 100644 index 0000000..d7e4131 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Segment.cs @@ -0,0 +1,78 @@ +using System.IO; + +namespace kcp2k +{ + // KCP Segment Definition + internal class Segment + { + internal uint conv; // conversation + internal uint cmd; // command, e.g. Kcp.CMD_ACK etc. + // fragment (sent as 1 byte). + // 0 if unfragmented, otherwise fragment numbers in reverse: N,..,32,1,0 + // this way the first received segment tells us how many fragments there are. + internal uint frg; + internal uint wnd; // window size that the receive can currently receive + internal uint ts; // timestamp + internal uint sn; // sequence number + internal uint una; + internal uint resendts; // resend timestamp + internal int rto; + internal uint fastack; + internal uint xmit; // retransmit count + + // we need an auto scaling byte[] with a WriteBytes function. + // MemoryStream does that perfectly, no need to reinvent the wheel. + // note: no need to pool it, because Segment is already pooled. + // -> default MTU as initial capacity to avoid most runtime resizing/allocations + // + // .data is only used for Encode(), which always fits it into a buffer. + // the buffer is always Kcp.buffer. Kcp ctor creates the buffer of size: + // (mtu + OVERHEAD) * 3 bytes. + // in other words, Encode only ever writes up to the above amount of bytes. + internal MemoryStream data = new MemoryStream(Kcp.MTU_DEF); + + // ikcp_encode_seg + // encode a segment into buffer. + // buffer is always Kcp.buffer. Kcp ctor creates the buffer of size: + // (mtu + OVERHEAD) * 3 bytes. + // in other words, Encode only ever writes up to the above amount of bytes. + internal int Encode(byte[] ptr, int offset) + { + int previousPosition = offset; + + offset += Utils.Encode32U(ptr, offset, conv); + offset += Utils.Encode8u(ptr, offset, (byte)cmd); + // IMPORTANT kcp encodes 'frg' as 1 byte. + // so we can only support up to 255 fragments. + // (which limits max message size to around 288 KB) + offset += Utils.Encode8u(ptr, offset, (byte)frg); + offset += Utils.Encode16U(ptr, offset, (ushort)wnd); + offset += Utils.Encode32U(ptr, offset, ts); + offset += Utils.Encode32U(ptr, offset, sn); + offset += Utils.Encode32U(ptr, offset, una); + offset += Utils.Encode32U(ptr, offset, (uint)data.Position); + + int written = offset - previousPosition; + return written; + } + + // reset to return a fresh segment to the pool + internal void Reset() + { + conv = 0; + cmd = 0; + frg = 0; + wnd = 0; + ts = 0; + sn = 0; + una = 0; + rto = 0; + xmit = 0; + resendts = 0; + fastack = 0; + + // keep buffer for next pool usage, but reset length (= bytes written) + data.SetLength(0); + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/Segment.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Segment.cs.meta new file mode 100644 index 0000000..d14dc1a --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Segment.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc58706a05dd3442c8fde858d5266855 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/Utils.cs b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Utils.cs new file mode 100644 index 0000000..2cb7462 --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Utils.cs @@ -0,0 +1,76 @@ +using System.Runtime.CompilerServices; + +namespace kcp2k +{ + public static partial class Utils + { + // Clamp so we don't have to depend on UnityEngine + public static int Clamp(int value, int min, int max) + { + if (value < min) return min; + if (value > max) return max; + return value; + } + + // encode 8 bits unsigned int + public static int Encode8u(byte[] p, int offset, byte value) + { + p[0 + offset] = value; + return 1; + } + + // decode 8 bits unsigned int + public static int Decode8u(byte[] p, int offset, out byte value) + { + value = p[0 + offset]; + return 1; + } + + // encode 16 bits unsigned int (lsb) + public static int Encode16U(byte[] p, int offset, ushort value) + { + p[0 + offset] = (byte)(value >> 0); + p[1 + offset] = (byte)(value >> 8); + return 2; + } + + // decode 16 bits unsigned int (lsb) + public static int Decode16U(byte[] p, int offset, out ushort value) + { + ushort result = 0; + result |= p[0 + offset]; + result |= (ushort)(p[1 + offset] << 8); + value = result; + return 2; + } + + // encode 32 bits unsigned int (lsb) + public static int Encode32U(byte[] p, int offset, uint value) + { + p[0 + offset] = (byte)(value >> 0); + p[1 + offset] = (byte)(value >> 8); + p[2 + offset] = (byte)(value >> 16); + p[3 + offset] = (byte)(value >> 24); + return 4; + } + + // decode 32 bits unsigned int (lsb) + public static int Decode32U(byte[] p, int offset, out uint value) + { + uint result = 0; + result |= p[0 + offset]; + result |= (uint)(p[1 + offset] << 8); + result |= (uint)(p[2 + offset] << 16); + result |= (uint)(p[3 + offset] << 24); + value = result; + return 4; + } + + // timediff was a macro in original Kcp. let's inline it if possible. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int TimeDiff(uint later, uint earlier) + { + return (int)(later - earlier); + } + } +} diff --git a/Assets/Mirror/Transports/KCP/kcp2k/kcp/Utils.cs.meta b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Utils.cs.meta new file mode 100644 index 0000000..86118bc --- /dev/null +++ b/Assets/Mirror/Transports/KCP/kcp2k/kcp/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef959eb716205bd48b050f010a9a35ae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Latency.meta b/Assets/Mirror/Transports/Latency.meta new file mode 100644 index 0000000..07d138e --- /dev/null +++ b/Assets/Mirror/Transports/Latency.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 397bb578e2bb049ebac1e29effa9d298 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Latency/LatencySimulation.cs b/Assets/Mirror/Transports/Latency/LatencySimulation.cs new file mode 100644 index 0000000..894d3fe --- /dev/null +++ b/Assets/Mirror/Transports/Latency/LatencySimulation.cs @@ -0,0 +1,323 @@ +// wraps around a transport and adds latency/loss/scramble simulation. +// +// reliable: latency +// unreliable: latency, loss, scramble (unreliable isn't ordered so we scramble) +// +// IMPORTANT: use Time.unscaledTime instead of Time.time. +// some games might have Time.timeScale modified. +// see also: https://github.com/vis2k/Mirror/issues/2907 +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; + +namespace Mirror +{ + struct QueuedMessage + { + public int connectionId; + public byte[] bytes; + public double time; + } + + [HelpURL("https://mirror-networking.gitbook.io/docs/transports/latency-simulaton-transport")] + [DisallowMultipleComponent] + public class LatencySimulation : Transport + { + public Transport wrap; + + [Header("Common")] + // latency always needs to be applied to both channels! + // fixes a bug in prediction where predictedTime would have no latency, but [Command]s would have 100ms latency resulting in heavy, hard to debug jittering! + // in real world, all UDP channels go over the same socket connection with the same latency. + [Tooltip("Latency in milliseconds (1000 = 1 second). Always applied to both reliable and unreliable, otherwise unreliable NetworkTime may be behind reliable [SyncVars/Commands/Rpcs] or vice versa!")] + [Range(0, 10000)] public float latency = 100; + + [Tooltip("Jitter latency via perlin(Time * jitterSpeed) * jitter")] + [FormerlySerializedAs("latencySpikeMultiplier")] + [Range(0, 1)] public float jitter = 0.02f; + + [Tooltip("Jitter latency via perlin(Time * jitterSpeed) * jitter")] + [FormerlySerializedAs("latencySpikeSpeedMultiplier")] + public float jitterSpeed = 1; + + [Header("Reliable Messages")] + // note: packet loss over reliable manifests itself in latency. + // don't need (and can't add) a loss option here. + // note: reliable is ordered by definition. no need to scramble. + + [Header("Unreliable Messages")] + [Tooltip("Packet loss in %\n2% recommended for long term play testing, upto 5% for short bursts.\nAnything higher, or for a prolonged amount of time, suggests user has a connection fault.")] + [Range(0, 100)] public float unreliableLoss = 2; + + [Tooltip("Scramble % of unreliable messages, just like over the real network. Mirror unreliable is unordered.")] + [Range(0, 100)] public float unreliableScramble = 2; + + // message queues + // list so we can insert randomly (scramble) + readonly List reliableClientToServer = new List(); + readonly List reliableServerToClient = new List(); + readonly List unreliableClientToServer = new List(); + readonly List unreliableServerToClient = new List(); + + // random + // UnityEngine.Random.value is [0, 1] with both upper and lower bounds inclusive + // but we need the upper bound to be exclusive, so using System.Random instead. + // => NextDouble() is NEVER < 0 so loss=0 never drops! + // => NextDouble() is ALWAYS < 1 so loss=1 always drops! + readonly System.Random random = new System.Random(); + + public void Awake() + { + if (wrap == null) + throw new Exception("LatencySimulationTransport requires an underlying transport to wrap around."); + } + + // forward enable/disable to the wrapped transport + void OnEnable() { wrap.enabled = true; } + void OnDisable() { wrap.enabled = false; } + + // noise function can be replaced if needed + protected virtual float Noise(float time) => Mathf.PerlinNoise(time, time); + + // helper function to simulate latency + float SimulateLatency(int channeldId) + { + // spike over perlin noise. + // no spikes isn't realistic. + // sin is too predictable / no realistic. + // perlin is still deterministic and random enough. +#if !UNITY_2020_3_OR_NEWER + float spike = Noise((float)NetworkTime.localTime * jitterSpeed) * jitter; +#else + float spike = Noise((float)Time.unscaledTimeAsDouble * jitterSpeed) * jitter; +#endif + + // base latency + switch (channeldId) + { + case Channels.Reliable: + return latency/1000 + spike; + case Channels.Unreliable: + return latency/1000 + spike; + default: + return 0; + } + } + + // helper function to simulate a send with latency/loss/scramble + void SimulateSend( + int connectionId, + ArraySegment segment, + int channelId, + float latency, + List reliableQueue, + List unreliableQueue) + { + // segment is only valid after returning. copy it. + // (allocates for now. it's only for testing anyway.) + byte[] bytes = new byte[segment.Count]; + Buffer.BlockCopy(segment.Array, segment.Offset, bytes, 0, segment.Count); + + // enqueue message. send after latency interval. + QueuedMessage message = new QueuedMessage + { + connectionId = connectionId, + bytes = bytes, +#if !UNITY_2020_3_OR_NEWER + time = NetworkTime.localTime + latency +#else + time = Time.unscaledTimeAsDouble + latency +#endif + }; + + switch (channelId) + { + case Channels.Reliable: + // simulate latency + reliableQueue.Add(message); + break; + case Channels.Unreliable: + // simulate packet loss + bool drop = random.NextDouble() < unreliableLoss/100; + if (!drop) + { + // simulate scramble (Random.Next is < max, so +1) + bool scramble = random.NextDouble() < unreliableScramble/100; + int last = unreliableQueue.Count; + int index = scramble ? random.Next(0, last + 1) : last; + + // simulate latency + unreliableQueue.Insert(index, message); + } + break; + default: + Debug.LogError($"{nameof(LatencySimulation)} unexpected channelId: {channelId}"); + break; + } + } + + public override bool Available() => wrap.Available(); + + public override void ClientConnect(string address) + { + wrap.OnClientConnected = OnClientConnected; + wrap.OnClientDataReceived = OnClientDataReceived; + wrap.OnClientError = OnClientError; + wrap.OnClientDisconnected = OnClientDisconnected; + wrap.ClientConnect(address); + } + + public override void ClientConnect(Uri uri) + { + wrap.OnClientConnected = OnClientConnected; + wrap.OnClientDataReceived = OnClientDataReceived; + wrap.OnClientError = OnClientError; + wrap.OnClientDisconnected = OnClientDisconnected; + wrap.ClientConnect(uri); + } + + public override bool ClientConnected() => wrap.ClientConnected(); + + public override void ClientDisconnect() + { + wrap.ClientDisconnect(); + reliableClientToServer.Clear(); + unreliableClientToServer.Clear(); + } + + public override void ClientSend(ArraySegment segment, int channelId) + { + float latency = SimulateLatency(channelId); + SimulateSend(0, segment, channelId, latency, reliableClientToServer, unreliableClientToServer); + } + + public override Uri ServerUri() => wrap.ServerUri(); + + public override bool ServerActive() => wrap.ServerActive(); + + public override string ServerGetClientAddress(int connectionId) => wrap.ServerGetClientAddress(connectionId); + + public override void ServerDisconnect(int connectionId) => wrap.ServerDisconnect(connectionId); + + public override void ServerSend(int connectionId, ArraySegment segment, int channelId) + { + float latency = SimulateLatency(channelId); + SimulateSend(connectionId, segment, channelId, latency, reliableServerToClient, unreliableServerToClient); + } + + public override void ServerStart() + { + wrap.OnServerConnected = OnServerConnected; + wrap.OnServerDataReceived = OnServerDataReceived; + wrap.OnServerError = OnServerError; + wrap.OnServerDisconnected = OnServerDisconnected; + wrap.ServerStart(); + } + + public override void ServerStop() + { + wrap.ServerStop(); + reliableServerToClient.Clear(); + unreliableServerToClient.Clear(); + } + + public override void ClientEarlyUpdate() => wrap.ClientEarlyUpdate(); + public override void ServerEarlyUpdate() => wrap.ServerEarlyUpdate(); + public override void ClientLateUpdate() + { + // flush reliable messages after latency. + // need to iterate all, since queue isn't a sortedlist. + for (int i = 0; i < reliableClientToServer.Count; ++i) + { + // message ready to be sent? + QueuedMessage message = reliableClientToServer[i]; +#if !UNITY_2020_3_OR_NEWER + if (message.time <= NetworkTime.localTime) +#else + if (message.time <= Time.unscaledTimeAsDouble) +#endif + { + // send and eat + wrap.ClientSend(new ArraySegment(message.bytes), Channels.Reliable); + reliableClientToServer.RemoveAt(i); + --i; + } + } + + // flush unreliable messages after latency. + // need to iterate all, since queue isn't a sortedlist. + for (int i = 0; i < unreliableClientToServer.Count; ++i) + { + // message ready to be sent? + QueuedMessage message = unreliableClientToServer[i]; +#if !UNITY_2020_3_OR_NEWER + if (message.time <= NetworkTime.localTime) +#else + if (message.time <= Time.unscaledTimeAsDouble) +#endif + { + // send and eat + wrap.ClientSend(new ArraySegment(message.bytes), Channels.Reliable); + unreliableClientToServer.RemoveAt(i); + --i; + } + } + + // update wrapped transport too + wrap.ClientLateUpdate(); + } + public override void ServerLateUpdate() + { + + // flush reliable messages after latency. + // need to iterate all, since queue isn't a sortedlist. + for (int i = 0; i < reliableServerToClient.Count; ++i) + { + // message ready to be sent? + QueuedMessage message = reliableServerToClient[i]; +#if !UNITY_2020_3_OR_NEWER + if (message.time <= NetworkTime.localTime) +#else + if (message.time <= Time.unscaledTimeAsDouble) +#endif + { + // send and eat + wrap.ServerSend(message.connectionId, new ArraySegment(message.bytes), Channels.Reliable); + reliableServerToClient.RemoveAt(i); + --i; + } + } + + + // flush unreliable messages after latency. + // need to iterate all, since queue isn't a sortedlist. + for (int i = 0; i < unreliableServerToClient.Count; ++i) + { + // message ready to be sent? + QueuedMessage message = unreliableServerToClient[i]; +#if !UNITY_2020_3_OR_NEWER + if (message.time <= NetworkTime.localTime) +#else + if (message.time <= Time.unscaledTimeAsDouble) +#endif + { + // send and eat + wrap.ServerSend(message.connectionId, new ArraySegment(message.bytes), Channels.Reliable); + unreliableServerToClient.RemoveAt(i); + --i; + } + } + + // update wrapped transport too + wrap.ServerLateUpdate(); + } + + public override int GetBatchThreshold(int channelId) => wrap.GetBatchThreshold(channelId); + public override int GetMaxPacketSize(int channelId = 0) => wrap.GetMaxPacketSize(channelId); + + public override void Shutdown() => wrap.Shutdown(); + + public override string ToString() => $"{nameof(LatencySimulation)} {wrap}"; + } +} diff --git a/Assets/Mirror/Transports/Latency/LatencySimulation.cs.meta b/Assets/Mirror/Transports/Latency/LatencySimulation.cs.meta new file mode 100644 index 0000000..eabbe4a --- /dev/null +++ b/Assets/Mirror/Transports/Latency/LatencySimulation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 96b149f511061407fb54895c057b7736 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Middleware.meta b/Assets/Mirror/Transports/Middleware.meta new file mode 100644 index 0000000..3038832 --- /dev/null +++ b/Assets/Mirror/Transports/Middleware.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 69344c174fdaf432e9ff0cdaf2e2ba21 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Middleware/MiddlewareTransport.cs b/Assets/Mirror/Transports/Middleware/MiddlewareTransport.cs new file mode 100644 index 0000000..7dd934a --- /dev/null +++ b/Assets/Mirror/Transports/Middleware/MiddlewareTransport.cs @@ -0,0 +1,61 @@ +using System; +using UnityEngine; + +namespace Mirror +{ + /// + /// Allows Middleware to override some of the transport methods or let the inner transport handle them. + /// + [DisallowMultipleComponent] + public abstract class MiddlewareTransport : Transport + { + /// + /// Transport to call to after middleware + /// + public Transport inner; + + public override bool Available() => inner.Available(); + public override int GetMaxPacketSize(int channelId = 0) => inner.GetMaxPacketSize(channelId); + public override int GetBatchThreshold(int channelId = Channels.Reliable) => inner.GetBatchThreshold(channelId); + public override void Shutdown() => inner.Shutdown(); + + #region Client + public override void ClientConnect(string address) + { + inner.OnClientConnected = OnClientConnected; + inner.OnClientDataReceived = OnClientDataReceived; + inner.OnClientDisconnected = OnClientDisconnected; + inner.OnClientError = OnClientError; + inner.ClientConnect(address); + } + + public override bool ClientConnected() => inner.ClientConnected(); + public override void ClientDisconnect() => inner.ClientDisconnect(); + public override void ClientSend(ArraySegment segment, int channelId) => inner.ClientSend(segment, channelId); + + public override void ClientEarlyUpdate() => inner.ClientEarlyUpdate(); + public override void ClientLateUpdate() => inner.ClientLateUpdate(); + #endregion + + #region Server + public override bool ServerActive() => inner.ServerActive(); + public override void ServerStart() + { + inner.OnServerConnected = OnServerConnected; + inner.OnServerDataReceived = OnServerDataReceived; + inner.OnServerDisconnected = OnServerDisconnected; + inner.OnServerError = OnServerError; + inner.ServerStart(); + } + + public override void ServerStop() => inner.ServerStop(); + public override void ServerSend(int connectionId, ArraySegment segment, int channelId) => inner.ServerSend(connectionId, segment, channelId); + public override void ServerDisconnect(int connectionId) => inner.ServerDisconnect(connectionId); + public override string ServerGetClientAddress(int connectionId) => inner.ServerGetClientAddress(connectionId); + public override Uri ServerUri() => inner.ServerUri(); + + public override void ServerEarlyUpdate() => inner.ServerEarlyUpdate(); + public override void ServerLateUpdate() => inner.ServerLateUpdate(); + #endregion + } +} diff --git a/Assets/Mirror/Transports/Middleware/MiddlewareTransport.cs.meta b/Assets/Mirror/Transports/Middleware/MiddlewareTransport.cs.meta new file mode 100644 index 0000000..dce8378 --- /dev/null +++ b/Assets/Mirror/Transports/Middleware/MiddlewareTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46f20ede74658e147a1af57172710de2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Mirror.Transports.asmdef b/Assets/Mirror/Transports/Mirror.Transports.asmdef new file mode 100644 index 0000000..3a67a0a --- /dev/null +++ b/Assets/Mirror/Transports/Mirror.Transports.asmdef @@ -0,0 +1,19 @@ +{ + "name": "Mirror.Transports", + "rootNamespace": "", + "references": [ + "GUID:30817c1a0e6d646d99c048fc403f5979", + "GUID:6806a62c384838046a3c66c44f06d75f", + "GUID:725ee7191c021de4dbf9269590ded755", + "GUID:3b5390adca4e2bb4791cb930316d6f3e" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Mirror.Transports.asmdef.meta b/Assets/Mirror/Transports/Mirror.Transports.asmdef.meta new file mode 100644 index 0000000..d180ef1 --- /dev/null +++ b/Assets/Mirror/Transports/Mirror.Transports.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 627104647b9c04b4ebb8978a92ecac63 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Multiplex.meta b/Assets/Mirror/Transports/Multiplex.meta new file mode 100644 index 0000000..59c257e --- /dev/null +++ b/Assets/Mirror/Transports/Multiplex.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 28d5150129fea43048bbdd23ea6e2446 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Multiplex/MultiplexTransport.cs b/Assets/Mirror/Transports/Multiplex/MultiplexTransport.cs new file mode 100644 index 0000000..3ef97d7 --- /dev/null +++ b/Assets/Mirror/Transports/Multiplex/MultiplexTransport.cs @@ -0,0 +1,440 @@ +using System; +using System.Collections.Generic; +using System.Text; +using UnityEngine; + +namespace Mirror +{ + // a transport that can listen to multiple underlying transport at the same time + [DisallowMultipleComponent] + public class MultiplexTransport : Transport, PortTransport + { + public Transport[] transports; + + Transport available; + + // underlying transport connectionId to multiplexed connectionId lookup. + // + // originally we used a formula to map the connectionId: + // connectionId * transportAmount + transportId + // + // if we have 3 transports, then + // transport 0 will produce connection ids [0, 3, 6, 9, ...] + // transport 1 will produce connection ids [1, 4, 7, 10, ...] + // transport 2 will produce connection ids [2, 5, 8, 11, ...] + // + // however, some transports like kcp may give very large connectionIds. + // if they are near int.max, then "* transprotAmount + transportIndex" + // will overflow, resulting in connIds which can't be projected back. + // https://github.com/vis2k/Mirror/issues/3280 + // + // instead, use a simple lookup with 0-indexed ids. + // with initial capacity to avoid runtime allocations. + + // (original connectionId, transport#) to multiplexed connectionId + readonly Dictionary, int> originalToMultiplexedId = + new Dictionary, int>(100); + + // multiplexed connectionId to (original connectionId, transport#) + readonly Dictionary> multiplexedToOriginalId = + new Dictionary>(100); + + // next multiplexed id counter. start at 1 because 0 is reserved for host. + int nextMultiplexedId = 1; + + // prevent log flood from OnGUI or similar per-frame updates + bool alreadyWarned; + + public ushort Port + { + get + { + foreach (Transport transport in transports) + if (transport.Available() && transport is PortTransport portTransport) + return portTransport.Port; + + return 0; + } + set + { + if (Utils.IsHeadless() && !alreadyWarned) + { + // prevent log flood from OnGUI or similar per-frame updates + alreadyWarned = true; + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"[Multiplexer] Server cannot set the same listen port for all transports! Set them directly instead."); + Console.ResetColor(); + } + else + { + // We can't set the same port for all transports because + // listen ports have to be different for each transport + // so we just set the first available one. + // This depends on the selected build platform. + foreach (Transport transport in transports) + if (transport.Available() && transport is PortTransport portTransport) + { + portTransport.Port = value; + break; + } + } + } + } + + // add to bidirection lookup. returns the multiplexed connectionId. + public int AddToLookup(int originalConnectionId, int transportIndex) + { + // add to both + KeyValuePair pair = new KeyValuePair(originalConnectionId, transportIndex); + int multiplexedId = nextMultiplexedId++; + + originalToMultiplexedId[pair] = multiplexedId; + multiplexedToOriginalId[multiplexedId] = pair; + + return multiplexedId; + } + + public void RemoveFromLookup(int originalConnectionId, int transportIndex) + { + // remove from both + KeyValuePair pair = new KeyValuePair(originalConnectionId, transportIndex); + if (originalToMultiplexedId.TryGetValue(pair, out int multiplexedId)) + { + originalToMultiplexedId.Remove(pair); + multiplexedToOriginalId.Remove(multiplexedId); + } + } + + public bool OriginalId(int multiplexId, out int originalConnectionId, out int transportIndex) + { + if (!multiplexedToOriginalId.ContainsKey(multiplexId)) + { + originalConnectionId = 0; + transportIndex = 0; + return false; + } + + KeyValuePair pair = multiplexedToOriginalId[multiplexId]; + originalConnectionId = pair.Key; + transportIndex = pair.Value; + return true; + } + + public int MultiplexId(int originalConnectionId, int transportIndex) + { + KeyValuePair pair = new KeyValuePair(originalConnectionId, transportIndex); + if (originalToMultiplexedId.TryGetValue(pair, out int multiplexedId)) + return multiplexedId; + else + return 0; + } + + //////////////////////////////////////////////////////////////////////// + + public void Awake() + { + if (transports == null || transports.Length == 0) + { + Debug.LogError("[Multiplexer] Multiplex transport requires at least 1 underlying transport"); + } + } + + public override void ClientEarlyUpdate() + { + foreach (Transport transport in transports) + transport.ClientEarlyUpdate(); + } + + public override void ServerEarlyUpdate() + { + foreach (Transport transport in transports) + transport.ServerEarlyUpdate(); + } + + public override void ClientLateUpdate() + { + foreach (Transport transport in transports) + transport.ClientLateUpdate(); + } + + public override void ServerLateUpdate() + { + foreach (Transport transport in transports) + transport.ServerLateUpdate(); + } + + void OnEnable() + { + foreach (Transport transport in transports) + transport.enabled = true; + } + + void OnDisable() + { + foreach (Transport transport in transports) + transport.enabled = false; + } + + public override bool Available() + { + // available if any of the transports is available + foreach (Transport transport in transports) + if (transport.Available()) + return true; + + return false; + } + + #region Client + + public override void ClientConnect(string address) + { + foreach (Transport transport in transports) + { + if (transport.Available()) + { + available = transport; + transport.OnClientConnected = OnClientConnected; + transport.OnClientDataReceived = OnClientDataReceived; + transport.OnClientError = OnClientError; + transport.OnClientDisconnected = OnClientDisconnected; + transport.ClientConnect(address); + return; + } + } + throw new ArgumentException("[Multiplexer] No transport suitable for this platform"); + } + + public override void ClientConnect(Uri uri) + { + foreach (Transport transport in transports) + { + if (transport.Available()) + { + try + { + available = transport; + transport.OnClientConnected = OnClientConnected; + transport.OnClientDataReceived = OnClientDataReceived; + transport.OnClientError = OnClientError; + transport.OnClientDisconnected = OnClientDisconnected; + transport.ClientConnect(uri); + return; + } + catch (ArgumentException) + { + // transport does not support the schema, just move on to the next one + } + } + } + throw new ArgumentException("[Multiplexer] No transport suitable for this platform"); + } + + public override bool ClientConnected() + { + return (object)available != null && available.ClientConnected(); + } + + public override void ClientDisconnect() + { + if ((object)available != null) + available.ClientDisconnect(); + } + + public override void ClientSend(ArraySegment segment, int channelId) + { + available.ClientSend(segment, channelId); + } + + #endregion + + #region Server + void AddServerCallbacks() + { + // all underlying transports should call the multiplex transport's events + for (int i = 0; i < transports.Length; i++) + { + // this is required for the handlers, if I use i directly + // then all the handlers will use the last i + int transportIndex = i; + Transport transport = transports[i]; + + transport.OnServerConnected = (originalConnectionId => + { + // invoke Multiplex event with multiplexed connectionId + int multiplexedId = AddToLookup(originalConnectionId, transportIndex); + OnServerConnected.Invoke(multiplexedId); + }); + + transport.OnServerDataReceived = (originalConnectionId, data, channel) => + { + // invoke Multiplex event with multiplexed connectionId + int multiplexedId = MultiplexId(originalConnectionId, transportIndex); + if (multiplexedId == 0) + { + if (Utils.IsHeadless()) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"[Multiplexer] Received data for unknown connectionId={originalConnectionId} on transport={transportIndex}"); + Console.ResetColor(); + } + else + Debug.LogWarning($"[Multiplexer] Received data for unknown connectionId={originalConnectionId} on transport={transportIndex}"); + + return; + } + OnServerDataReceived.Invoke(multiplexedId, data, channel); + }; + + transport.OnServerError = (originalConnectionId, error, reason) => + { + // invoke Multiplex event with multiplexed connectionId + int multiplexedId = MultiplexId(originalConnectionId, transportIndex); + if (multiplexedId == 0) + { + if (Utils.IsHeadless()) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"[Multiplexer] Received error for unknown connectionId={originalConnectionId} on transport={transportIndex}"); + Console.ResetColor(); + } + else + Debug.LogError($"[Multiplexer] Received error for unknown connectionId={originalConnectionId} on transport={transportIndex}"); + + return; + } + OnServerError.Invoke(multiplexedId, error, reason); + }; + + transport.OnServerDisconnected = originalConnectionId => + { + // invoke Multiplex event with multiplexed connectionId + int multiplexedId = MultiplexId(originalConnectionId, transportIndex); + if (multiplexedId == 0) + { + if (Utils.IsHeadless()) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"[Multiplexer] Received disconnect for unknown connectionId={originalConnectionId} on transport={transportIndex}"); + Console.ResetColor(); + } + else + Debug.LogWarning($"[Multiplexer] Received disconnect for unknown connectionId={originalConnectionId} on transport={transportIndex}"); + + return; + } + OnServerDisconnected.Invoke(multiplexedId); + RemoveFromLookup(originalConnectionId, transportIndex); + }; + } + } + + // for now returns the first uri, + // should we return all available uris? + public override Uri ServerUri() => + transports[0].ServerUri(); + + public override bool ServerActive() + { + // avoid Linq.All allocations + foreach (Transport transport in transports) + if (!transport.ServerActive()) + return false; + + return true; + } + + public override string ServerGetClientAddress(int connectionId) + { + // convert multiplexed connectionId to original id & transport index + if (OriginalId(connectionId, out int originalConnectionId, out int transportIndex)) + return transports[transportIndex].ServerGetClientAddress(originalConnectionId); + else + return ""; + } + + public override void ServerDisconnect(int connectionId) + { + // convert multiplexed connectionId to original id & transport index + if (OriginalId(connectionId, out int originalConnectionId, out int transportIndex)) + transports[transportIndex].ServerDisconnect(originalConnectionId); + } + + public override void ServerSend(int connectionId, ArraySegment segment, int channelId) + { + // convert multiplexed connectionId to original transport + connId + if (OriginalId(connectionId, out int originalConnectionId, out int transportIndex)) + transports[transportIndex].ServerSend(originalConnectionId, segment, channelId); + } + + public override void ServerStart() + { + AddServerCallbacks(); + + foreach (Transport transport in transports) + { + transport.ServerStart(); + + if (transport is PortTransport portTransport) + { + if (Utils.IsHeadless()) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine($"[Multiplexer]: Server listening on port {portTransport.Port} with {transport}"); + Console.ResetColor(); + } + else + { + Debug.Log($"[Multiplexer]: Server listening on port {portTransport.Port} with {transport}"); + } + } + } + } + + public override void ServerStop() + { + foreach (Transport transport in transports) + transport.ServerStop(); + } + #endregion + + public override int GetMaxPacketSize(int channelId = 0) + { + // finding the max packet size in a multiplex environment has to be + // done very carefully: + // * servers run multiple transports at the same time + // * different clients run different transports + // * there should only ever be ONE true max packet size for everyone, + // otherwise a spawn message might be sent to all tcp sockets, but + // be too big for some udp sockets. that would be a debugging + // nightmare and allow for possible exploits and players on + // different platforms seeing a different game state. + // => the safest solution is to use the smallest max size for all + // transports. that will never fail. + int mininumAllowedSize = int.MaxValue; + foreach (Transport transport in transports) + { + int size = transport.GetMaxPacketSize(channelId); + mininumAllowedSize = Mathf.Min(size, mininumAllowedSize); + } + return mininumAllowedSize; + } + + public override void Shutdown() + { + foreach (Transport transport in transports) + transport.Shutdown(); + } + + public override string ToString() + { + StringBuilder builder = new StringBuilder(); + builder.Append("Multiplexer:"); + + foreach (Transport transport in transports) + builder.Append($" {transport}"); + + return builder.ToString().Trim(); + } + } +} diff --git a/Assets/Mirror/Transports/Multiplex/MultiplexTransport.cs.meta b/Assets/Mirror/Transports/Multiplex/MultiplexTransport.cs.meta new file mode 100644 index 0000000..6e97b28 --- /dev/null +++ b/Assets/Mirror/Transports/Multiplex/MultiplexTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 929e3234c7db540b899f00183fc2b1fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb.meta b/Assets/Mirror/Transports/SimpleWeb.meta new file mode 100644 index 0000000..5baa80f --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3ba68af305d809418d6c6a804939290 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/Editor.meta b/Assets/Mirror/Transports/SimpleWeb/Editor.meta new file mode 100644 index 0000000..0ffdb34 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a7a134b4d9eef45239a2d7caf7f52c3e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/Editor/ClientWebsocketSettingsDrawer.cs b/Assets/Mirror/Transports/SimpleWeb/Editor/ClientWebsocketSettingsDrawer.cs new file mode 100644 index 0000000..9857dda --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/Editor/ClientWebsocketSettingsDrawer.cs @@ -0,0 +1,71 @@ +using UnityEditor; +using UnityEngine; + +namespace Mirror.SimpleWeb.Editor +{ +#if UNITY_EDITOR + [CustomPropertyDrawer(typeof(ClientWebsocketSettings))] + public class ClientWebsocketSettingsDrawer : PropertyDrawer + { + readonly string websocketPortOptionName = nameof(ClientWebsocketSettings.ClientPortOption); + readonly string customPortName = nameof(ClientWebsocketSettings.CustomClientPort); + readonly GUIContent portOptionLabel = new GUIContent("Client Port Option", + "Specify what port the client websocket connection uses (default same as server port)"); + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + property.isExpanded = true; + return SumPropertyHeights(property, websocketPortOptionName, customPortName); + } + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + DrawPortSettings(position, property); + } + + void DrawPortSettings(Rect position, SerializedProperty property) + { + SerializedProperty portOptionProp = property.FindPropertyRelative(websocketPortOptionName); + SerializedProperty portProp = property.FindPropertyRelative(customPortName); + float portOptionHeight = EditorGUI.GetPropertyHeight(portOptionProp); + float portHeight = EditorGUI.GetPropertyHeight(portProp); + float spacing = EditorGUIUtility.standardVerticalSpacing; + bool wasEnabled = GUI.enabled; + + position.height = portOptionHeight; + + EditorGUI.PropertyField(position, portOptionProp, portOptionLabel); + position.y += spacing + portOptionHeight; + position.height = portHeight; + + WebsocketPortOption portOption = (WebsocketPortOption)portOptionProp.enumValueIndex; + if (portOption == WebsocketPortOption.MatchWebpageProtocol || portOption == WebsocketPortOption.DefaultSameAsServer) + { + int port = 0; + if (property.serializedObject.targetObject is SimpleWebTransport swt) + if (portOption == WebsocketPortOption.MatchWebpageProtocol) + port = swt.clientUseWss ? 443 : 80; + else + port = swt.port; + + GUI.enabled = false; + EditorGUI.IntField(position, new GUIContent("Client Port"), port); + GUI.enabled = wasEnabled; + } + else + EditorGUI.PropertyField(position, portProp); + + position.y += spacing + portHeight; + } + + float SumPropertyHeights(SerializedProperty property, params string[] propertyNames) + { + float totalHeight = 0; + foreach (var name in propertyNames) + totalHeight += EditorGUI.GetPropertyHeight(property.FindPropertyRelative(name)) + EditorGUIUtility.standardVerticalSpacing; + + return totalHeight; + } + } +#endif +} diff --git a/Assets/Mirror/Transports/SimpleWeb/Editor/ClientWebsocketSettingsDrawer.cs.meta b/Assets/Mirror/Transports/SimpleWeb/Editor/ClientWebsocketSettingsDrawer.cs.meta new file mode 100644 index 0000000..fdbba6d --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/Editor/ClientWebsocketSettingsDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2d0e5b00ac8e45c99e68ad95cf843f80 +timeCreated: 1700081340 \ No newline at end of file diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb.meta new file mode 100644 index 0000000..c2852a8 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8ae237a052b29fc4b8d000f48e545bb7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/AssemblyInfo.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/AssemblyInfo.cs new file mode 100644 index 0000000..c0df7fe --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/AssemblyInfo.cs @@ -0,0 +1,7 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyVersion("1.6.0")] + +[assembly: InternalsVisibleTo("SimpleWebTransport.Tests.Runtime")] +[assembly: InternalsVisibleTo("SimpleWebTransport.Tests.Editor")] diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/AssemblyInfo.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/AssemblyInfo.cs.meta new file mode 100644 index 0000000..028a307 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee9e76201f7665244bd6ab8ea343a83f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/CHANGELOG.md b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/CHANGELOG.md new file mode 100644 index 0000000..d98f014 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/CHANGELOG.md @@ -0,0 +1,48 @@ +# [1.3.0](https://github.com/James-Frowen/SimpleWebTransport/compare/v1.2.7...v1.3.0) (2022-02-12) + + +### Features + +* Allowing max message size to be increase to int32.max ([#2](https://github.com/James-Frowen/SimpleWebTransport/issues/2)) ([4cc60fd](https://github.com/James-Frowen/SimpleWebTransport/commit/4cc60fd67f3c65d90ced0e6f9f97d15d0368076d)) + +## [1.2.7](https://github.com/James-Frowen/SimpleWebTransport/compare/v1.2.6...v1.2.7) (2022-02-12) + + +### Bug Fixes + +* fixing ObjectDisposedException in toString ([426de52](https://github.com/James-Frowen/SimpleWebTransport/commit/426de52ee4e98ac6212713b2b2272e3affb8fc99)) + +## [1.2.6](https://github.com/James-Frowen/SimpleWebTransport/compare/v1.2.5...v1.2.6) (2022-02-02) + + +### Bug Fixes + +* fixing Runtime is not defined for unity 2021 ([945b50d](https://github.com/James-Frowen/SimpleWebTransport/commit/945b50dbad5b71c43e2bdaa4033f87d3f62c5572)) + +## [1.2.5](https://github.com/James-Frowen/SimpleWebTransport/compare/v1.2.4...v1.2.5) (2022-02-02) + + +### Bug Fixes + +* updating Pointer_stringify to UTF8ToString ([2f5a74b](https://github.com/James-Frowen/SimpleWebTransport/commit/2f5a74ba10865e934be8d3b54ebfdeb14ca491f6)) + +## [1.2.4](https://github.com/James-Frowen/SimpleWebTransport/compare/v1.2.3...v1.2.4) (2021-12-16) + + +### Bug Fixes + +* adding meta file for changelog ([ba5b164](https://github.com/James-Frowen/SimpleWebTransport/commit/ba5b1647aa5cc69ca80f5b52c542a9b5ee749c7f)) + +## [1.2.3](https://github.com/James-Frowen/SimpleWebTransport/compare/v1.2.2...v1.2.3) (2021-12-16) + + +### Bug Fixes + +* fixing compile error in assemblyInfo ([7ee8380](https://github.com/James-Frowen/SimpleWebTransport/commit/7ee8380b4daf34d4e12017de55d8be481690046f)) + +## [1.2.2](https://github.com/James-Frowen/SimpleWebTransport/compare/v1.2.1...v1.2.2) (2021-12-16) + + +### Bug Fixes + +* fixing release with empty commit ([068af74](https://github.com/James-Frowen/SimpleWebTransport/commit/068af74f7399354081f25181f90fb060b0fa1524)) diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/CHANGELOG.md.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/CHANGELOG.md.meta new file mode 100644 index 0000000..bc43099 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/CHANGELOG.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b0ef23ac1c6a62546bbad5529b3bfdad +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client.meta new file mode 100644 index 0000000..e6e2943 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5faa957b8d9fc314ab7596ccf14750d9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/ClientWebsocketSettings.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/ClientWebsocketSettings.cs new file mode 100644 index 0000000..50ce331 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/ClientWebsocketSettings.cs @@ -0,0 +1,17 @@ +using System; + +namespace Mirror.SimpleWeb +{ + [Serializable] + public struct ClientWebsocketSettings + { + public WebsocketPortOption ClientPortOption; + public ushort CustomClientPort; + } + public enum WebsocketPortOption + { + DefaultSameAsServer, + MatchWebpageProtocol, + SpecifyPort + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/ClientWebsocketSettings.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/ClientWebsocketSettings.cs.meta new file mode 100644 index 0000000..9d81fd6 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/ClientWebsocketSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 20ed869c5ba54a56b750ac9e82be069f +timeCreated: 1700425326 \ No newline at end of file diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/SimpleWebClient.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/SimpleWebClient.cs new file mode 100644 index 0000000..5fe02d2 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/SimpleWebClient.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Concurrent; +using UnityEngine; + +namespace Mirror.SimpleWeb +{ + public enum ClientState + { + NotConnected = 0, + Connecting = 1, + Connected = 2, + Disconnecting = 3, + } + + /// + /// Client used to control websockets + /// Base class used by WebSocketClientWebGl and WebSocketClientStandAlone + /// + public abstract class SimpleWebClient + { + readonly int maxMessagesPerTick; + + protected ClientState state; + protected readonly int maxMessageSize; + protected readonly BufferPool bufferPool; + + public readonly ConcurrentQueue receiveQueue = new ConcurrentQueue(); + + public ClientState ConnectionState => state; + + public event Action onConnect; + public event Action onDisconnect; + public event Action> onData; + public event Action onError; + + public abstract void Connect(Uri serverAddress); + public abstract void Disconnect(); + public abstract void Send(ArraySegment segment); + + public static SimpleWebClient Create(int maxMessageSize, int maxMessagesPerTick, TcpConfig tcpConfig) + { +#if UNITY_WEBGL && !UNITY_EDITOR + return new WebSocketClientWebGl(maxMessageSize, maxMessagesPerTick); +#else + return new WebSocketClientStandAlone(maxMessageSize, maxMessagesPerTick, tcpConfig); +#endif + } + + protected SimpleWebClient(int maxMessageSize, int maxMessagesPerTick) + { + this.maxMessageSize = maxMessageSize; + this.maxMessagesPerTick = maxMessagesPerTick; + bufferPool = new BufferPool(5, 20, maxMessageSize); + } + + /// + /// Processes all new messages + /// + public void ProcessMessageQueue() + { + ProcessMessageQueue(null); + } + + /// + /// Processes all messages while is enabled + /// + /// + public void ProcessMessageQueue(MonoBehaviour behaviour) + { + int processedCount = 0; + bool skipEnabled = behaviour == null; + // check enabled every time in case behaviour was disabled after data + while ( + (skipEnabled || behaviour.enabled) && + processedCount < maxMessagesPerTick && + // Dequeue last + receiveQueue.TryDequeue(out Message next) + ) + { + processedCount++; + + switch (next.type) + { + case EventType.Connected: + onConnect?.Invoke(); + break; + case EventType.Data: + onData?.Invoke(next.data.ToSegment()); + next.data.Release(); + break; + case EventType.Disconnected: + onDisconnect?.Invoke(); + break; + case EventType.Error: + onError?.Invoke(next.exception); + break; + } + } + if (receiveQueue.Count > 0) + Log.Warn($"[SWT-SimpleWebClient]: ProcessMessageQueue has {receiveQueue.Count} remaining."); + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/SimpleWebClient.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/SimpleWebClient.cs.meta new file mode 100644 index 0000000..90c361b --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/SimpleWebClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 13131761a0bf5a64dadeccd700fe26e5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone.meta new file mode 100644 index 0000000..bf320c6 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9c19d05220a87c4cbbe4d1e422da0aa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientHandshake.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientHandshake.cs new file mode 100644 index 0000000..7821ded --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientHandshake.cs @@ -0,0 +1,91 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Mirror.SimpleWeb +{ + /// + /// Handles Handshake to the server when it first connects + /// The client handshake does not need buffers to reduce allocations since it only happens once + /// + internal class ClientHandshake + { + public bool TryHandshake(Connection conn, Uri uri) + { + try + { + Stream stream = conn.stream; + + byte[] keyBuffer = new byte[16]; + using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) + rng.GetBytes(keyBuffer); + + string key = Convert.ToBase64String(keyBuffer); + string keySum = key + Constants.HandshakeGUID; + byte[] keySumBytes = Encoding.ASCII.GetBytes(keySum); + Log.Verbose($"[SWT-ClientHandshake]: Handshake Hashing {Encoding.ASCII.GetString(keySumBytes)}"); + + // SHA-1 is the websocket standard: + // https://www.rfc-editor.org/rfc/rfc6455 + // we should follow the standard, even though SHA1 is considered weak: + // https://stackoverflow.com/questions/38038841/why-is-sha-1-considered-insecure + byte[] keySumHash = SHA1.Create().ComputeHash(keySumBytes); + + string expectedResponse = Convert.ToBase64String(keySumHash); + string handshake = + $"GET {uri.PathAndQuery} HTTP/1.1\r\n" + + $"Host: {uri.Host}:{uri.Port}\r\n" + + $"Upgrade: websocket\r\n" + + $"Connection: Upgrade\r\n" + + $"Sec-WebSocket-Key: {key}\r\n" + + $"Sec-WebSocket-Version: 13\r\n" + + "\r\n"; + byte[] encoded = Encoding.ASCII.GetBytes(handshake); + stream.Write(encoded, 0, encoded.Length); + + byte[] responseBuffer = new byte[1000]; + + int? lengthOrNull = ReadHelper.SafeReadTillMatch(stream, responseBuffer, 0, responseBuffer.Length, Constants.endOfHandshake); + + if (!lengthOrNull.HasValue) + { + Log.Error("[SWT-ClientHandshake]: Connection closed before handshake"); + return false; + } + + string responseString = Encoding.ASCII.GetString(responseBuffer, 0, lengthOrNull.Value); + Log.Verbose($"[SWT-ClientHandshake]: Handshake Response {responseString}"); + + string acceptHeader = "Sec-WebSocket-Accept: "; + int startIndex = responseString.IndexOf(acceptHeader, StringComparison.InvariantCultureIgnoreCase); + + if (startIndex < 0) + { + Log.Error($"[SWT-ClientHandshake]: Unexpected Handshake Response {responseString}"); + return false; + } + + startIndex += acceptHeader.Length; + int endIndex = responseString.IndexOf("\r\n", startIndex); + string responseKey = responseString.Substring(startIndex, endIndex - startIndex); + + if (responseKey != expectedResponse) + { + Log.Error($"[SWT-ClientHandshake]: Response key incorrect\n" + + $"Expected:{expectedResponse}\n" + + $"Response:{responseKey}\n" + + $"This can happen if Websocket Protocol is not installed in Windows Server Roles."); + return false; + } + + return true; + } + catch (Exception e) + { + Log.Exception(e); + return false; + } + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientHandshake.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientHandshake.cs.meta new file mode 100644 index 0000000..ad3d40d --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientHandshake.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3ffdcabc9e28f764a94fc4efc82d3e8b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientSslHelper.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientSslHelper.cs new file mode 100644 index 0000000..b033241 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientSslHelper.cs @@ -0,0 +1,47 @@ +using System; +using System.IO; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Cryptography.X509Certificates; + +namespace Mirror.SimpleWeb +{ + internal class ClientSslHelper + { + internal bool TryCreateStream(Connection conn, Uri uri) + { + NetworkStream stream = conn.client.GetStream(); + if (uri.Scheme != "wss") + { + conn.stream = stream; + return true; + } + + try + { + conn.stream = CreateStream(stream, uri); + return true; + } + catch (Exception e) + { + Log.Error($"[SWT-ClientSslHelper]: Create SSLStream Failed: {e.Message}\n{e.StackTrace}\n\n"); + return false; + } + } + + Stream CreateStream(NetworkStream stream, Uri uri) + { + SslStream sslStream = new SslStream(stream, true, ValidateServerCertificate); + sslStream.AuthenticateAsClient(uri.Host); + return sslStream; + } + + static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + // Do not allow this client to communicate with unauthenticated servers. + + // only accept if no errors + return sslPolicyErrors == SslPolicyErrors.None; + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientSslHelper.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientSslHelper.cs.meta new file mode 100644 index 0000000..d6be2bb --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/ClientSslHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46055a75559a79849a750f39a766db61 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/WebSocketClientStandAlone.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/WebSocketClientStandAlone.cs new file mode 100644 index 0000000..3375a63 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/WebSocketClientStandAlone.cs @@ -0,0 +1,140 @@ +using System; +using System.Net.Sockets; +using System.Threading; + +namespace Mirror.SimpleWeb +{ + public class WebSocketClientStandAlone : SimpleWebClient + { + readonly ClientSslHelper sslHelper; + readonly ClientHandshake handshake; + readonly TcpConfig tcpConfig; + Connection conn; + + internal WebSocketClientStandAlone(int maxMessageSize, int maxMessagesPerTick, TcpConfig tcpConfig) : base(maxMessageSize, maxMessagesPerTick) + { +#if UNITY_WEBGL && !UNITY_EDITOR + throw new NotSupportedException(); +#else + sslHelper = new ClientSslHelper(); + handshake = new ClientHandshake(); + this.tcpConfig = tcpConfig; +#endif + } + + public override void Connect(Uri serverAddress) + { + state = ClientState.Connecting; + + // create connection here before thread so that send queue exist before connected + TcpClient client = new TcpClient(); + tcpConfig.ApplyTo(client); + + // create connection object here so dispose correctly disconnects on failed connect + conn = new Connection(client, AfterConnectionDisposed); + + Thread receiveThread = new Thread(() => ConnectAndReceiveLoop(serverAddress)); + receiveThread.IsBackground = true; + receiveThread.Start(); + } + + void ConnectAndReceiveLoop(Uri serverAddress) + { + try + { + // connection created above + TcpClient client = conn.client; + conn.receiveThread = Thread.CurrentThread; + + try + { + client.Connect(serverAddress.Host, serverAddress.Port); + } + catch (SocketException) + { + client.Dispose(); + throw; + } + + + bool success = sslHelper.TryCreateStream(conn, serverAddress); + if (!success) + { + Log.Warn($"[SWT-WebSocketClientStandAlone]: Failed to create Stream with {serverAddress}"); + conn.Dispose(); + return; + } + + success = handshake.TryHandshake(conn, serverAddress); + if (!success) + { + Log.Warn($"[SWT-WebSocketClientStandAlone]: Failed Handshake with {serverAddress}"); + conn.Dispose(); + return; + } + + Log.Info($"[SWT-WebSocketClientStandAlone]: HandShake Successful with {serverAddress}"); + + state = ClientState.Connected; + + receiveQueue.Enqueue(new Message(EventType.Connected)); + + Thread sendThread = new Thread(() => + { + SendLoop.Config sendConfig = new SendLoop.Config( + conn, + bufferSize: Constants.HeaderSize + Constants.MaskSize + maxMessageSize, + setMask: true); + + SendLoop.Loop(sendConfig); + }); + + conn.sendThread = sendThread; + sendThread.IsBackground = true; + sendThread.Start(); + + ReceiveLoop.Config config = new ReceiveLoop.Config(conn, + maxMessageSize, + false, + receiveQueue, + bufferPool); + ReceiveLoop.Loop(config); + } + catch (ThreadInterruptedException e) { Log.InfoException(e); } + catch (ThreadAbortException e) { Log.InfoException(e); } + catch (Exception e) { Log.Exception(e); } + finally + { + // close here in case connect fails + conn?.Dispose(); + } + } + + void AfterConnectionDisposed(Connection conn) + { + state = ClientState.NotConnected; + // make sure Disconnected event is only called once + receiveQueue.Enqueue(new Message(EventType.Disconnected)); + } + + public override void Disconnect() + { + state = ClientState.Disconnecting; + Log.Verbose("[SWT-WebSocketClientStandAlone]: Disconnect Called"); + + if (conn == null) + state = ClientState.NotConnected; + else + conn?.Dispose(); + } + + public override void Send(ArraySegment segment) + { + ArrayBuffer buffer = bufferPool.Take(segment.Count); + buffer.CopyFrom(segment); + + conn.sendQueue.Enqueue(buffer); + conn.sendPending.Set(); + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/WebSocketClientStandAlone.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/WebSocketClientStandAlone.cs.meta new file mode 100644 index 0000000..37229d3 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/StandAlone/WebSocketClientStandAlone.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 05a9c87dea309e241a9185e5aa0d72ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl.meta new file mode 100644 index 0000000..2d81f7f --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7142349d566213c4abc763afaf4d91a1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/SimpleWebJSLib.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/SimpleWebJSLib.cs new file mode 100644 index 0000000..6af4671 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/SimpleWebJSLib.cs @@ -0,0 +1,34 @@ +using System; +#if UNITY_WEBGL +using System.Runtime.InteropServices; +#endif + +namespace Mirror.SimpleWeb +{ + internal static class SimpleWebJSLib + { +#if UNITY_WEBGL + [DllImport("__Internal")] + internal static extern bool IsConnected(int index); + +#pragma warning disable CA2101 // Specify marshaling for P/Invoke string arguments + [DllImport("__Internal")] +#pragma warning restore CA2101 // Specify marshaling for P/Invoke string arguments + internal static extern int Connect(string address, Action openCallback, Action closeCallBack, Action messageCallback, Action errorCallback); + + [DllImport("__Internal")] + internal static extern void Disconnect(int index); + + [DllImport("__Internal")] + internal static extern bool Send(int index, byte[] array, int offset, int length); +#else + internal static bool IsConnected(int index) => throw new NotSupportedException(); + + internal static int Connect(string address, Action openCallback, Action closeCallBack, Action messageCallback, Action errorCallback) => throw new NotSupportedException(); + + internal static void Disconnect(int index) => throw new NotSupportedException(); + + internal static bool Send(int index, byte[] array, int offset, int length) => throw new NotSupportedException(); +#endif + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/SimpleWebJSLib.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/SimpleWebJSLib.cs.meta new file mode 100644 index 0000000..9dfa12e --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/SimpleWebJSLib.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97b96a0b65c104443977473323c2ff35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/WebSocketClientWebGl.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/WebSocketClientWebGl.cs new file mode 100644 index 0000000..d96bcc8 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/WebSocketClientWebGl.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using AOT; + +namespace Mirror.SimpleWeb +{ +#if !UNITY_2021_3_OR_NEWER + + // Unity 2019 doesn't have ArraySegment.ToArray() yet. + public static class Extensions + { + public static byte[] ToArray(this ArraySegment segment) + { + byte[] array = new byte[segment.Count]; + Array.Copy(segment.Array, segment.Offset, array, 0, segment.Count); + return array; + } + } + +#endif + + public class WebSocketClientWebGl : SimpleWebClient + { + static readonly Dictionary instances = new Dictionary(); + + [MonoPInvokeCallback(typeof(Action))] + static void OpenCallback(int index) => instances[index].onOpen(); + + [MonoPInvokeCallback(typeof(Action))] + static void CloseCallBack(int index) => instances[index].onClose(); + + [MonoPInvokeCallback(typeof(Action))] + static void MessageCallback(int index, IntPtr bufferPtr, int count) => instances[index].onMessage(bufferPtr, count); + + [MonoPInvokeCallback(typeof(Action))] + static void ErrorCallback(int index) => instances[index].onErr(); + + /// + /// key for instances sent between c# and js + /// + int index; + + /// + /// Queue for messages sent by high level while still connecting, they will be sent after onOpen is called. + /// + /// This is a workaround for anything that calls Send immediately after Connect. + /// Without this the JS websocket will give errors. + /// + /// + Queue ConnectingSendQueue; + + public bool CheckJsConnected() => SimpleWebJSLib.IsConnected(index); + + internal WebSocketClientWebGl(int maxMessageSize, int maxMessagesPerTick) : base(maxMessageSize, maxMessagesPerTick) + { +#if !UNITY_WEBGL || UNITY_EDITOR + throw new NotSupportedException(); +#endif + } + + public override void Connect(Uri serverAddress) + { + index = SimpleWebJSLib.Connect(serverAddress.ToString(), OpenCallback, CloseCallBack, MessageCallback, ErrorCallback); + instances.Add(index, this); + state = ClientState.Connecting; + } + + public override void Disconnect() + { + state = ClientState.Disconnecting; + // disconnect should cause closeCallback and OnDisconnect to be called + SimpleWebJSLib.Disconnect(index); + } + + public override void Send(ArraySegment segment) + { + if (segment.Count > maxMessageSize) + { + Log.Error($"[SWT-WebSocketClientWebGl]: Cant send message with length {segment.Count} because it is over the max size of {maxMessageSize}"); + return; + } + + if (state == ClientState.Connected) + { + SimpleWebJSLib.Send(index, segment.Array, segment.Offset, segment.Count); + } + else if (ConnectingSendQueue == null) + { + ConnectingSendQueue = new Queue(); + ConnectingSendQueue.Enqueue(segment.ToArray()); + } + } + + void onOpen() + { + receiveQueue.Enqueue(new Message(EventType.Connected)); + state = ClientState.Connected; + + if (ConnectingSendQueue != null) + { + while (ConnectingSendQueue.Count > 0) + { + byte[] next = ConnectingSendQueue.Dequeue(); + SimpleWebJSLib.Send(index, next, 0, next.Length); + } + + ConnectingSendQueue = null; + } + } + + void onClose() + { + // this code should be last in this class + + receiveQueue.Enqueue(new Message(EventType.Disconnected)); + state = ClientState.NotConnected; + instances.Remove(index); + } + + void onMessage(IntPtr bufferPtr, int count) + { + try + { + ArrayBuffer buffer = bufferPool.Take(count); + buffer.CopyFrom(bufferPtr, count); + + receiveQueue.Enqueue(new Message(buffer)); + } + catch (Exception e) + { + Log.Error($"[SWT-WebSocketClientWebGl]: onMessage {e.GetType()}: {e.Message}\n{e.StackTrace}"); + receiveQueue.Enqueue(new Message(e)); + } + } + + void onErr() + { + receiveQueue.Enqueue(new Message(new Exception("Javascript Websocket error"))); + Disconnect(); + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/WebSocketClientWebGl.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/WebSocketClientWebGl.cs.meta new file mode 100644 index 0000000..3827d3a --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/WebSocketClientWebGl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 015c5b1915fd1a64cbe36444d16b2f7d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin.meta new file mode 100644 index 0000000..b516a8f --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1999985791b91b9458059e88404885a7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin/SimpleWeb.jslib b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin/SimpleWeb.jslib new file mode 100644 index 0000000..02e6b93 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin/SimpleWeb.jslib @@ -0,0 +1,114 @@ +// this will create a global object +const SimpleWeb = { + webSockets: [], + next: 1, + GetWebSocket: function (index) { + return SimpleWeb.webSockets[index] + }, + AddNextSocket: function (webSocket) { + var index = SimpleWeb.next; + SimpleWeb.next++; + SimpleWeb.webSockets[index] = webSocket; + return index; + }, + RemoveSocket: function (index) { + SimpleWeb.webSockets[index] = undefined; + }, +}; + +function IsConnected(index) { + var webSocket = SimpleWeb.GetWebSocket(index); + if (webSocket) { + return webSocket.readyState === webSocket.OPEN; + } + else { + return false; + } +} + +function Connect(addressPtr, openCallbackPtr, closeCallBackPtr, messageCallbackPtr, errorCallbackPtr) { + // fix for unity 2021 because unity bug in .jslib + if (typeof Runtime === "undefined") { + // if unity doesn't create Runtime, then make it here + // dont ask why this works, just be happy that it does + Runtime = { + dynCall: dynCall + } + } + + const address = UTF8ToString(addressPtr); + console.log("Connecting to " + address); + // Create webSocket connection. + webSocket = new WebSocket(address); + webSocket.binaryType = 'arraybuffer'; + const index = SimpleWeb.AddNextSocket(webSocket); + + // Connection opened + webSocket.addEventListener('open', function (event) { + console.log("Connected to " + address); + Runtime.dynCall('vi', openCallbackPtr, [index]); + }); + webSocket.addEventListener('close', function (event) { + console.log("Disconnected from " + address); + Runtime.dynCall('vi', closeCallBackPtr, [index]); + }); + + // Listen for messages + webSocket.addEventListener('message', function (event) { + if (event.data instanceof ArrayBuffer) { + // TODO dont alloc each time + var array = new Uint8Array(event.data); + var arrayLength = array.length; + + var bufferPtr = _malloc(arrayLength); + var dataBuffer = new Uint8Array(HEAPU8.buffer, bufferPtr, arrayLength); + dataBuffer.set(array); + + Runtime.dynCall('viii', messageCallbackPtr, [index, bufferPtr, arrayLength]); + _free(bufferPtr); + } + else { + console.error("message type not supported") + } + }); + + webSocket.addEventListener('error', function (event) { + console.error('Socket Error', event); + + Runtime.dynCall('vi', errorCallbackPtr, [index]); + }); + + return index; +} + +function Disconnect(index) { + var webSocket = SimpleWeb.GetWebSocket(index); + if (webSocket) { + webSocket.close(1000, "Disconnect Called by Mirror"); + } + + SimpleWeb.RemoveSocket(index); +} + +function Send(index, arrayPtr, offset, length) { + var webSocket = SimpleWeb.GetWebSocket(index); + if (webSocket) { + const start = arrayPtr + offset; + const end = start + length; + const data = HEAPU8.buffer.slice(start, end); + webSocket.send(data); + return true; + } + return false; +} + + +const SimpleWebLib = { + $SimpleWeb: SimpleWeb, + IsConnected, + Connect, + Disconnect, + Send +}; +autoAddDeps(SimpleWebLib, '$SimpleWeb'); +mergeInto(LibraryManager.library, SimpleWebLib); diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin/SimpleWeb.jslib.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin/SimpleWeb.jslib.meta new file mode 100644 index 0000000..cc1319e --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Client/Webgl/plugin/SimpleWeb.jslib.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: 54452a8c6d2ca9b49a8c79f81b50305c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Facebook: WebGL + second: + enabled: 1 + settings: {} + - first: + WebGL: WebGL + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common.meta new file mode 100644 index 0000000..078faaa --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 564d2cd3eee5b21419553c0528739d1b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/BufferPool.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/BufferPool.cs new file mode 100644 index 0000000..325bc45 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/BufferPool.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Mirror.SimpleWeb +{ + public interface IBufferOwner + { + void Return(ArrayBuffer buffer); + } + + public sealed class ArrayBuffer : IDisposable + { + readonly IBufferOwner owner; + + public readonly byte[] array; + + /// + /// number of bytes written to buffer + /// + public int count { get; internal set; } + + /// + /// How many times release needs to be called before buffer is returned to pool + /// This allows the buffer to be used in multiple places at the same time + /// + public void SetReleasesRequired(int required) + { + releasesRequired = required; + } + + /// + /// How many times release needs to be called before buffer is returned to pool + /// This allows the buffer to be used in multiple places at the same time + /// + /// + /// This value is normally 0, but can be changed to require release to be called multiple times + /// + int releasesRequired; + + public ArrayBuffer(IBufferOwner owner, int size) + { + this.owner = owner; + array = new byte[size]; + } + + public void Release() + { + int newValue = Interlocked.Decrement(ref releasesRequired); + if (newValue <= 0) + { + count = 0; + owner?.Return(this); + } + } + public void Dispose() + { + Release(); + } + + public void CopyTo(byte[] target, int offset) + { + if (count > (target.Length + offset)) + throw new ArgumentException($"{nameof(count)} was greater than {nameof(target)}.length", nameof(target)); + + Buffer.BlockCopy(array, 0, target, offset, count); + } + + public void CopyFrom(ArraySegment segment) + { + CopyFrom(segment.Array, segment.Offset, segment.Count); + } + + public void CopyFrom(byte[] source, int offset, int length) + { + if (length > array.Length) + throw new ArgumentException($"{nameof(length)} was greater than {nameof(array)}.length", nameof(length)); + + count = length; + Buffer.BlockCopy(source, offset, array, 0, length); + } + + public void CopyFrom(IntPtr bufferPtr, int length) + { + if (length > array.Length) + throw new ArgumentException($"{nameof(length)} was greater than {nameof(array)}.length", nameof(length)); + + count = length; + Marshal.Copy(bufferPtr, array, 0, length); + } + + public ArraySegment ToSegment() => new ArraySegment(array, 0, count); + + [Conditional("UNITY_ASSERTIONS")] + internal void Validate(int arraySize) + { + if (array.Length != arraySize) + Log.Error("[SWT-ArrayBuffer]: Buffer that was returned had an array of the wrong size"); + } + } + + internal class BufferBucket : IBufferOwner + { + public readonly int arraySize; + readonly ConcurrentQueue buffers; + + /// + /// keeps track of how many arrays are taken vs returned + /// + internal int _current = 0; + + public BufferBucket(int arraySize) + { + this.arraySize = arraySize; + buffers = new ConcurrentQueue(); + } + + public ArrayBuffer Take() + { + IncrementCreated(); + if (buffers.TryDequeue(out ArrayBuffer buffer)) + return buffer; + else + { + Log.Flood($"[SWT-BufferBucket]: BufferBucket({arraySize}) create new"); + return new ArrayBuffer(this, arraySize); + } + } + + public void Return(ArrayBuffer buffer) + { + DecrementCreated(); + buffer.Validate(arraySize); + buffers.Enqueue(buffer); + } + + [Conditional("DEBUG")] + void IncrementCreated() + { + int next = Interlocked.Increment(ref _current); + Log.Flood($"[SWT-BufferBucket]: BufferBucket({arraySize}) count:{next}"); + } + + [Conditional("DEBUG")] + void DecrementCreated() + { + int next = Interlocked.Decrement(ref _current); + Log.Flood($"[SWT-BufferBucket]: BufferBucket({arraySize}) count:{next}"); + } + } + + /// + /// Collection of different sized buffers + /// + /// + /// + /// Problem:
+ /// * Need to cached byte[] so that new ones aren't created each time
+ /// * Arrays sent are multiple different sizes
+ /// * Some message might be big so need buffers to cover that size
+ /// * Most messages will be small compared to max message size
+ ///
+ ///
+ /// + /// Solution:
+ /// * Create multiple groups of buffers covering the range of allowed sizes
+ /// * Split range exponentially (using math.log) so that there are more groups for small buffers
+ ///
+ ///
+ public class BufferPool + { + internal readonly BufferBucket[] buckets; + readonly int bucketCount; + readonly int smallest; + readonly int largest; + + public BufferPool(int bucketCount, int smallest, int largest) + { + if (bucketCount < 2) throw new ArgumentException("Count must be at least 2"); + if (smallest < 1) throw new ArgumentException("Smallest must be at least 1"); + if (largest < smallest) throw new ArgumentException("Largest must be greater than smallest"); + + this.bucketCount = bucketCount; + this.smallest = smallest; + this.largest = largest; + + // split range over log scale (more buckets for smaller sizes) + double minLog = Math.Log(this.smallest); + double maxLog = Math.Log(this.largest); + double range = maxLog - minLog; + double each = range / (bucketCount - 1); + + buckets = new BufferBucket[bucketCount]; + + for (int i = 0; i < bucketCount; i++) + { + double size = smallest * Math.Pow(Math.E, each * i); + buckets[i] = new BufferBucket((int)Math.Ceiling(size)); + } + + Validate(); + + // Example + // 5 count + // 20 smallest + // 16400 largest + + // 3.0 log 20 + // 9.7 log 16400 + + // 6.7 range 9.7 - 3 + // 1.675 each 6.7 / (5-1) + + // 20 e^ (3 + 1.675 * 0) + // 107 e^ (3 + 1.675 * 1) + // 572 e^ (3 + 1.675 * 2) + // 3056 e^ (3 + 1.675 * 3) + // 16,317 e^ (3 + 1.675 * 4) + + // precision wont be lose when using doubles + } + + [Conditional("UNITY_ASSERTIONS")] + void Validate() + { + if (buckets[0].arraySize != smallest) + Log.Error($"[SWT-BufferPool]: BufferPool Failed to create bucket for smallest. bucket:{buckets[0].arraySize} smallest:{smallest}"); + + int largestBucket = buckets[bucketCount - 1].arraySize; + // rounded using Ceiling, so allowed to be 1 more that largest + if (largestBucket != largest && largestBucket != largest + 1) + Log.Error($"[SWT-BufferPool]: BufferPool Failed to create bucket for largest. bucket:{largestBucket} smallest:{largest}"); + } + + public ArrayBuffer Take(int size) + { + if (size > largest) + throw new ArgumentException($"Size ({size}) is greater than largest ({largest})"); + + for (int i = 0; i < bucketCount; i++) + if (size <= buckets[i].arraySize) + return buckets[i].Take(); + + throw new ArgumentException($"Size ({size}) is greater than largest ({largest})"); + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/BufferPool.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/BufferPool.cs.meta new file mode 100644 index 0000000..0b1070f --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/BufferPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 94ae50f3ec35667469b861b12cd72f92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Connection.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Connection.cs new file mode 100644 index 0000000..a890f9c --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Connection.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +namespace Mirror.SimpleWeb +{ + internal sealed class Connection : IDisposable + { + readonly object disposedLock = new object(); + + public const int IdNotSet = -1; + public TcpClient client; + public int connId = IdNotSet; + + /// + /// Connect request, sent from client to start handshake + /// Only valid on server + /// + public Request request; + /// + /// RemoteEndpoint address or address from request header + /// Only valid on server + /// + public string remoteAddress; + + public Stream stream; + public Thread receiveThread; + public Thread sendThread; + + public ManualResetEventSlim sendPending = new ManualResetEventSlim(false); + public ConcurrentQueue sendQueue = new ConcurrentQueue(); + + public Action onDispose; + volatile bool hasDisposed; + + public Connection(TcpClient client, Action onDispose) + { + this.client = client ?? throw new ArgumentNullException(nameof(client)); + this.onDispose = onDispose; + } + + /// + /// disposes client and stops threads + /// + public void Dispose() + { + Log.Verbose($"[SWT-Connection]: Dispose {ToString()}"); + + // check hasDisposed first to stop ThreadInterruptedException on lock + if (hasDisposed) return; + + Log.Verbose($"[SWT-Connection]: Connection Close: {ToString()}"); + + lock (disposedLock) + { + // check hasDisposed again inside lock to make sure no other object has called this + if (hasDisposed) return; + + hasDisposed = true; + + // stop threads first so they don't try to use disposed objects + receiveThread.Interrupt(); + sendThread?.Interrupt(); + + try + { + // stream + stream?.Dispose(); + stream = null; + client.Dispose(); + client = null; + } + catch (Exception e) + { + Log.Exception(e); + } + + sendPending.Dispose(); + + // release all buffers in send queue + while (sendQueue.TryDequeue(out ArrayBuffer buffer)) + buffer.Release(); + + onDispose.Invoke(this); + } + } + + public override string ToString() + { + // remoteAddress isn't set until after handshake + if (hasDisposed) + return $"[Conn:{connId}, Disposed]"; + else if (!string.IsNullOrWhiteSpace(remoteAddress)) + return $"[Conn:{connId}, endPoint:{remoteAddress}]"; + else + try + { + EndPoint endpoint = client?.Client?.RemoteEndPoint; + return $"[Conn:{connId}, endPoint:{endpoint}]"; + } + catch (SocketException) + { + return $"[Conn:{connId}, endPoint:n/a]"; + } + } + + /// + /// Gets the address based on the and RemoteEndPoint + /// Called after ServerHandShake is accepted + /// + internal string CalculateAddress() + { + if (request.Headers.TryGetValue("X-Forwarded-For", out string forwardFor)) + { + string actualClientIP = forwardFor.ToString().Split(',').First(); + // Remove the port number from the address + return actualClientIP.Split(':').First(); + } + else + { + IPEndPoint ipEndPoint = (IPEndPoint)client.Client.RemoteEndPoint; + IPAddress ipAddress = ipEndPoint.Address; + if (ipAddress.IsIPv4MappedToIPv6) + ipAddress = ipAddress.MapToIPv4(); + + return ipAddress.ToString(); + } + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Connection.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Connection.cs.meta new file mode 100644 index 0000000..d48a835 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Connection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a13073c2b49d39943888df45174851bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Constants.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Constants.cs new file mode 100644 index 0000000..95d8cbb --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Constants.cs @@ -0,0 +1,76 @@ +using System.Text; + +namespace Mirror.SimpleWeb +{ + /// + /// Constant values that should never change + /// + /// Some values are from https://tools.ietf.org/html/rfc6455 + /// + /// + internal static class Constants + { + /// + /// Header is at most 4 bytes + /// + /// If message is less than 125 then header is 2 bytes, else header is 4 bytes + /// + /// + public const int HeaderSize = 4; + + /// + /// Smallest size of header + /// + /// If message is less than 125 then header is 2 bytes, else header is 4 bytes + /// + /// + public const int HeaderMinSize = 2; + + /// + /// bytes for short length + /// + public const int ShortLength = 2; + + /// + /// bytes for long length + /// + public const int LongLength = 8; + + /// + /// Message mask is always 4 bytes + /// + public const int MaskSize = 4; + + /// + /// Max size of a message for length to be 1 byte long + /// + /// payload length between 0-125 + /// + /// + public const int BytePayloadLength = 125; + + /// + /// if payload length is 126 when next 2 bytes will be the length + /// + public const int UshortPayloadLength = 126; + + /// + /// if payload length is 127 when next 8 bytes will be the length + /// + public const int UlongPayloadLength = 127; + + /// + /// Guid used for WebSocket Protocol + /// + public const string HandshakeGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + public static readonly int HandshakeGUIDLength = HandshakeGUID.Length; + + public static readonly byte[] HandshakeGUIDBytes = Encoding.ASCII.GetBytes(HandshakeGUID); + + /// + /// Handshake messages will end with \r\n\r\n + /// + public static readonly byte[] endOfHandshake = new byte[4] { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Constants.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Constants.cs.meta new file mode 100644 index 0000000..ece602e --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Constants.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 85d110a089d6ad348abf2d073ebce7cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/EventType.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/EventType.cs new file mode 100644 index 0000000..3a9d185 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/EventType.cs @@ -0,0 +1,10 @@ +namespace Mirror.SimpleWeb +{ + public enum EventType + { + Connected, + Data, + Disconnected, + Error + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/EventType.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/EventType.cs.meta new file mode 100644 index 0000000..a91403a --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/EventType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d9cd7d2b5229ab42a12e82ae17d0347 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Log.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Log.cs new file mode 100644 index 0000000..9b41e07 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Log.cs @@ -0,0 +1,224 @@ +using System; +using UnityEngine; +using Conditional = System.Diagnostics.ConditionalAttribute; + +namespace Mirror.SimpleWeb +{ + public static class Log + { + // The.NET console color names map to the following approximate CSS color names: + + // Black: Black + // Blue: Blue + // Cyan: Aqua or Cyan + // DarkBlue: DarkBlue + // DarkCyan: DarkCyan + // DarkGray: DarkGray + // DarkGreen: DarkGreen + // DarkMagenta: DarkMagenta + // DarkRed: DarkRed + // DarkYellow: DarkOrange or DarkGoldenRod + // Gray: Gray + // Green: Green + // Magenta: Magenta + // Red: Red + // White: White + // Yellow: Yellow + + // We can't use colors that are close to white or black because + // they won't show up well in the server console or browser console + + public enum Levels + { + Flood, + Verbose, + Info, + Warn, + Error, + None + } + + public static ILogger logger = Debug.unityLogger; + public static Levels minLogLevel = Levels.None; + + /// + /// Logs all exceptions to console + /// + /// Exception to log + public static void Exception(Exception e) + { +#if UNITY_SERVER || UNITY_WEBGL + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"[SWT:Exception] {e.GetType().Name}: {e.Message}\n{e.StackTrace}\n\n"); + Console.ResetColor(); +#else + logger.Log(LogType.Exception, $"[SWT:Exception] {e.GetType().Name}: {e.Message}\n{e.StackTrace}\n\n"); +#endif + } + + /// + /// Logs flood to console if minLogLevel is set to Flood or lower + /// + /// Message text to log + [Conditional("DEBUG")] + public static void Flood(string msg) + { + if (minLogLevel > Levels.Flood) return; + +#if UNITY_SERVER || UNITY_WEBGL + Console.ForegroundColor = ConsoleColor.Gray; + logger.Log(LogType.Log, msg); + Console.ResetColor(); +#else + logger.Log(LogType.Log, msg); +#endif + } + + /// + /// Logs buffer to console if minLogLevel is set to Flood or lower + /// Debug mode requrired, e.g. Unity Editor of Develpment Build + /// + /// Source of the log message + /// Byte array to be logged + /// starting point of byte array + /// number of bytes to read + [Conditional("DEBUG")] + public static void DumpBuffer(string label, byte[] buffer, int offset, int length) + { + if (minLogLevel > Levels.Flood) return; + +#if UNITY_SERVER || UNITY_WEBGL + Console.ForegroundColor = ConsoleColor.DarkBlue; + logger.Log(LogType.Log, $"{label}: {BufferToString(buffer, offset, length)}"); + Console.ResetColor(); +#else + logger.Log(LogType.Log, $"{label}: {BufferToString(buffer, offset, length)}"); +#endif + } + + /// + /// Logs buffer to console if minLogLevel is set to Flood or lower + /// Debug mode requrired, e.g. Unity Editor of Develpment Build + /// + /// Source of the log message + /// ArrayBuffer to show details for + [Conditional("DEBUG")] + public static void DumpBuffer(string label, ArrayBuffer arrayBuffer) + { + if (minLogLevel > Levels.Flood) return; + +#if UNITY_SERVER || UNITY_WEBGL + Console.ForegroundColor = ConsoleColor.DarkBlue; + logger.Log(LogType.Log, $"{label}: {BufferToString(arrayBuffer.array, 0, arrayBuffer.count)}"); + Console.ResetColor(); +#else + logger.Log(LogType.Log, $"{label}: {BufferToString(arrayBuffer.array, 0, arrayBuffer.count)}"); +#endif + } + + /// + /// Logs verbose to console if minLogLevel is set to Verbose or lower + /// + /// Message text to log + public static void Verbose(string msg) + { + if (minLogLevel > Levels.Verbose) return; + +#if DEBUG + // Debug builds and Unity Editor + logger.Log(LogType.Log, msg); +#else + // Server or WebGL + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine(msg); + Console.ResetColor(); +#endif + } + + /// + /// Logs info to console if minLogLevel is set to Info or lower + /// + /// Message text to log + /// Default Cyan works in server and browser consoles + public static void Info(string msg, ConsoleColor consoleColor = ConsoleColor.Cyan) + { + if (minLogLevel > Levels.Info) return; + +#if DEBUG + // Debug builds and Unity Editor + logger.Log(LogType.Log, msg); +#else + // Server or WebGL + Console.ForegroundColor = consoleColor; + Console.WriteLine(msg); + Console.ResetColor(); +#endif + } + + /// + /// Logs info to console if minLogLevel is set to Info or lower + /// + /// Exception to log + public static void InfoException(Exception e) + { + if (minLogLevel > Levels.Info) return; + +#if DEBUG + // Debug builds and Unity Editor + logger.Log(LogType.Exception, e.Message); +#else + // Server or WebGL + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine(e.Message); + Console.ResetColor(); +#endif + } + + /// + /// Logs info to console if minLogLevel is set to Warn or lower + /// + /// Message text to log + public static void Warn(string msg) + { + if (minLogLevel > Levels.Warn) return; + +#if DEBUG + // Debug builds and Unity Editor + logger.Log(LogType.Warning, msg); +#else + // Server or WebGL + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(msg); + Console.ResetColor(); +#endif + } + + /// + /// Logs info to console if minLogLevel is set to Error or lower + /// + /// Message text to log + public static void Error(string msg) + { + if (minLogLevel > Levels.Error) return; + +#if DEBUG + // Debug builds and Unity Editor + logger.Log(LogType.Error, msg); +#else + // Server or WebGL + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(msg); + Console.ResetColor(); +#endif + } + + /// + /// Returns a string representation of the byte array starting from offset for length bytes + /// + /// Byte array to read + /// starting point in the byte array + /// number of bytes to read from offset + /// + public static string BufferToString(byte[] buffer, int offset = 0, int? length = null) => BitConverter.ToString(buffer, offset, length ?? buffer.Length); + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Log.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Log.cs.meta new file mode 100644 index 0000000..beb2883 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Log.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3cf1521098e04f74fbea0fe2aa0439f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Message.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Message.cs new file mode 100644 index 0000000..29b4849 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Message.cs @@ -0,0 +1,49 @@ +using System; + +namespace Mirror.SimpleWeb +{ + public struct Message + { + public readonly int connId; + public readonly EventType type; + public readonly ArrayBuffer data; + public readonly Exception exception; + + public Message(EventType type) : this() + { + this.type = type; + } + + public Message(ArrayBuffer data) : this() + { + type = EventType.Data; + this.data = data; + } + + public Message(Exception exception) : this() + { + type = EventType.Error; + this.exception = exception; + } + + public Message(int connId, EventType type) : this() + { + this.connId = connId; + this.type = type; + } + + public Message(int connId, ArrayBuffer data) : this() + { + this.connId = connId; + type = EventType.Data; + this.data = data; + } + + public Message(int connId, Exception exception) : this() + { + this.connId = connId; + type = EventType.Error; + this.exception = exception; + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Message.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Message.cs.meta new file mode 100644 index 0000000..3286a2c --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Message.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f5d05d71b09d2714b96ffe80bc3d2a77 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/MessageProcessor.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/MessageProcessor.cs new file mode 100644 index 0000000..e3269f3 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/MessageProcessor.cs @@ -0,0 +1,175 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; + +namespace Mirror.SimpleWeb +{ + public static class MessageProcessor + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static byte FirstLengthByte(byte[] buffer) => (byte)(buffer[1] & 0b0111_1111); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NeedToReadShortLength(byte[] buffer) + { + byte lenByte = FirstLengthByte(buffer); + return lenByte == Constants.UshortPayloadLength; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NeedToReadLongLength(byte[] buffer) + { + byte lenByte = FirstLengthByte(buffer); + return lenByte == Constants.UlongPayloadLength; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetOpcode(byte[] buffer) => buffer[0] & 0b0000_1111; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetPayloadLength(byte[] buffer) => GetMessageLength(buffer, 0, FirstLengthByte(buffer)); + + /// + /// Has full message been sent + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Finished(byte[] buffer) => (buffer[0] & 0b1000_0000) != 0; + + public static void ValidateHeader(byte[] buffer, int maxLength, bool expectMask, bool opCodeContinuation = false) + { + bool finished = Finished(buffer); + bool hasMask = (buffer[1] & 0b1000_0000) != 0; // true from clients, false from server, "All messages from the client to the server have this bit set" + + int opcode = buffer[0] & 0b0000_1111; // expecting 1 - text message + byte lenByte = FirstLengthByte(buffer); + + ThrowIfMaskNotExpected(hasMask, expectMask); + ThrowIfBadOpCode(opcode, finished, opCodeContinuation); + + int msglen = GetMessageLength(buffer, 0, lenByte); + + ThrowIfLengthZero(msglen); + ThrowIfMsgLengthTooLong(msglen, maxLength); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ToggleMask(byte[] src, int sourceOffset, int messageLength, byte[] maskBuffer, int maskOffset) + { + ToggleMask(src, sourceOffset, src, sourceOffset, messageLength, maskBuffer, maskOffset); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ToggleMask(byte[] src, int sourceOffset, ArrayBuffer dst, int messageLength, byte[] maskBuffer, int maskOffset) + { + ToggleMask(src, sourceOffset, dst.array, 0, messageLength, maskBuffer, maskOffset); + dst.count = messageLength; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ToggleMask(byte[] src, int srcOffset, byte[] dst, int dstOffset, int messageLength, byte[] maskBuffer, int maskOffset) + { + for (int i = 0; i < messageLength; i++) + { + byte maskByte = maskBuffer[maskOffset + i % Constants.MaskSize]; + dst[dstOffset + i] = (byte)(src[srcOffset + i] ^ maskByte); + } + } + + /// + static int GetMessageLength(byte[] buffer, int offset, byte lenByte) + { + if (lenByte == Constants.UshortPayloadLength) + { + // header is 2 bytes + ushort value = 0; + value |= (ushort)(buffer[offset + 2] << 8); + value |= buffer[offset + 3]; + + return value; + } + else if (lenByte == Constants.UlongPayloadLength) + { + // header is 8 bytes + ulong value = 0; + value |= ((ulong)buffer[offset + 2] << 56); + value |= ((ulong)buffer[offset + 3] << 48); + value |= ((ulong)buffer[offset + 4] << 40); + value |= ((ulong)buffer[offset + 5] << 32); + value |= ((ulong)buffer[offset + 6] << 24); + value |= ((ulong)buffer[offset + 7] << 16); + value |= ((ulong)buffer[offset + 8] << 8); + value |= ((ulong)buffer[offset + 9] << 0); + + if (value > int.MaxValue) + throw new NotSupportedException($"Can't receive payloads larger that int.max: {int.MaxValue}"); + + return (int)value; + } + else // is less than 126 + { + // header is 2 bytes long + return lenByte; + } + } + + /// + static void ThrowIfMaskNotExpected(bool hasMask, bool expectMask) + { + if (hasMask != expectMask) + throw new InvalidDataException($"Message expected mask to be {expectMask} but was {hasMask}"); + } + + /// + static void ThrowIfBadOpCode(int opcode, bool finished, bool opCodeContinuation) + { + // 0 = continuation + // 2 = binary + // 8 = close + + // do we expect Continuation? + if (opCodeContinuation) + { + // good it was Continuation + if (opcode == 0) + return; + + // bad, wasn't Continuation + throw new InvalidDataException("Expected opcode to be Continuation"); + } + else if (!finished) + { + // fragmented message, should be binary + if (opcode == 2) + return; + + throw new InvalidDataException("Expected opcode to be binary"); + } + else + { + // normal message, should be binary or close + if (opcode == 2 || opcode == 8) + return; + + throw new InvalidDataException("Expected opcode to be binary or close"); + } + } + + /// + static void ThrowIfLengthZero(int msglen) + { + if (msglen == 0) + throw new InvalidDataException("Message length was zero"); + } + + /// + /// need to check this so that data from previous buffer isn't used + /// + public static void ThrowIfMsgLengthTooLong(int msglen, int maxLength) + { + if (msglen > maxLength) + throw new InvalidDataException("Message length is greater than max length"); + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/MessageProcessor.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/MessageProcessor.cs.meta new file mode 100644 index 0000000..7e3a7c4 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/MessageProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c1f218a2b16ca846aaf23260078e549 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReadHelper.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReadHelper.cs new file mode 100644 index 0000000..36bcb16 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReadHelper.cs @@ -0,0 +1,123 @@ +using System; +using System.IO; +using System.Runtime.Serialization; + +namespace Mirror.SimpleWeb +{ + public static class ReadHelper + { + /// + /// Reads exactly length from stream + /// + /// outOffset + length + /// + public static int Read(Stream stream, byte[] outBuffer, int outOffset, int length) + { + int received = 0; + try + { + while (received < length) + { + int read = stream.Read(outBuffer, outOffset + received, length - received); + if (read == 0) + throw new ReadHelperException("returned 0"); + + received += read; + } + } + catch (AggregateException ae) + { + // if interrupt is called we don't care about Exceptions + Utils.CheckForInterupt(); + + // rethrow + ae.Handle(e => false); + } + + if (received != length) + throw new ReadHelperException("returned not equal to length"); + + return outOffset + received; + } + + /// + /// Reads and returns results. This should never throw an exception + /// + public static bool TryRead(Stream stream, byte[] outBuffer, int outOffset, int length) + { + try + { + Read(stream, outBuffer, outOffset, length); + return true; + } + catch (ReadHelperException) + { + return false; + } + catch (IOException) + { + return false; + } + catch (Exception e) + { + Log.Exception(e); + return false; + } + } + + public static int? SafeReadTillMatch(Stream stream, byte[] outBuffer, int outOffset, int maxLength, byte[] endOfHeader) + { + try + { + int read = 0; + int endIndex = 0; + int endLength = endOfHeader.Length; + while (true) + { + int next = stream.ReadByte(); + if (next == -1) // closed + return null; + + if (read >= maxLength) + { + Log.Error("[SWT-ReadHelper]: SafeReadTillMatch exceeded maxLength"); + return null; + } + + outBuffer[outOffset + read] = (byte)next; + read++; + + // if n is match, check n+1 next + if (endOfHeader[endIndex] == next) + { + endIndex++; + // when all is match return with read length + if (endIndex >= endLength) + return read; + } + // if n not match reset to 0 + else + endIndex = 0; + } + } + catch (IOException e) + { + Log.InfoException(e); + return null; + } + catch (Exception e) + { + Log.Exception(e); + return null; + } + } + } + + [Serializable] + public class ReadHelperException : Exception + { + public ReadHelperException(string message) : base(message) { } + + protected ReadHelperException(SerializationInfo info, StreamingContext context) : base(info, context) { } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReadHelper.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReadHelper.cs.meta new file mode 100644 index 0000000..77d09c1 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReadHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f4fa5d324e708c46a55810a97de75bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReceiveLoop.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReceiveLoop.cs new file mode 100644 index 0000000..741c0b7 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReceiveLoop.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using UnityEngine.Profiling; + +namespace Mirror.SimpleWeb +{ + internal static class ReceiveLoop + { + public struct Config + { + public readonly Connection conn; + public readonly int maxMessageSize; + public readonly bool expectMask; + public readonly ConcurrentQueue queue; + public readonly BufferPool bufferPool; + + public Config(Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue queue, BufferPool bufferPool) + { + this.conn = conn ?? throw new ArgumentNullException(nameof(conn)); + this.maxMessageSize = maxMessageSize; + this.expectMask = expectMask; + this.queue = queue ?? throw new ArgumentNullException(nameof(queue)); + this.bufferPool = bufferPool ?? throw new ArgumentNullException(nameof(bufferPool)); + } + + public void Deconstruct(out Connection conn, out int maxMessageSize, out bool expectMask, out ConcurrentQueue queue, out BufferPool bufferPool) + { + conn = this.conn; + maxMessageSize = this.maxMessageSize; + expectMask = this.expectMask; + queue = this.queue; + bufferPool = this.bufferPool; + } + } + + struct Header + { + public int payloadLength; + public int offset; + public int opcode; + public bool finished; + } + + public static void Loop(Config config) + { + (Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue queue, BufferPool _) = config; + + Profiler.BeginThreadProfiling("SimpleWeb", $"ReceiveLoop {conn.connId}"); + + byte[] readBuffer = new byte[Constants.HeaderSize + (expectMask ? Constants.MaskSize : 0) + maxMessageSize]; + try + { + try + { + TcpClient client = conn.client; + + while (client.Connected) + ReadOneMessage(config, readBuffer); + + Log.Verbose($"[SWT-ReceiveLoop]: {conn} Not Connected"); + } + catch (Exception) + { + // if interrupted we don't care about other exceptions + Utils.CheckForInterupt(); + throw; + } + } + catch (ThreadInterruptedException e) { Log.InfoException(e); } + catch (ThreadAbortException e) { Log.InfoException(e); } + catch (ObjectDisposedException e) { Log.InfoException(e); } + catch (ReadHelperException e) + { + Log.InfoException(e); + } + catch (SocketException e) + { + // this could happen if wss client closes stream + Log.Warn($"[SWT-ReceiveLoop]: ReceiveLoop SocketException\n{e.Message}"); + queue.Enqueue(new Message(conn.connId, e)); + } + catch (IOException e) + { + // this could happen if client disconnects + Log.Warn($"[SWT-ReceiveLoop]: ReceiveLoop IOException\n{e.Message}"); + queue.Enqueue(new Message(conn.connId, e)); + } + catch (InvalidDataException e) + { + Log.Error($"[SWT-ReceiveLoop]: Invalid data from {conn}\n{e.Message}\n{e.StackTrace}\n\n"); + queue.Enqueue(new Message(conn.connId, e)); + } + catch (Exception e) + { + Log.Exception(e); + queue.Enqueue(new Message(conn.connId, e)); + } + finally + { + Profiler.EndThreadProfiling(); + conn.Dispose(); + } + } + + static void ReadOneMessage(Config config, byte[] buffer) + { + (Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue queue, BufferPool bufferPool) = config; + Stream stream = conn.stream; + + Header header = ReadHeader(config, buffer); + + int msgOffset = header.offset; + header.offset = ReadHelper.Read(stream, buffer, header.offset, header.payloadLength); + + if (header.finished) + { + switch (header.opcode) + { + case 2: + HandleArrayMessage(config, buffer, msgOffset, header.payloadLength); + break; + case 8: + HandleCloseMessage(config, buffer, msgOffset, header.payloadLength); + break; + } + } + else + { + // todo cache this to avoid allocations + Queue fragments = new Queue(); + fragments.Enqueue(CopyMessageToBuffer(bufferPool, expectMask, buffer, msgOffset, header.payloadLength)); + int totalSize = header.payloadLength; + + while (!header.finished) + { + header = ReadHeader(config, buffer, opCodeContinuation: true); + + msgOffset = header.offset; + header.offset = ReadHelper.Read(stream, buffer, header.offset, header.payloadLength); + fragments.Enqueue(CopyMessageToBuffer(bufferPool, expectMask, buffer, msgOffset, header.payloadLength)); + + totalSize += header.payloadLength; + MessageProcessor.ThrowIfMsgLengthTooLong(totalSize, maxMessageSize); + } + + ArrayBuffer msg = bufferPool.Take(totalSize); + msg.count = 0; + while (fragments.Count > 0) + { + ArrayBuffer part = fragments.Dequeue(); + + part.CopyTo(msg.array, msg.count); + msg.count += part.count; + + part.Release(); + } + + // dump after mask off + Log.DumpBuffer($"[SWT-ReceiveLoop]: Message", msg); + + queue.Enqueue(new Message(conn.connId, msg)); + } + } + + static Header ReadHeader(Config config, byte[] buffer, bool opCodeContinuation = false) + { + (Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue queue, BufferPool bufferPool) = config; + Stream stream = conn.stream; + Header header = new Header(); + + // read 2 + header.offset = ReadHelper.Read(stream, buffer, header.offset, Constants.HeaderMinSize); + // log after first blocking call + Log.Flood($"[SWT-ReceiveLoop]: Message From {conn}"); + + if (MessageProcessor.NeedToReadShortLength(buffer)) + header.offset = ReadHelper.Read(stream, buffer, header.offset, Constants.ShortLength); + if (MessageProcessor.NeedToReadLongLength(buffer)) + header.offset = ReadHelper.Read(stream, buffer, header.offset, Constants.LongLength); + + Log.DumpBuffer($"[SWT-ReceiveLoop]: Raw Header", buffer, 0, header.offset); + + MessageProcessor.ValidateHeader(buffer, maxMessageSize, expectMask, opCodeContinuation); + + if (expectMask) + header.offset = ReadHelper.Read(stream, buffer, header.offset, Constants.MaskSize); + + header.opcode = MessageProcessor.GetOpcode(buffer); + header.payloadLength = MessageProcessor.GetPayloadLength(buffer); + header.finished = MessageProcessor.Finished(buffer); + + Log.Flood($"[SWT-ReceiveLoop]: Header ln:{header.payloadLength} op:{header.opcode} mask:{expectMask}"); + + return header; + } + + static void HandleArrayMessage(Config config, byte[] buffer, int msgOffset, int payloadLength) + { + (Connection conn, int _, bool expectMask, ConcurrentQueue queue, BufferPool bufferPool) = config; + + ArrayBuffer arrayBuffer = CopyMessageToBuffer(bufferPool, expectMask, buffer, msgOffset, payloadLength); + + // dump after mask off + Log.DumpBuffer($"[SWT-ReceiveLoop]: Message", arrayBuffer); + + queue.Enqueue(new Message(conn.connId, arrayBuffer)); + } + + static ArrayBuffer CopyMessageToBuffer(BufferPool bufferPool, bool expectMask, byte[] buffer, int msgOffset, int payloadLength) + { + ArrayBuffer arrayBuffer = bufferPool.Take(payloadLength); + + if (expectMask) + { + int maskOffset = msgOffset - Constants.MaskSize; + // write the result of toggle directly into arrayBuffer to avoid 2nd copy call + MessageProcessor.ToggleMask(buffer, msgOffset, arrayBuffer, payloadLength, buffer, maskOffset); + } + else + arrayBuffer.CopyFrom(buffer, msgOffset, payloadLength); + + return arrayBuffer; + } + + static void HandleCloseMessage(Config config, byte[] buffer, int msgOffset, int payloadLength) + { + (Connection conn, int _, bool expectMask, ConcurrentQueue _, BufferPool _) = config; + + if (expectMask) + { + int maskOffset = msgOffset - Constants.MaskSize; + MessageProcessor.ToggleMask(buffer, msgOffset, payloadLength, buffer, maskOffset); + } + + // dump after mask off + Log.DumpBuffer($"[SWT-ReceiveLoop]: Message", buffer, msgOffset, payloadLength); + Log.Verbose($"[SWT-ReceiveLoop]: Close: {GetCloseCode(buffer, msgOffset)} message:{GetCloseMessage(buffer, msgOffset, payloadLength)}"); + + conn.Dispose(); + } + + static string GetCloseMessage(byte[] buffer, int msgOffset, int payloadLength) + => Encoding.UTF8.GetString(buffer, msgOffset + 2, payloadLength - 2); + + static int GetCloseCode(byte[] buffer, int msgOffset) + => buffer[msgOffset + 0] << 8 | buffer[msgOffset + 1]; + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReceiveLoop.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReceiveLoop.cs.meta new file mode 100644 index 0000000..47c6ff5 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/ReceiveLoop.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a26c2815f58431c4a98c158c8b655ffd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Request.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Request.cs new file mode 100644 index 0000000..c062faa --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Request.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mirror.SimpleWeb +{ + /// + /// Represents a client's request to the Websockets server, which is the first message from the client. + /// + public class Request + { + static readonly char[] lineSplitChars = new char[] { '\r', '\n' }; + static readonly char[] headerSplitChars = new char[] { ':' }; + public string RequestLine; + public Dictionary Headers = new Dictionary(); + + public Request(string message) + { + string[] all = message.Split(lineSplitChars, StringSplitOptions.RemoveEmptyEntries); + RequestLine = all.First(); + Headers = all.Skip(1) + .Select(header => header.Split(headerSplitChars, 2, StringSplitOptions.RemoveEmptyEntries)) + .ToDictionary(split => split[0].Trim(), split => split[1].Trim()); + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Request.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Request.cs.meta new file mode 100644 index 0000000..8baf222 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Request.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 50b41ad63d4956a42a073bad5158fe09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/SendLoop.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/SendLoop.cs new file mode 100644 index 0000000..fa10816 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/SendLoop.cs @@ -0,0 +1,225 @@ +using System; +using System.IO; +using System.Net.Sockets; +using System.Security.Cryptography; +using System.Threading; +using UnityEngine.Profiling; + +namespace Mirror.SimpleWeb +{ + public static class SendLoopConfig + { + public static volatile bool batchSend = false; + public static volatile bool sleepBeforeSend = false; + } + internal static class SendLoop + { + public struct Config + { + public readonly Connection conn; + public readonly int bufferSize; + public readonly bool setMask; + + public Config(Connection conn, int bufferSize, bool setMask) + { + this.conn = conn ?? throw new ArgumentNullException(nameof(conn)); + this.bufferSize = bufferSize; + this.setMask = setMask; + } + + public void Deconstruct(out Connection conn, out int bufferSize, out bool setMask) + { + conn = this.conn; + bufferSize = this.bufferSize; + setMask = this.setMask; + } + } + + public static void Loop(Config config) + { + (Connection conn, int bufferSize, bool setMask) = config; + + Profiler.BeginThreadProfiling("SimpleWeb", $"SendLoop {conn.connId}"); + + // create write buffer for this thread + byte[] writeBuffer = new byte[bufferSize]; + MaskHelper maskHelper = setMask ? new MaskHelper() : null; + try + { + TcpClient client = conn.client; + Stream stream = conn.stream; + + // null check in case disconnect while send thread is starting + if (client == null) + return; + + while (client.Connected) + { + // wait for message + conn.sendPending.Wait(); + // wait for 1ms for mirror to send other messages + if (SendLoopConfig.sleepBeforeSend) + Thread.Sleep(1); + + conn.sendPending.Reset(); + + if (SendLoopConfig.batchSend) + { + int offset = 0; + while (conn.sendQueue.TryDequeue(out ArrayBuffer msg)) + { + // check if connected before sending message + if (!client.Connected) + { + Log.Verbose($"[SWT-SendLoop]: SendLoop {conn} not connected"); + msg.Release(); + return; + } + + int maxLength = msg.count + Constants.HeaderSize + Constants.MaskSize; + + // if next writer could overflow, write to stream and clear buffer + if (offset + maxLength > bufferSize) + { + stream.Write(writeBuffer, 0, offset); + offset = 0; + } + + offset = SendMessage(writeBuffer, offset, msg, setMask, maskHelper); + msg.Release(); + } + + // after no message in queue, send remaining messages + // don't need to check offset > 0 because last message in queue will always be sent here + + stream.Write(writeBuffer, 0, offset); + } + else + { + while (conn.sendQueue.TryDequeue(out ArrayBuffer msg)) + { + // check if connected before sending message + if (!client.Connected) + { + Log.Verbose($"[SWT-SendLoop]: SendLoop {conn} not connected"); + msg.Release(); + return; + } + + int length = SendMessage(writeBuffer, 0, msg, setMask, maskHelper); + stream.Write(writeBuffer, 0, length); + msg.Release(); + } + } + } + + Log.Verbose($"[SWT-SendLoop]: {conn} Not Connected"); + } + catch (ThreadInterruptedException e) { Log.InfoException(e); } + catch (ThreadAbortException e) { Log.InfoException(e); } + catch (Exception e) + { + Log.Exception(e); + } + finally + { + Profiler.EndThreadProfiling(); + conn.Dispose(); + maskHelper?.Dispose(); + } + } + + /// new offset in buffer + static int SendMessage(byte[] buffer, int startOffset, ArrayBuffer msg, bool setMask, MaskHelper maskHelper) + { + int msgLength = msg.count; + int offset = WriteHeader(buffer, startOffset, msgLength, setMask); + + if (setMask) + { + offset = maskHelper.WriteMask(buffer, offset); + } + + msg.CopyTo(buffer, offset); + offset += msgLength; + + // dump before mask on + Log.DumpBuffer("[SWT-SendLoop]: Send", buffer, startOffset, offset); + + if (setMask) + { + int messageOffset = offset - msgLength; + MessageProcessor.ToggleMask(buffer, messageOffset, msgLength, buffer, messageOffset - Constants.MaskSize); + } + + return offset; + } + + public static int WriteHeader(byte[] buffer, int startOffset, int msgLength, bool setMask) + { + int sendLength = 0; + const byte finished = 128; + const byte byteOpCode = 2; + + buffer[startOffset + 0] = finished | byteOpCode; + sendLength++; + + if (msgLength <= Constants.BytePayloadLength) + { + buffer[startOffset + 1] = (byte)msgLength; + sendLength++; + } + else if (msgLength <= ushort.MaxValue) + { + buffer[startOffset + 1] = 126; + buffer[startOffset + 2] = (byte)(msgLength >> 8); + buffer[startOffset + 3] = (byte)msgLength; + sendLength += 3; + } + else + { + buffer[startOffset + 1] = 127; + // must be 64 bytes, but we only have 32 bit length, so first 4 bits are 0 + buffer[startOffset + 2] = 0; + buffer[startOffset + 3] = 0; + buffer[startOffset + 4] = 0; + buffer[startOffset + 5] = 0; + buffer[startOffset + 6] = (byte)(msgLength >> 24); + buffer[startOffset + 7] = (byte)(msgLength >> 16); + buffer[startOffset + 8] = (byte)(msgLength >> 8); + buffer[startOffset + 9] = (byte)msgLength; + + sendLength += 9; + } + + if (setMask) + buffer[startOffset + 1] |= 0b1000_0000; + + return sendLength + startOffset; + } + + } + sealed class MaskHelper : IDisposable + { + readonly byte[] maskBuffer; + readonly RNGCryptoServiceProvider random; + + public MaskHelper() + { + maskBuffer = new byte[4]; + random = new RNGCryptoServiceProvider(); + } + public void Dispose() + { + random.Dispose(); + } + + public int WriteMask(byte[] buffer, int offset) + { + random.GetBytes(maskBuffer); + Buffer.BlockCopy(maskBuffer, 0, buffer, offset, 4); + + return offset + 4; + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/SendLoop.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/SendLoop.cs.meta new file mode 100644 index 0000000..09dfd1e --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/SendLoop.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f87dd81736d9c824db67f808ac71841d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/TcpConfig.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/TcpConfig.cs new file mode 100644 index 0000000..230cd7a --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/TcpConfig.cs @@ -0,0 +1,26 @@ +using System.Net.Sockets; + +namespace Mirror.SimpleWeb +{ + [System.Serializable] + public struct TcpConfig + { + public readonly bool noDelay; + public readonly int sendTimeout; + public readonly int receiveTimeout; + + public TcpConfig(bool noDelay, int sendTimeout, int receiveTimeout) + { + this.noDelay = noDelay; + this.sendTimeout = sendTimeout; + this.receiveTimeout = receiveTimeout; + } + + public void ApplyTo(TcpClient client) + { + client.SendTimeout = sendTimeout; + client.ReceiveTimeout = receiveTimeout; + client.NoDelay = noDelay; + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/TcpConfig.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/TcpConfig.cs.meta new file mode 100644 index 0000000..62ba232 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/TcpConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 81ac8d35f28fab14b9edda5cd9d4fc86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Utils.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Utils.cs new file mode 100644 index 0000000..b8a860c --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Utils.cs @@ -0,0 +1,13 @@ +using System.Threading; + +namespace Mirror.SimpleWeb +{ + internal static class Utils + { + public static void CheckForInterupt() + { + // sleep in order to check for ThreadInterruptedException + Thread.Sleep(1); + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Utils.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Utils.cs.meta new file mode 100644 index 0000000..79a1583 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Common/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4643ffb4cb0562847b1ae925d07e15b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/LICENSE b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/LICENSE new file mode 100644 index 0000000..d2b4728 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 James Frowen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/LICENSE.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/LICENSE.meta new file mode 100644 index 0000000..8ece59e --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0a0cf751b4a201242ac60b4adbc54657 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/README.txt b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/README.txt new file mode 100644 index 0000000..fd59b3d --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/README.txt @@ -0,0 +1,19 @@ +SimpleWebTransport is a Transport that implements websocket for Webgl +Can be used in High level networking solution like Mirror or Mirage +This transport can also work on standalone builds and has support for +encryption with websocket secure. + +Requirements: + Unity 2019.4 LTS + +Documentation: + https://mirror-networking.gitbook.io/docs/ + https://github.com/James-Frowen/SimpleWebTransport/blob/master/README.md + +Support: + Discord: https://discord.gg/BZTQcftBkE + Bug Reports: https://github.com/James-Frowen/SimpleWebTransport/issues + + +**To get most recent updates and fixes download from github** +https://github.com/James-Frowen/SimpleWebTransport/releases diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/README.txt.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/README.txt.meta new file mode 100644 index 0000000..b63fe39 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/README.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0e3971d5783109f4d9ce93c7a689d701 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server.meta new file mode 100644 index 0000000..31f317f --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0e599e92544d43344a9a9060052add28 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerHandshake.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerHandshake.cs new file mode 100644 index 0000000..7949da8 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerHandshake.cs @@ -0,0 +1,156 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Mirror.SimpleWeb +{ + /// + /// Handles Handshakes from new clients on the server + /// The server handshake has buffers to reduce allocations when clients connect + /// + internal class ServerHandshake + { + const int GetSize = 3; + const int ResponseLength = 129; + const int KeyLength = 24; + const int MergedKeyLength = 60; + const string KeyHeaderString = "\r\nSec-WebSocket-Key: "; + // this isn't an official max, just a reasonable size for a websocket handshake + readonly int maxHttpHeaderSize = 3000; + + // SHA-1 is the websocket standard: + // https://www.rfc-editor.org/rfc/rfc6455 + // we should follow the standard, even though SHA1 is considered weak: + // https://stackoverflow.com/questions/38038841/why-is-sha-1-considered-insecure + readonly SHA1 sha1 = SHA1.Create(); + readonly BufferPool bufferPool; + + public ServerHandshake(BufferPool bufferPool, int handshakeMaxSize) + { + this.bufferPool = bufferPool; + maxHttpHeaderSize = handshakeMaxSize; + } + + ~ServerHandshake() + { + sha1.Dispose(); + } + + public bool TryHandshake(Connection conn) + { + Stream stream = conn.stream; + + using (ArrayBuffer getHeader = bufferPool.Take(GetSize)) + { + if (!ReadHelper.TryRead(stream, getHeader.array, 0, GetSize)) + return false; + + getHeader.count = GetSize; + + if (!IsGet(getHeader.array)) + { + Log.Warn($"[SWT-ServerHandshake]: First bytes from client was not 'GET' for handshake, instead was {Log.BufferToString(getHeader.array, 0, GetSize)}"); + return false; + } + } + + string msg = ReadToEndForHandshake(stream); + + if (string.IsNullOrEmpty(msg)) + return false; + + try + { + AcceptHandshake(stream, msg); + + conn.request = new Request(msg); + conn.remoteAddress = conn.CalculateAddress(); + Log.Info($"[SWT-ServerHandshake]: A client connected from {conn}"); + + return true; + } + catch (ArgumentException e) + { + Log.InfoException(e); + return false; + } + } + + string ReadToEndForHandshake(Stream stream) + { + using (ArrayBuffer readBuffer = bufferPool.Take(maxHttpHeaderSize)) + { + int? readCountOrFail = ReadHelper.SafeReadTillMatch(stream, readBuffer.array, 0, maxHttpHeaderSize, Constants.endOfHandshake); + if (!readCountOrFail.HasValue) + return null; + + int readCount = readCountOrFail.Value; + + string msg = Encoding.ASCII.GetString(readBuffer.array, 0, readCount); + // GET isn't in the bytes we read here, so we need to add it back + msg = $"GET{msg}"; + Log.Verbose($"[SWT-ServerHandshake]: Client Handshake Message:\r\n{msg}"); + + return msg; + } + } + + static bool IsGet(byte[] getHeader) + { + // just check bytes here instead of using Encoding.ASCII + return getHeader[0] == 71 && // G + getHeader[1] == 69 && // E + getHeader[2] == 84; // T + } + + void AcceptHandshake(Stream stream, string msg) + { + using (ArrayBuffer keyBuffer = bufferPool.Take(KeyLength + Constants.HandshakeGUIDLength), + responseBuffer = bufferPool.Take(ResponseLength)) + { + GetKey(msg, keyBuffer.array); + AppendGuid(keyBuffer.array); + byte[] keyHash = CreateHash(keyBuffer.array); + CreateResponse(keyHash, responseBuffer.array); + + stream.Write(responseBuffer.array, 0, ResponseLength); + } + } + + static void GetKey(string msg, byte[] keyBuffer) + { + int start = msg.IndexOf(KeyHeaderString, StringComparison.InvariantCultureIgnoreCase) + KeyHeaderString.Length; + + Log.Verbose($"[SWT-ServerHandshake]: Handshake Key: {msg.Substring(start, KeyLength)}"); + Encoding.ASCII.GetBytes(msg, start, KeyLength, keyBuffer, 0); + } + + static void AppendGuid(byte[] keyBuffer) + { + Buffer.BlockCopy(Constants.HandshakeGUIDBytes, 0, keyBuffer, KeyLength, Constants.HandshakeGUIDLength); + } + + byte[] CreateHash(byte[] keyBuffer) + { + Log.Verbose($"[SWT-ServerHandshake]: Handshake Hashing {Encoding.ASCII.GetString(keyBuffer, 0, MergedKeyLength)}"); + return sha1.ComputeHash(keyBuffer, 0, MergedKeyLength); + } + + static void CreateResponse(byte[] keyHash, byte[] responseBuffer) + { + string keyHashString = Convert.ToBase64String(keyHash); + + // compiler should merge these strings into 1 string before format + string message = string.Format( + "HTTP/1.1 101 Switching Protocols\r\n" + + "Connection: Upgrade\r\n" + + "Upgrade: websocket\r\n" + + "Sec-WebSocket-Accept: {0}\r\n\r\n", + keyHashString); + + Log.Verbose($"[SWT-ServerHandshake]: Handshake Response length {message.Length}, IsExpected {message.Length == ResponseLength}"); + Encoding.ASCII.GetBytes(message, 0, ResponseLength, responseBuffer, 0); + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerHandshake.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerHandshake.cs.meta new file mode 100644 index 0000000..6fa74da --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerHandshake.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6268509ac4fb48141b9944c03295da11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerSslHelper.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerSslHelper.cs new file mode 100644 index 0000000..fb45b13 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerSslHelper.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; + +namespace Mirror.SimpleWeb +{ + public struct SslConfig + { + public readonly bool enabled; + public readonly string certPath; + public readonly string certPassword; + public readonly SslProtocols sslProtocols; + + public SslConfig(bool enabled, string certPath, string certPassword, SslProtocols sslProtocols) + { + this.enabled = enabled; + this.certPath = certPath; + this.certPassword = certPassword; + this.sslProtocols = sslProtocols; + } + } + internal class ServerSslHelper + { + readonly SslConfig config; + readonly X509Certificate2 certificate; + + public ServerSslHelper(SslConfig sslConfig) + { + config = sslConfig; + if (config.enabled) + { + certificate = new X509Certificate2(config.certPath, config.certPassword); + Log.Info($"[SWT-ServerSslHelper]: SSL Certificate {certificate.Subject} loaded with expiration of {certificate.GetExpirationDateString()}"); + } + } + + internal bool TryCreateStream(Connection conn) + { + NetworkStream stream = conn.client.GetStream(); + if (config.enabled) + { + try + { + conn.stream = CreateStream(stream); + return true; + } + catch (Exception e) + { + Log.Error($"[SWT-ServerSslHelper]: Create SSLStream Failed: {e.Message}"); + return false; + } + } + else + { + conn.stream = stream; + return true; + } + } + + Stream CreateStream(NetworkStream stream) + { + SslStream sslStream = new SslStream(stream, true, acceptClient); + sslStream.AuthenticateAsServer(certificate, false, config.sslProtocols, false); + + return sslStream; + } + + // always accept client + bool acceptClient(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => true; + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerSslHelper.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerSslHelper.cs.meta new file mode 100644 index 0000000..e0d133c --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/ServerSslHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11061fee528ebdd43817a275b1e4a317 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/SimpleWebServer.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/SimpleWebServer.cs new file mode 100644 index 0000000..6ededeb --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/SimpleWebServer.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Mirror.SimpleWeb +{ + public class SimpleWebServer + { + public event Action onConnect; + public event Action onDisconnect; + public event Action> onData; + public event Action onError; + + readonly int maxMessagesPerTick; + readonly WebSocketServer server; + readonly BufferPool bufferPool; + + public bool Active { get; private set; } + + public SimpleWebServer(int maxMessagesPerTick, TcpConfig tcpConfig, int maxMessageSize, int handshakeMaxSize, SslConfig sslConfig) + { + this.maxMessagesPerTick = maxMessagesPerTick; + // use max because bufferpool is used for both messages and handshake + int max = Math.Max(maxMessageSize, handshakeMaxSize); + bufferPool = new BufferPool(5, 20, max); + server = new WebSocketServer(tcpConfig, maxMessageSize, handshakeMaxSize, sslConfig, bufferPool); + } + + public void Start(ushort port) + { + server.Listen(port); + Active = true; + } + + public void Stop() + { + server.Stop(); + Active = false; + } + + public void SendAll(List connectionIds, ArraySegment source) + { + ArrayBuffer buffer = bufferPool.Take(source.Count); + buffer.CopyFrom(source); + buffer.SetReleasesRequired(connectionIds.Count); + + // make copy of array before for each, data sent to each client is the same + foreach (int id in connectionIds) + server.Send(id, buffer); + } + + public void SendOne(int connectionId, ArraySegment source) + { + ArrayBuffer buffer = bufferPool.Take(source.Count); + buffer.CopyFrom(source); + server.Send(connectionId, buffer); + } + + public bool KickClient(int connectionId) => server.CloseConnection(connectionId); + + public string GetClientAddress(int connectionId) => server.GetClientAddress(connectionId); + + public Request GetClientRequest(int connectionId) => server.GetClientRequest(connectionId); + + /// + /// Processes all new messages + /// + public void ProcessMessageQueue() + { + ProcessMessageQueue(null); + } + + /// + /// Processes all messages while is enabled + /// + /// + public void ProcessMessageQueue(MonoBehaviour behaviour) + { + int processedCount = 0; + bool skipEnabled = behaviour == null; + // check enabled every time in case behaviour was disabled after data + while ( + (skipEnabled || behaviour.enabled) && + processedCount < maxMessagesPerTick && + // Dequeue last + server.receiveQueue.TryDequeue(out Message next) + ) + { + processedCount++; + + switch (next.type) + { + case EventType.Connected: + onConnect?.Invoke(next.connId); + break; + case EventType.Data: + onData?.Invoke(next.connId, next.data.ToSegment()); + next.data.Release(); + break; + case EventType.Disconnected: + onDisconnect?.Invoke(next.connId); + break; + case EventType.Error: + onError?.Invoke(next.connId, next.exception); + break; + } + } + + if (server.receiveQueue.Count > 0) + { + Log.Warn($"[SWT-SimpleWebServer]: ProcessMessageQueue has {server.receiveQueue.Count} remaining."); + } + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/SimpleWebServer.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/SimpleWebServer.cs.meta new file mode 100644 index 0000000..c8c6f5a --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/SimpleWebServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd51d7896f55a5e48b41a4b526562b0e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/WebSocketServer.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/WebSocketServer.cs new file mode 100644 index 0000000..c8895a2 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/WebSocketServer.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Concurrent; +using System.Linq; +using System.Net.Sockets; +using System.Threading; + +namespace Mirror.SimpleWeb +{ + public class WebSocketServer + { + public readonly ConcurrentQueue receiveQueue = new ConcurrentQueue(); + + readonly TcpConfig tcpConfig; + readonly int maxMessageSize; + + TcpListener listener; + Thread acceptThread; + bool serverStopped; + readonly ServerHandshake handShake; + readonly ServerSslHelper sslHelper; + readonly BufferPool bufferPool; + readonly ConcurrentDictionary connections = new ConcurrentDictionary(); + + int _idCounter = 0; + + public WebSocketServer(TcpConfig tcpConfig, int maxMessageSize, int handshakeMaxSize, SslConfig sslConfig, BufferPool bufferPool) + { + this.tcpConfig = tcpConfig; + this.maxMessageSize = maxMessageSize; + sslHelper = new ServerSslHelper(sslConfig); + this.bufferPool = bufferPool; + handShake = new ServerHandshake(this.bufferPool, handshakeMaxSize); + } + + public void Listen(int port) + { + listener = TcpListener.Create(port); + listener.Start(); + + Log.Verbose($"[SWT-WebSocketServer]: Server Started on {port}"); + + acceptThread = new Thread(acceptLoop); + acceptThread.IsBackground = true; + acceptThread.Start(); + } + + public void Stop() + { + serverStopped = true; + + // Interrupt then stop so that Exception is handled correctly + acceptThread?.Interrupt(); + listener?.Stop(); + acceptThread = null; + + Log.Verbose($"[SWT-WebSocketServer]: Server stopped...closing all connections."); + + // make copy so that foreach doesn't break if values are removed + Connection[] connectionsCopy = connections.Values.ToArray(); + foreach (Connection conn in connectionsCopy) + conn.Dispose(); + + connections.Clear(); + } + + void acceptLoop() + { + try + { + try + { + while (true) + { + TcpClient client = listener.AcceptTcpClient(); + tcpConfig.ApplyTo(client); + + // TODO keep track of connections before they are in connections dictionary + // this might not be a problem as HandshakeAndReceiveLoop checks for stop + // and returns/disposes before sending message to queue + Connection conn = new Connection(client, AfterConnectionDisposed); + Log.Verbose($"[SWT-WebSocketServer]: A client connected from {conn}"); + + // handshake needs its own thread as it needs to wait for message from client + Thread receiveThread = new Thread(() => HandshakeAndReceiveLoop(conn)); + + conn.receiveThread = receiveThread; + + receiveThread.IsBackground = true; + receiveThread.Start(); + } + } + catch (SocketException) + { + // check for Interrupted/Abort + Utils.CheckForInterupt(); + throw; + } + } + catch (ThreadInterruptedException e) { Log.InfoException(e); } + catch (ThreadAbortException e) { Log.InfoException(e); } + catch (Exception e) { Log.Exception(e); } + } + + void HandshakeAndReceiveLoop(Connection conn) + { + try + { + bool success = sslHelper.TryCreateStream(conn); + if (!success) + { + Log.Warn($"[SWT-WebSocketServer]: Failed to create SSL Stream {conn}"); + conn.Dispose(); + return; + } + + success = handShake.TryHandshake(conn); + + if (success) + Log.Verbose($"[SWT-WebSocketServer]: Sent Handshake {conn}, false"); + else + { + Log.Warn($"[SWT-WebSocketServer]: Handshake Failed {conn}"); + conn.Dispose(); + return; + } + + // check if Stop has been called since accepting this client + if (serverStopped) + { + Log.Warn("[SWT-WebSocketServer]: Server stopped after successful handshake"); + return; + } + + conn.connId = Interlocked.Increment(ref _idCounter); + connections.TryAdd(conn.connId, conn); + + receiveQueue.Enqueue(new Message(conn.connId, EventType.Connected)); + + Thread sendThread = new Thread(() => + { + SendLoop.Config sendConfig = new SendLoop.Config( + conn, + bufferSize: Constants.HeaderSize + maxMessageSize, + setMask: false); + + SendLoop.Loop(sendConfig); + }); + + conn.sendThread = sendThread; + sendThread.IsBackground = true; + sendThread.Name = $"SendThread {conn.connId}"; + sendThread.Start(); + + ReceiveLoop.Config receiveConfig = new ReceiveLoop.Config( + conn, + maxMessageSize, + expectMask: true, + receiveQueue, + bufferPool); + + ReceiveLoop.Loop(receiveConfig); + } + catch (ThreadInterruptedException e) + { + Log.Error($"[SWT-WebSocketServer]: Handshake ThreadInterruptedException {e.Message}"); + } + catch (ThreadAbortException e) + { + Log.Error($"[SWT-WebSocketServer]: Handshake ThreadAbortException {e.Message}"); + } + catch (Exception e) + { + Log.Error($"[SWT-WebSocketServer]: Handshake Exception {e.Message}"); + } + finally + { + // close here in case connect fails + conn.Dispose(); + } + } + + void AfterConnectionDisposed(Connection conn) + { + if (conn.connId != Connection.IdNotSet) + { + receiveQueue.Enqueue(new Message(conn.connId, EventType.Disconnected)); + connections.TryRemove(conn.connId, out Connection _); + } + } + + public void Send(int id, ArrayBuffer buffer) + { + if (connections.TryGetValue(id, out Connection conn)) + { + conn.sendQueue.Enqueue(buffer); + conn.sendPending.Set(); + } + else + Log.Warn($"[SWT-WebSocketServer]: Cannot send message to {id} because connection was not found in dictionary. Maybe it disconnected."); + } + + public bool CloseConnection(int id) + { + if (connections.TryGetValue(id, out Connection conn)) + { + Log.Info($"[SWT-WebSocketServer]: Disconnecting connection {id}"); + conn.Dispose(); + return true; + } + else + { + Log.Warn($"[SWT-WebSocketServer]: Failed to kick {id} because id not found."); + return false; + } + } + + public string GetClientAddress(int id) + { + if (!connections.TryGetValue(id, out Connection conn)) + { + Log.Warn($"[SWT-WebSocketServer]: Cannot get address of connection {id} because connection was not found in dictionary."); + return null; + } + + return conn.remoteAddress; + } + + public Request GetClientRequest(int id) + { + if (!connections.TryGetValue(id, out Connection conn)) + { + Log.Warn($"[SWT-WebSocketServer]: Cannot get request of connection {id} because connection was not found in dictionary."); + return null; + } + + return conn.request; + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/WebSocketServer.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/WebSocketServer.cs.meta new file mode 100644 index 0000000..0a76a9f --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/WebSocketServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c434db044777d2439bae5a57d4e8ee7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SimpleWebTransport.asmdef b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SimpleWebTransport.asmdef new file mode 100644 index 0000000..dfb91ea --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SimpleWebTransport.asmdef @@ -0,0 +1,14 @@ +{ + "name": "SimpleWebTransport", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SimpleWebTransport.asmdef.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SimpleWebTransport.asmdef.meta new file mode 100644 index 0000000..99755b6 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SimpleWebTransport.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3b5390adca4e2bb4791cb930316d6f3e +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SslConfigLoader.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SslConfigLoader.cs new file mode 100644 index 0000000..9996793 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SslConfigLoader.cs @@ -0,0 +1,49 @@ +using System.IO; +using System.Security.Authentication; +using UnityEngine; + +namespace Mirror.SimpleWeb +{ + + public class SslConfigLoader + { + internal struct Cert + { + public string path; + public string password; + } + public static SslConfig Load(bool sslEnabled, string sslCertJson, SslProtocols sslProtocols) + { + // don't need to load anything if ssl is not enabled + if (!sslEnabled) + return default; + + string certJsonPath = sslCertJson; + + Cert cert = LoadCertJson(certJsonPath); + + return new SslConfig( + enabled: sslEnabled, + sslProtocols: sslProtocols, + certPath: cert.path, + certPassword: cert.password + ); + } + + internal static Cert LoadCertJson(string certJsonPath) + { + string json = File.ReadAllText(certJsonPath); + Cert cert = JsonUtility.FromJson(json); + + if (string.IsNullOrWhiteSpace(cert.path)) + throw new InvalidDataException("Cert Json didn't not contain \"path\""); + + // don't use IsNullOrWhiteSpace here because whitespace could be a valid password for a cert + // password can also be empty + if (string.IsNullOrEmpty(cert.password)) + cert.password = string.Empty; + + return cert; + } + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SslConfigLoader.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SslConfigLoader.cs.meta new file mode 100644 index 0000000..e653532 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/SslConfigLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dfdb6b97a48a48b498e563e857342da1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWebTransport.cs b/Assets/Mirror/Transports/SimpleWeb/SimpleWebTransport.cs new file mode 100644 index 0000000..5990bc3 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWebTransport.cs @@ -0,0 +1,383 @@ +using System; +using System.Net; +using System.Security.Authentication; +using UnityEngine; +using UnityEngine.Serialization; + +namespace Mirror.SimpleWeb +{ + [DisallowMultipleComponent] + [HelpURL("https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport")] + public class SimpleWebTransport : Transport, PortTransport + { + public const string NormalScheme = "ws"; + public const string SecureScheme = "wss"; + + [Tooltip("Protect against allocation attacks by keeping the max message size small. Otherwise an attacker might send multiple fake packets with 2GB headers, causing the server to run out of memory after allocating multiple large packets.")] + public int maxMessageSize = 16 * 1024; + + [FormerlySerializedAs("handshakeMaxSize")] + [Tooltip("Max size for http header send as handshake for websockets")] + public int maxHandshakeSize = 3000; + + [FormerlySerializedAs("serverMaxMessagesPerTick")] + [Tooltip("Caps the number of messages the server will process per tick. Allows LateUpdate to finish to let the reset of unity continue in case more messages arrive before they are processed")] + public int serverMaxMsgsPerTick = 10000; + + [FormerlySerializedAs("clientMaxMessagesPerTick")] + [Tooltip("Caps the number of messages the client will process per tick. Allows LateUpdate to finish to let the reset of unity continue in case more messages arrive before they are processed")] + public int clientMaxMsgsPerTick = 1000; + + [Tooltip("Send would stall forever if the network is cut off during a send, so we need a timeout (in milliseconds)")] + public int sendTimeout = 5000; + + [Tooltip("How long without a message before disconnecting (in milliseconds)")] + public int receiveTimeout = 20000; + + [Tooltip("disables nagle algorithm. lowers CPU% and latency but increases bandwidth")] + public bool noDelay = true; + + [Header("Obsolete SSL settings")] + + [Tooltip("Requires wss connections on server, only to be used with SSL cert.json, never with reverse proxy.\nNOTE: if sslEnabled is true clientUseWss is forced true, even if not checked.")] + public bool sslEnabled; + + [Tooltip("Protocols that SSL certificate is created to support.")] + public SslProtocols sslProtocols = SslProtocols.Tls12; + + [Tooltip("Path to json file that contains path to cert and its password\nUse Json file so that cert password is not included in client builds\nSee Assets/Mirror/Transports/.cert.example.Json")] + public string sslCertJson = "./cert.json"; + + [Header("Server settings")] + + [Tooltip("Port to use for server")] + public ushort port = 7778; + public ushort Port + { + get + { +#if UNITY_WEBGL + if (clientWebsocketSettings.ClientPortOption == WebsocketPortOption.SpecifyPort) + return clientWebsocketSettings.CustomClientPort; + else + return port; +#else + return port; +#endif + } + set + { +#if UNITY_WEBGL + if (clientWebsocketSettings.ClientPortOption == WebsocketPortOption.SpecifyPort) + clientWebsocketSettings.CustomClientPort = value; + else + port = value; +#else + port = value; +#endif + } + } + + [Tooltip("Groups messages in queue before calling Stream.Send")] + public bool batchSend = true; + + [Tooltip("Waits for 1ms before grouping and sending messages.\n" + + "This gives time for mirror to finish adding message to queue so that less groups need to be made.\n" + + "If WaitBeforeSend is true then BatchSend Will also be set to true")] + public bool waitBeforeSend = true; + + [Header("Client settings")] + + [Tooltip("Sets connect scheme to wss. Useful when client needs to connect using wss when TLS is outside of transport.\nNOTE: if sslEnabled is true clientUseWss is also true")] + public bool clientUseWss; + public ClientWebsocketSettings clientWebsocketSettings; + + [Header("Logging")] + + [Tooltip("Choose minimum severity level for logging\nFlood level requires Debug build")] + [SerializeField] Log.Levels minimumLogLevel = Log.Levels.Warn; + + /// + /// Gets _logLevels field + /// Sets _logLevels and Log.level fields + /// + public Log.Levels LogLevels + { + get => minimumLogLevel; + set + { + minimumLogLevel = value; + Log.minLogLevel = minimumLogLevel; + } + } + + SimpleWebClient client; + SimpleWebServer server; + + TcpConfig TcpConfig => new TcpConfig(noDelay, sendTimeout, receiveTimeout); + + void Awake() + { + Log.minLogLevel = minimumLogLevel; + } + + public override string ToString() => $"SWT [{port}]"; + + void OnValidate() + { + Log.minLogLevel = minimumLogLevel; + } + + public override bool Available() => true; + + public override int GetMaxPacketSize(int channelId = 0) => maxMessageSize; + + public override void Shutdown() + { + client?.Disconnect(); + client = null; + server?.Stop(); + server = null; + } + + #region Client + + string GetClientScheme() => (sslEnabled || clientUseWss) ? SecureScheme : NormalScheme; + + public override bool ClientConnected() + { + // not null and not NotConnected (we want to return true if connecting or disconnecting) + return client != null && client.ConnectionState != ClientState.NotConnected; + } + + public override void ClientConnect(string hostname) + { + UriBuilder builder = new UriBuilder + { + Scheme = GetClientScheme(), + Host = hostname, + }; + + switch (clientWebsocketSettings.ClientPortOption) + { + case WebsocketPortOption.SpecifyPort: + builder.Port = clientWebsocketSettings.CustomClientPort; + break; + case WebsocketPortOption.MatchWebpageProtocol: + // not including a port in the builder allows the webpage to drive the port + // https://github.com/MirrorNetworking/Mirror/pull/3477 + break; + default: // default case handles ClientWebsocketPortOption.DefaultSameAsServerPort + builder.Port = port; + break; + } + + ClientConnect(builder.Uri); + } + + public override void ClientConnect(Uri uri) + { + // connecting or connected + if (ClientConnected()) + { + Log.Warn("[SWT-ClientConnect]: Already Connected"); + return; + } + + client = SimpleWebClient.Create(maxMessageSize, clientMaxMsgsPerTick, TcpConfig); + if (client == null) + return; + + client.onConnect += OnClientConnected.Invoke; + + client.onDisconnect += () => + { + OnClientDisconnected.Invoke(); + // clear client here after disconnect event has been sent + // there should be no more messages after disconnect + client = null; + }; + + client.onData += (ArraySegment data) => OnClientDataReceived.Invoke(data, Channels.Reliable); + + // We will not invoke OnClientError if minLogLevel is set to None + // We only send the full exception if minLogLevel is set to Verbose + switch (Log.minLogLevel) + { + case Log.Levels.Flood: + case Log.Levels.Verbose: + client.onError += (Exception e) => + { + OnClientError.Invoke(TransportError.Unexpected, e.ToString()); + ClientDisconnect(); + }; + break; + case Log.Levels.Info: + case Log.Levels.Warn: + case Log.Levels.Error: + client.onError += (Exception e) => + { + OnClientError.Invoke(TransportError.Unexpected, e.Message); + ClientDisconnect(); + }; + break; + } + + client.Connect(uri); + } + + public override void ClientDisconnect() + { + // don't set client null here of messages wont be processed + client?.Disconnect(); + } + + public override void ClientSend(ArraySegment segment, int channelId) + { + if (!ClientConnected()) + { + Log.Error("[SWT-ClientSend]: Not Connected"); + return; + } + + if (segment.Count > maxMessageSize) + { + Log.Error("[SWT-ClientSend]: Message greater than max size"); + return; + } + + if (segment.Count == 0) + { + Log.Error("[SWT-ClientSend]: Message count was zero"); + return; + } + + client.Send(segment); + + // call event. might be null if no statistics are listening etc. + OnClientDataSent?.Invoke(segment, Channels.Reliable); + } + + // messages should always be processed in early update + public override void ClientEarlyUpdate() + { + client?.ProcessMessageQueue(this); + } + + #endregion + + #region Server + + string GetServerScheme() => sslEnabled ? SecureScheme : NormalScheme; + + public override Uri ServerUri() + { + UriBuilder builder = new UriBuilder + { + Scheme = GetServerScheme(), + Host = Dns.GetHostName(), + Port = port + }; + return builder.Uri; + } + + public override bool ServerActive() + { + return server != null && server.Active; + } + + public override void ServerStart() + { + if (ServerActive()) + Log.Warn("[SWT-ServerStart]: Server Already Started"); + + SslConfig config = SslConfigLoader.Load(sslEnabled, sslCertJson, sslProtocols); + server = new SimpleWebServer(serverMaxMsgsPerTick, TcpConfig, maxMessageSize, maxHandshakeSize, config); + + server.onConnect += OnServerConnected.Invoke; + server.onDisconnect += OnServerDisconnected.Invoke; + server.onData += (int connId, ArraySegment data) => OnServerDataReceived.Invoke(connId, data, Channels.Reliable); + + // We will not invoke OnServerError if minLogLevel is set to None + // We only send the full exception if minLogLevel is set to Verbose + switch (Log.minLogLevel) + { + case Log.Levels.Flood: + case Log.Levels.Verbose: + server.onError += (connId, exception) => + { + OnServerError(connId, TransportError.Unexpected, exception.ToString()); + ServerDisconnect(connId); + }; + break; + case Log.Levels.Info: + case Log.Levels.Warn: + case Log.Levels.Error: + server.onError += (connId, exception) => + { + OnServerError(connId, TransportError.Unexpected, exception.Message); + ServerDisconnect(connId); + }; + break; + } + + SendLoopConfig.batchSend = batchSend || waitBeforeSend; + SendLoopConfig.sleepBeforeSend = waitBeforeSend; + + server.Start(port); + } + + public override void ServerStop() + { + if (ServerActive()) + { + server.Stop(); + server = null; + } + } + + public override void ServerDisconnect(int connectionId) + { + if (ServerActive()) + server.KickClient(connectionId); + } + + public override void ServerSend(int connectionId, ArraySegment segment, int channelId) + { + if (!ServerActive()) + { + Log.Error("[SWT-ServerSend]: Server Not Active"); + return; + } + + if (segment.Count > maxMessageSize) + { + Log.Error("[SWT-ServerSend]: Message greater than max size"); + return; + } + + if (segment.Count == 0) + { + Log.Error("[SWT-ServerSend]: Message count was zero"); + return; + } + + server.SendOne(connectionId, segment); + + // call event. might be null if no statistics are listening etc. + OnServerDataSent?.Invoke(connectionId, segment, Channels.Reliable); + } + + public override string ServerGetClientAddress(int connectionId) => server.GetClientAddress(connectionId); + + public Request ServerGetClientRequest(int connectionId) => server.GetClientRequest(connectionId); + + // messages should always be processed in early update + public override void ServerEarlyUpdate() + { + server?.ProcessMessageQueue(this); + } + + #endregion + } +} diff --git a/Assets/Mirror/Transports/SimpleWeb/SimpleWebTransport.cs.meta b/Assets/Mirror/Transports/SimpleWeb/SimpleWebTransport.cs.meta new file mode 100644 index 0000000..381a5c7 --- /dev/null +++ b/Assets/Mirror/Transports/SimpleWeb/SimpleWebTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0110f245bfcfc7d459681f7bd9ebc590 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy.meta b/Assets/Mirror/Transports/Telepathy.meta new file mode 100644 index 0000000..ede2d0e --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 552b3d8382916438d81fe7f39e18db72 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy.meta b/Assets/Mirror/Transports/Telepathy/Telepathy.meta new file mode 100644 index 0000000..345a638 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a1233408bc4b145fb8f6f5a8e95790e0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Client.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/Client.cs new file mode 100644 index 0000000..b2a1c85 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Client.cs @@ -0,0 +1,361 @@ +using System; +using System.Net.Sockets; +using System.Threading; + +namespace Telepathy +{ + // ClientState OBJECT that can be handed to the ReceiveThread safely. + // => allows us to create a NEW OBJECT every time we connect and start a + // receive thread. + // => perfectly protects us against data races. fixes all the flaky tests + // where .Connecting or .client would still be used by a dieing thread + // while attempting to use it for a new connection attempt etc. + // => creating a fresh client state each time is the best solution against + // data races here! + class ClientConnectionState : ConnectionState + { + public Thread receiveThread; + + // TcpClient.Connected doesn't check if socket != null, which + // results in NullReferenceExceptions if connection was closed. + // -> let's check it manually instead + public bool Connected => client != null && + client.Client != null && + client.Client.Connected; + + // TcpClient has no 'connecting' state to check. We need to keep track + // of it manually. + // -> checking 'thread.IsAlive && !Connected' is not enough because the + // thread is alive and connected is false for a short moment after + // disconnecting, so this would cause race conditions. + // -> we use a threadsafe bool wrapper so that ThreadFunction can remain + // static (it needs a common lock) + // => Connecting is true from first Connect() call in here, through the + // thread start, until TcpClient.Connect() returns. Simple and clear. + // => bools are atomic according to + // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/variables + // made volatile so the compiler does not reorder access to it + public volatile bool Connecting; + + // thread safe pipe for received messages + // => inside client connection state so that we can create a new state + // each time we connect + // (unlike server which has one receive pipe for all connections) + public readonly MagnificentReceivePipe receivePipe; + + // constructor always creates new TcpClient for client connection! + public ClientConnectionState(int MaxMessageSize) : base(new TcpClient(), MaxMessageSize) + { + // create receive pipe with max message size for pooling + receivePipe = new MagnificentReceivePipe(MaxMessageSize); + } + + // dispose all the state safely + public void Dispose() + { + // close client + client.Close(); + + // wait until thread finished. this is the only way to guarantee + // that we can call Connect() again immediately after Disconnect + // -> calling .Join would sometimes wait forever, e.g. when + // calling Disconnect while trying to connect to a dead end + receiveThread?.Interrupt(); + + // we interrupted the receive Thread, so we can't guarantee that + // connecting was reset. let's do it manually. + Connecting = false; + + // clear send pipe. no need to hold on to elements. + // (unlike receiveQueue, which is still needed to process the + // latest Disconnected message, etc.) + sendPipe.Clear(); + + // IMPORTANT: DO NOT CLEAR RECEIVE PIPE. + // we still want to process disconnect messages in Tick()! + + // let go of this client completely. the thread ended, no one uses + // it anymore and this way Connected is false again immediately. + client = null; + } + } + + public class Client : Common + { + // events to hook into + // => OnData uses ArraySegment for allocation free receives later + public Action OnConnected; + public Action> OnData; + public Action OnDisconnected; + + // disconnect if send queue gets too big. + // -> avoids ever growing queue memory if network is slower than input + // -> disconnecting is great for load balancing. better to disconnect + // one connection than risking every connection / the whole server + // -> huge queue would introduce multiple seconds of latency anyway + // + // Mirror/DOTSNET use MaxMessageSize batching, so for a 16kb max size: + // limit = 1,000 means 16 MB of memory/connection + // limit = 10,000 means 160 MB of memory/connection + public int SendQueueLimit = 10000; + public int ReceiveQueueLimit = 10000; + + // all client state wrapped into an object that is passed to ReceiveThread + // => we create a new one each time we connect to avoid data races with + // old dieing threads still using the previous object! + ClientConnectionState state; + + // Connected & Connecting + public bool Connected => state != null && state.Connected; + public bool Connecting => state != null && state.Connecting; + + // pipe count, useful for debugging / benchmarks + public int ReceivePipeCount => state != null ? state.receivePipe.TotalCount : 0; + + // constructor + public Client(int MaxMessageSize) : base(MaxMessageSize) {} + + // the thread function + // STATIC to avoid sharing state! + // => pass ClientState object. a new one is created for each new thread! + // => avoids data races where an old dieing thread might still modify + // the current thread's state :/ + static void ReceiveThreadFunction(ClientConnectionState state, string ip, int port, int MaxMessageSize, bool NoDelay, int SendTimeout, int ReceiveTimeout, int ReceiveQueueLimit) + + { + Thread sendThread = null; + + // absolutely must wrap with try/catch, otherwise thread + // exceptions are silent + try + { + // connect (blocking) + state.client.Connect(ip, port); + state.Connecting = false; // volatile! + + // set socket options after the socket was created in Connect() + // (not after the constructor because we clear the socket there) + state.client.NoDelay = NoDelay; + state.client.SendTimeout = SendTimeout; + state.client.ReceiveTimeout = ReceiveTimeout; + + // start send thread only after connected + // IMPORTANT: DO NOT SHARE STATE ACROSS MULTIPLE THREADS! + sendThread = new Thread(() => { ThreadFunctions.SendLoop(0, state.client, state.sendPipe, state.sendPending); }); + sendThread.IsBackground = true; + sendThread.Start(); + + // run the receive loop + // (receive pipe is shared across all loops) + ThreadFunctions.ReceiveLoop(0, state.client, MaxMessageSize, state.receivePipe, ReceiveQueueLimit); + } + catch (SocketException exception) + { + // this happens if (for example) the ip address is correct + // but there is no server running on that ip/port + Log.Info("Client Recv: failed to connect to ip=" + ip + " port=" + port + " reason=" + exception); + } + catch (ThreadInterruptedException) + { + // expected if Disconnect() aborts it + } + catch (ThreadAbortException) + { + // expected if Disconnect() aborts it + } + catch (ObjectDisposedException) + { + // expected if Disconnect() aborts it and disposed the client + // while ReceiveThread is in a blocking Connect() call + } + catch (Exception exception) + { + // something went wrong. probably important. + Log.Error("Client Recv Exception: " + exception); + } + // add 'Disconnected' event to receive pipe so that the caller + // knows that the Connect failed. otherwise they will never know + state.receivePipe.Enqueue(0, EventType.Disconnected, default); + + // sendthread might be waiting on ManualResetEvent, + // so let's make sure to end it if the connection + // closed. + // otherwise the send thread would only end if it's + // actually sending data while the connection is + // closed. + sendThread?.Interrupt(); + + // Connect might have failed. thread might have been closed. + // let's reset connecting state no matter what. + state.Connecting = false; + + // if we got here then we are done. ReceiveLoop cleans up already, + // but we may never get there if connect fails. so let's clean up + // here too. + state.client?.Close(); + } + + public void Connect(string ip, int port) + { + // not if already started + if (Connecting || Connected) + { + Log.Warning("Telepathy Client can not create connection because an existing connection is connecting or connected"); + return; + } + + // overwrite old thread's state object. create a new one to avoid + // data races where an old dieing thread might still modify the + // current state! fixes all the flaky tests! + state = new ClientConnectionState(MaxMessageSize); + + // We are connecting from now until Connect succeeds or fails + state.Connecting = true; + + // create a TcpClient with perfect IPv4, IPv6 and hostname resolving + // support. + // + // * TcpClient(hostname, port): works but would connect (and block) + // already + // * TcpClient(AddressFamily.InterNetworkV6): takes Ipv4 and IPv6 + // addresses but only connects to IPv6 servers (e.g. Telepathy). + // does NOT connect to IPv4 servers (e.g. Mirror Booster), even + // with DualMode enabled. + // * TcpClient(): creates IPv4 socket internally, which would force + // Connect() to only use IPv4 sockets. + // + // => the trick is to clear the internal IPv4 socket so that Connect + // resolves the hostname and creates either an IPv4 or an IPv6 + // socket as needed (see TcpClient source) + state.client.Client = null; // clear internal IPv4 socket until Connect() + + // client.Connect(ip, port) is blocking. let's call it in the thread + // and return immediately. + // -> this way the application doesn't hang for 30s if connect takes + // too long, which is especially good in games + // -> this way we don't async client.BeginConnect, which seems to + // fail sometimes if we connect too many clients too fast + state.receiveThread = new Thread(() => { + ReceiveThreadFunction(state, ip, port, MaxMessageSize, NoDelay, SendTimeout, ReceiveTimeout, ReceiveQueueLimit); + }); + state.receiveThread.IsBackground = true; + state.receiveThread.Start(); + } + + public void Disconnect() + { + // only if started + if (Connecting || Connected) + { + // dispose all the state safely + state.Dispose(); + + // IMPORTANT: DO NOT set state = null! + // we still want to process the pipe's disconnect message etc.! + } + } + + // send message to server using socket connection. + // arraysegment for allocation free sends later. + // -> the segment's array is only used until Send() returns! + public bool Send(ArraySegment message) + { + if (Connected) + { + // respect max message size to avoid allocation attacks. + if (message.Count <= MaxMessageSize) + { + // check send pipe limit + if (state.sendPipe.Count < SendQueueLimit) + { + // add to thread safe send pipe and return immediately. + // calling Send here would be blocking (sometimes for long + // times if other side lags or wire was disconnected) + state.sendPipe.Enqueue(message); + state.sendPending.Set(); // interrupt SendThread WaitOne() + return true; + } + // disconnect if send queue gets too big. + // -> avoids ever growing queue memory if network is slower + // than input + // -> avoids ever growing latency as well + // + // note: while SendThread always grabs the WHOLE send queue + // immediately, it's still possible that the sending + // blocks for so long that the send queue just gets + // way too big. have a limit - better safe than sorry. + else + { + // log the reason + Log.Warning($"Client.Send: sendPipe reached limit of {SendQueueLimit}. This can happen if we call send faster than the network can process messages. Disconnecting to avoid ever growing memory & latency."); + + // just close it. send thread will take care of the rest. + state.client.Close(); + return false; + } + } + Log.Error("Client.Send: message too big: " + message.Count + ". Limit: " + MaxMessageSize); + return false; + } + Log.Warning("Client.Send: not connected!"); + return false; + } + + // tick: processes up to 'limit' messages + // => limit parameter to avoid deadlocks / too long freezes if server or + // client is too slow to process network load + // => Mirror & DOTSNET need to have a process limit anyway. + // might as well do it here and make life easier. + // => returns amount of remaining messages to process, so the caller + // can call tick again as many times as needed (or up to a limit) + // + // Tick() may process multiple messages, but Mirror needs a way to stop + // processing immediately if a scene change messages arrives. Mirror + // can't process any other messages during a scene change. + // (could be useful for others too) + // => make sure to allocate the lambda only once in transports + public int Tick(int processLimit, Func checkEnabled = null) + { + // only if state was created yet (after connect()) + // note: we don't check 'only if connected' because we want to still + // process Disconnect messages afterwards too! + if (state == null) + return 0; + + // process up to 'processLimit' messages + for (int i = 0; i < processLimit; ++i) + { + // check enabled in case a Mirror scene message arrived + if (checkEnabled != null && !checkEnabled()) + break; + + // peek first. allows us to process the first queued entry while + // still keeping the pooled byte[] alive by not removing anything. + if (state.receivePipe.TryPeek(out int _, out EventType eventType, out ArraySegment message)) + { + switch (eventType) + { + case EventType.Connected: + OnConnected?.Invoke(); + break; + case EventType.Data: + OnData?.Invoke(message); + break; + case EventType.Disconnected: + OnDisconnected?.Invoke(); + break; + } + + // IMPORTANT: now dequeue and return it to pool AFTER we are + // done processing the event. + state.receivePipe.TryDequeue(); + } + // no more messages. stop the loop. + else break; + } + + // return what's left to process for next time + return state.receivePipe.TotalCount; + } + } +} diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Client.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/Client.cs.meta new file mode 100644 index 0000000..1b6d222 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Client.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a5b95294cc4ec4b15aacba57531c7985 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Common.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/Common.cs new file mode 100644 index 0000000..15265f9 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Common.cs @@ -0,0 +1,39 @@ +// common code used by server and client +namespace Telepathy +{ + public abstract class Common + { + // IMPORTANT: DO NOT SHARE STATE ACROSS SEND/RECV LOOPS (DATA RACES) + // (except receive pipe which is used for all threads) + + // NoDelay disables nagle algorithm. lowers CPU% and latency but + // increases bandwidth + public bool NoDelay = true; + + // Prevent allocation attacks. Each packet is prefixed with a length + // header, so an attacker could send a fake packet with length=2GB, + // causing the server to allocate 2GB and run out of memory quickly. + // -> simply increase max packet size if you want to send around bigger + // files! + // -> 16KB per message should be more than enough. + public readonly int MaxMessageSize; + + // Send would stall forever if the network is cut off during a send, so + // we need a timeout (in milliseconds) + public int SendTimeout = 5000; + + // Default TCP receive time out can be huge (minutes). + // That's way too much for games, let's make it configurable. + // we need a timeout (in milliseconds) + // => '0' means disabled + // => disabled by default because some people might use Telepathy + // without Mirror and without sending pings, so timeouts are likely + public int ReceiveTimeout = 0; + + // constructor + protected Common(int MaxMessageSize) + { + this.MaxMessageSize = MaxMessageSize; + } + } +} diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Common.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/Common.cs.meta new file mode 100644 index 0000000..5d8ab5b --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Common.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4d56322cf0e248a89103c002a505dab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/ConnectionState.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/ConnectionState.cs new file mode 100644 index 0000000..cdfe3c0 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/ConnectionState.cs @@ -0,0 +1,35 @@ +// both server and client need a connection state object. +// -> server needs it to keep track of multiple connections +// -> client needs it to safely create a new connection state on every new +// connect in order to avoid data races where a dieing thread might still +// modify the current state. can't happen if we create a new state each time! +// (fixes all the flaky tests) +// +// ... besides, it also allows us to share code! +using System.Net.Sockets; +using System.Threading; + +namespace Telepathy +{ + public class ConnectionState + { + public TcpClient client; + + // thread safe pipe to send messages from main thread to send thread + public readonly MagnificentSendPipe sendPipe; + + // ManualResetEvent to wake up the send thread. better than Thread.Sleep + // -> call Set() if everything was sent + // -> call Reset() if there is something to send again + // -> call WaitOne() to block until Reset was called + public ManualResetEvent sendPending = new ManualResetEvent(false); + + public ConnectionState(TcpClient client, int MaxMessageSize) + { + this.client = client; + + // create send pipe with max message size for pooling + sendPipe = new MagnificentSendPipe(MaxMessageSize); + } + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/ConnectionState.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/ConnectionState.cs.meta new file mode 100644 index 0000000..3dcceaf --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/ConnectionState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af95e2b6f6343411aa8bdf871abd7b1b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/EventType.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/EventType.cs new file mode 100644 index 0000000..66bc3b4 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/EventType.cs @@ -0,0 +1,9 @@ +namespace Telepathy +{ + public enum EventType + { + Connected, + Data, + Disconnected + } +} diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/EventType.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/EventType.cs.meta new file mode 100644 index 0000000..ac88c1b --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/EventType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 49f1a330755814803be5f27f493e1910 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/LICENSE b/Assets/Mirror/Transports/Telepathy/Telepathy/LICENSE new file mode 100644 index 0000000..680deef --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018, vis2k + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/LICENSE.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/LICENSE.meta new file mode 100644 index 0000000..4d7664e --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0ba11103b95fd4721bffbb08440d5b8e +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Log.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/Log.cs new file mode 100644 index 0000000..2d50aa3 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Log.cs @@ -0,0 +1,15 @@ +// A simple logger class that uses Console.WriteLine by default. +// Can also do Logger.LogMethod = Debug.Log for Unity etc. +// (this way we don't have to depend on UnityEngine.DLL and don't need a +// different version for every UnityEngine version here) +using System; + +namespace Telepathy +{ + public static class Log + { + public static Action Info = Console.WriteLine; + public static Action Warning = Console.WriteLine; + public static Action Error = Console.Error.WriteLine; + } +} diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Log.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/Log.cs.meta new file mode 100644 index 0000000..8f78650 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Log.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0a123d054bef34d059057ac2ce936605 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentReceivePipe.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentReceivePipe.cs new file mode 100644 index 0000000..2e10318 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentReceivePipe.cs @@ -0,0 +1,222 @@ +// a magnificent receive pipe to shield us from all of life's complexities. +// safely sends messages from receive thread to main thread. +// -> thread safety built in +// -> byte[] pooling coming in the future +// +// => hides all the complexity from telepathy +// => easy to switch between stack/queue/concurrentqueue/etc. +// => easy to test +using System; +using System.Collections.Generic; + +namespace Telepathy +{ + public class MagnificentReceivePipe + { + // queue entry message. only used in here. + // -> byte arrays are always of 4 + MaxMessageSize + // -> ArraySegment indicates the actual message content + struct Entry + { + public int connectionId; + public EventType eventType; + public ArraySegment data; + public Entry(int connectionId, EventType eventType, ArraySegment data) + { + this.connectionId = connectionId; + this.eventType = eventType; + this.data = data; + } + } + + // message queue + // ConcurrentQueue allocates. lock{} instead. + // + // IMPORTANT: lock{} all usages! + readonly Queue queue = new Queue(); + + // byte[] pool to avoid allocations + // Take & Return is beautifully encapsulated in the pipe. + // the outside does not need to worry about anything. + // and it can be tested easily. + // + // IMPORTANT: lock{} all usages! + Pool pool; + + // unfortunately having one receive pipe per connetionId is way slower + // in CCU tests. right now we have one pipe for all connections. + // => we still need to limit queued messages per connection to avoid one + // spamming connection being able to slow down everyone else since + // the queue would be full of just this connection's messages forever + // => let's use a simpler per-connectionId counter for now + Dictionary queueCounter = new Dictionary(); + + // constructor + public MagnificentReceivePipe(int MaxMessageSize) + { + // initialize pool to create max message sized byte[]s each time + pool = new Pool(() => new byte[MaxMessageSize]); + } + + // return amount of queued messages for this connectionId. + // for statistics. don't call Count and assume that it's the same after + // the call. + public int Count(int connectionId) + { + lock (this) + { + return queueCounter.TryGetValue(connectionId, out int count) + ? count + : 0; + } + } + + // total count + public int TotalCount + { + get { lock (this) { return queue.Count; } } + } + + // pool count for testing + public int PoolCount + { + get { lock (this) { return pool.Count(); } } + } + + // enqueue a message + // -> ArraySegment to avoid allocations later + // -> parameters passed directly so it's more obvious that we don't just + // queue a passed 'Message', instead we copy the ArraySegment into + // a byte[] and store it internally, etc.) + public void Enqueue(int connectionId, EventType eventType, ArraySegment message) + { + // pool & queue usage always needs to be locked + lock (this) + { + // does this message have a data array content? + ArraySegment segment = default; + if (message != default) + { + // ArraySegment is only valid until returning. + // copy it into a byte[] that we can store. + // ArraySegment array is only valid until returning, so copy + // it into a byte[] that we can queue safely. + + // get one from the pool first to avoid allocations + byte[] bytes = pool.Take(); + + // copy into it + Buffer.BlockCopy(message.Array, message.Offset, bytes, 0, message.Count); + + // indicate which part is the message + segment = new ArraySegment(bytes, 0, message.Count); + } + + // enqueue it + // IMPORTANT: pass the segment around pool byte[], + // NOT the 'message' that is only valid until returning! + Entry entry = new Entry(connectionId, eventType, segment); + queue.Enqueue(entry); + + // increase counter for this connectionId + int oldCount = Count(connectionId); + queueCounter[connectionId] = oldCount + 1; + } + } + + // peek the next message + // -> allows the caller to process it while pipe still holds on to the + // byte[] + // -> TryDequeue should be called after processing, so that the message + // is actually dequeued and the byte[] is returned to pool! + // => see TryDequeue comments! + // + // IMPORTANT: TryPeek & Dequeue need to be called from the SAME THREAD! + public bool TryPeek(out int connectionId, out EventType eventType, out ArraySegment data) + { + connectionId = 0; + eventType = EventType.Disconnected; + data = default; + + // pool & queue usage always needs to be locked + lock (this) + { + if (queue.Count > 0) + { + Entry entry = queue.Peek(); + connectionId = entry.connectionId; + eventType = entry.eventType; + data = entry.data; + return true; + } + return false; + } + } + + // dequeue the next message + // -> simply dequeues and returns the byte[] to pool (if any) + // -> use Peek to actually process the first element while the pipe + // still holds on to the byte[] + // -> doesn't return the element because the byte[] needs to be returned + // to the pool in dequeue. caller can't be allowed to work with a + // byte[] that is already returned to pool. + // => Peek & Dequeue is the most simple, clean solution for receive + // pipe pooling to avoid allocations! + // + // IMPORTANT: TryPeek & Dequeue need to be called from the SAME THREAD! + public bool TryDequeue() + { + // pool & queue usage always needs to be locked + lock (this) + { + if (queue.Count > 0) + { + // dequeue from queue + Entry entry = queue.Dequeue(); + + // return byte[] to pool (if any). + // not all message types have byte[] contents. + if (entry.data != default) + { + pool.Return(entry.data.Array); + } + + // decrease counter for this connectionId + queueCounter[entry.connectionId]--; + + // remove if zero. don't want to keep old connectionIds in + // there forever, it would cause slowly growing memory. + if (queueCounter[entry.connectionId] == 0) + queueCounter.Remove(entry.connectionId); + + return true; + } + return false; + } + } + + public void Clear() + { + // pool & queue usage always needs to be locked + lock (this) + { + // clear queue, but via dequeue to return each byte[] to pool + while (queue.Count > 0) + { + // dequeue + Entry entry = queue.Dequeue(); + + // return byte[] to pool (if any). + // not all message types have byte[] contents. + if (entry.data != default) + { + pool.Return(entry.data.Array); + } + } + + // clear counter too + queueCounter.Clear(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentReceivePipe.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentReceivePipe.cs.meta new file mode 100644 index 0000000..614bab6 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentReceivePipe.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 010a208972a9a4e0cb0e7c18a60b4494 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentSendPipe.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentSendPipe.cs new file mode 100644 index 0000000..be456a0 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentSendPipe.cs @@ -0,0 +1,165 @@ +// a magnificent send pipe to shield us from all of life's complexities. +// safely sends messages from main thread to send thread. +// -> thread safety built in +// -> byte[] pooling coming in the future +// +// => hides all the complexity from telepathy +// => easy to switch between stack/queue/concurrentqueue/etc. +// => easy to test + +using System; +using System.Collections.Generic; + +namespace Telepathy +{ + public class MagnificentSendPipe + { + // message queue + // ConcurrentQueue allocates. lock{} instead. + // -> byte arrays are always of MaxMessageSize + // -> ArraySegment indicates the actual message content + // + // IMPORTANT: lock{} all usages! + readonly Queue> queue = new Queue>(); + + // byte[] pool to avoid allocations + // Take & Return is beautifully encapsulated in the pipe. + // the outside does not need to worry about anything. + // and it can be tested easily. + // + // IMPORTANT: lock{} all usages! + Pool pool; + + // constructor + public MagnificentSendPipe(int MaxMessageSize) + { + // initialize pool to create max message sized byte[]s each time + pool = new Pool(() => new byte[MaxMessageSize]); + } + + // for statistics. don't call Count and assume that it's the same after + // the call. + public int Count + { + get { lock (this) { return queue.Count; } } + } + + // pool count for testing + public int PoolCount + { + get { lock (this) { return pool.Count(); } } + } + + // enqueue a message + // arraysegment for allocation free sends later. + // -> the segment's array is only used until Enqueue() returns! + public void Enqueue(ArraySegment message) + { + // pool & queue usage always needs to be locked + lock (this) + { + // ArraySegment array is only valid until returning, so copy + // it into a byte[] that we can queue safely. + + // get one from the pool first to avoid allocations + byte[] bytes = pool.Take(); + + // copy into it + Buffer.BlockCopy(message.Array, message.Offset, bytes, 0, message.Count); + + // indicate which part is the message + ArraySegment segment = new ArraySegment(bytes, 0, message.Count); + + // now enqueue it + queue.Enqueue(segment); + } + } + + // send threads need to dequeue each byte[] and write it into the socket + // -> dequeueing one byte[] after another works, but it's WAY slower + // than dequeueing all immediately (locks only once) + // lock{} & DequeueAll is WAY faster than ConcurrentQueue & dequeue + // one after another: + // + // uMMORPG 450 CCU + // SafeQueue: 900-1440ms latency + // ConcurrentQueue: 2000ms latency + // + // -> the most obvious solution is to just return a list with all byte[] + // (which allocates) and then write each one into the socket + // -> a faster solution is to serialize each one into one payload buffer + // and pass that to the socket only once. fewer socket calls always + // give WAY better CPU performance(!) + // -> to avoid allocating a new list of entries each time, we simply + // serialize all entries into the payload here already + // => having all this complexity built into the pipe makes testing and + // modifying the algorithm super easy! + // + // IMPORTANT: serializing in here will allow us to return the byte[] + // entries back to a pool later to completely avoid + // allocations! + public bool DequeueAndSerializeAll(ref byte[] payload, out int packetSize) + { + // pool & queue usage always needs to be locked + lock (this) + { + // do nothing if empty + packetSize = 0; + if (queue.Count == 0) + return false; + + // we might have multiple pending messages. merge into one + // packet to avoid TCP overheads and improve performance. + // + // IMPORTANT: Mirror & DOTSNET already batch into MaxMessageSize + // chunks, but we STILL pack all pending messages + // into one large payload so we only give it to TCP + // ONCE. This is HUGE for performance so we keep it! + packetSize = 0; + foreach (ArraySegment message in queue) + packetSize += 4 + message.Count; // header + content + + // create payload buffer if not created yet or previous one is + // too small + // IMPORTANT: payload.Length might be > packetSize! don't use it! + if (payload == null || payload.Length < packetSize) + payload = new byte[packetSize]; + + // dequeue all byte[] messages and serialize into the packet + int position = 0; + while (queue.Count > 0) + { + // dequeue + ArraySegment message = queue.Dequeue(); + + // write header (size) into buffer at position + Utils.IntToBytesBigEndianNonAlloc(message.Count, payload, position); + position += 4; + + // copy message into payload at position + Buffer.BlockCopy(message.Array, message.Offset, payload, position, message.Count); + position += message.Count; + + // return to pool so it can be reused (avoids allocations!) + pool.Return(message.Array); + } + + // we did serialize something + return true; + } + } + + public void Clear() + { + // pool & queue usage always needs to be locked + lock (this) + { + // clear queue, but via dequeue to return each byte[] to pool + while (queue.Count > 0) + { + pool.Return(queue.Dequeue().Array); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentSendPipe.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentSendPipe.cs.meta new file mode 100644 index 0000000..cf1415f --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/MagnificentSendPipe.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d490021c2e6a64374bc88168cec75c70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/NetworkStreamExtensions.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/NetworkStreamExtensions.cs new file mode 100644 index 0000000..7cfd73c --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/NetworkStreamExtensions.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Net.Sockets; + +namespace Telepathy +{ + public static class NetworkStreamExtensions + { + // .Read returns '0' if remote closed the connection but throws an + // IOException if we voluntarily closed our own connection. + // + // let's add a ReadSafely method that returns '0' in both cases so we don't + // have to worry about exceptions, since a disconnect is a disconnect... + public static int ReadSafely(this NetworkStream stream, byte[] buffer, int offset, int size) + { + try + { + return stream.Read(buffer, offset, size); + } + // IOException happens if we voluntarily closed our own connection. + catch (IOException) + { + return 0; + } + // ObjectDisposedException can be thrown if Client.Disconnect() + // disposes the stream, while we are still trying to read here. + // catching it fixes https://github.com/vis2k/Telepathy/pull/104 + catch (ObjectDisposedException) + { + return 0; + } + } + + // helper function to read EXACTLY 'n' bytes + // -> default .Read reads up to 'n' bytes. this function reads exactly + // 'n' bytes + // -> this is blocking until 'n' bytes were received + // -> immediately returns false in case of disconnects + public static bool ReadExactly(this NetworkStream stream, byte[] buffer, int amount) + { + // there might not be enough bytes in the TCP buffer for .Read to read + // the whole amount at once, so we need to keep trying until we have all + // the bytes (blocking) + // + // note: this just is a faster version of reading one after another: + // for (int i = 0; i < amount; ++i) + // if (stream.Read(buffer, i, 1) == 0) + // return false; + // return true; + int bytesRead = 0; + while (bytesRead < amount) + { + // read up to 'remaining' bytes with the 'safe' read extension + int remaining = amount - bytesRead; + int result = stream.ReadSafely(buffer, bytesRead, remaining); + + // .Read returns 0 if disconnected + if (result == 0) + return false; + + // otherwise add to bytes read + bytesRead += result; + } + return true; + } + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/NetworkStreamExtensions.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/NetworkStreamExtensions.cs.meta new file mode 100644 index 0000000..e7e5744 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/NetworkStreamExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a8076c43fa8d4d45831adae232d4d3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Pool.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/Pool.cs new file mode 100644 index 0000000..4ec4fd2 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Pool.cs @@ -0,0 +1,34 @@ +// pool to avoid allocations. originally from libuv2k. +using System; +using System.Collections.Generic; + +namespace Telepathy +{ + public class Pool + { + // objects + readonly Stack objects = new Stack(); + + // some types might need additional parameters in their constructor, so + // we use a Func generator + readonly Func objectGenerator; + + // constructor + public Pool(Func objectGenerator) + { + this.objectGenerator = objectGenerator; + } + + // take an element from the pool, or create a new one if empty + public T Take() => objects.Count > 0 ? objects.Pop() : objectGenerator(); + + // return an element to the pool + public void Return(T item) => objects.Push(item); + + // clear the pool with the disposer function applied to each object + public void Clear() => objects.Clear(); + + // count to see how many objects are in the pool. useful for tests. + public int Count() => objects.Count; + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Pool.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/Pool.cs.meta new file mode 100644 index 0000000..9a7dafc --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Pool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6d3e530f6872642ec81e9b8b76277c93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Server.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/Server.cs new file mode 100644 index 0000000..0b4ada7 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Server.cs @@ -0,0 +1,401 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +namespace Telepathy +{ + public class Server : Common + { + // events to hook into + // => OnData uses ArraySegment for allocation free receives later + public Action OnConnected; + public Action> OnData; + public Action OnDisconnected; + + // listener + public TcpListener listener; + Thread listenerThread; + + // disconnect if send queue gets too big. + // -> avoids ever growing queue memory if network is slower than input + // -> disconnecting is great for load balancing. better to disconnect + // one connection than risking every connection / the whole server + // -> huge queue would introduce multiple seconds of latency anyway + // + // Mirror/DOTSNET use MaxMessageSize batching, so for a 16kb max size: + // limit = 1,000 means 16 MB of memory/connection + // limit = 10,000 means 160 MB of memory/connection + public int SendQueueLimit = 10000; + public int ReceiveQueueLimit = 10000; + + // thread safe pipe for received messages + // IMPORTANT: unfortunately using one pipe per connection is way slower + // when testing 150 CCU. we need to use one pipe for all + // connections. this scales beautifully. + protected MagnificentReceivePipe receivePipe; + + // pipe count, useful for debugging / benchmarks + public int ReceivePipeTotalCount => receivePipe.TotalCount; + + // clients with + readonly ConcurrentDictionary clients = new ConcurrentDictionary(); + + // connectionId counter + int counter; + + // public next id function in case someone needs to reserve an id + // (e.g. if hostMode should always have 0 connection and external + // connections should start at 1, etc.) + public int NextConnectionId() + { + int id = Interlocked.Increment(ref counter); + + // it's very unlikely that we reach the uint limit of 2 billion. + // even with 1 new connection per second, this would take 68 years. + // -> but if it happens, then we should throw an exception because + // the caller probably should stop accepting clients. + // -> it's hardly worth using 'bool Next(out id)' for that case + // because it's just so unlikely. + if (id == int.MaxValue) + { + throw new Exception("connection id limit reached: " + id); + } + + return id; + } + + // check if the server is running + public bool Active => listenerThread != null && listenerThread.IsAlive; + + // constructor + public Server(int MaxMessageSize) : base(MaxMessageSize) {} + + // the listener thread's listen function + // note: no maxConnections parameter. high level API should handle that. + // (Transport can't send a 'too full' message anyway) + void Listen(int port) + { + // absolutely must wrap with try/catch, otherwise thread + // exceptions are silent + try + { + // start listener on all IPv4 and IPv6 address via .Create + listener = TcpListener.Create(port); + listener.Server.NoDelay = NoDelay; + // IMPORTANT: do not set send/receive timeouts on listener. + // On linux setting the recv timeout will cause the blocking + // Accept call to timeout with EACCEPT (which mono interprets + // as EWOULDBLOCK). + // https://stackoverflow.com/questions/1917814/eagain-error-for-accept-on-blocking-socket/1918118#1918118 + // => fixes https://github.com/vis2k/Mirror/issues/2695 + // + //listener.Server.SendTimeout = SendTimeout; + //listener.Server.ReceiveTimeout = ReceiveTimeout; + listener.Start(); + Log.Info("Server: listening port=" + port); + + // keep accepting new clients + while (true) + { + // wait and accept new client + // note: 'using' sucks here because it will try to + // dispose after thread was started but we still need it + // in the thread + TcpClient client = listener.AcceptTcpClient(); + + // set socket options + client.NoDelay = NoDelay; + client.SendTimeout = SendTimeout; + client.ReceiveTimeout = ReceiveTimeout; + + // generate the next connection id (thread safely) + int connectionId = NextConnectionId(); + + // add to dict immediately + ConnectionState connection = new ConnectionState(client, MaxMessageSize); + clients[connectionId] = connection; + + // spawn a send thread for each client + Thread sendThread = new Thread(() => + { + // wrap in try-catch, otherwise Thread exceptions + // are silent + try + { + // run the send loop + // IMPORTANT: DO NOT SHARE STATE ACROSS MULTIPLE THREADS! + ThreadFunctions.SendLoop(connectionId, client, connection.sendPipe, connection.sendPending); + } + catch (ThreadAbortException) + { + // happens on stop. don't log anything. + // (we catch it in SendLoop too, but it still gets + // through to here when aborting. don't show an + // error.) + } + catch (Exception exception) + { + Log.Error("Server send thread exception: " + exception); + } + }); + sendThread.IsBackground = true; + sendThread.Start(); + + // spawn a receive thread for each client + Thread receiveThread = new Thread(() => + { + // wrap in try-catch, otherwise Thread exceptions + // are silent + try + { + // run the receive loop + // (receive pipe is shared across all loops) + ThreadFunctions.ReceiveLoop(connectionId, client, MaxMessageSize, receivePipe, ReceiveQueueLimit); + + // IMPORTANT: do NOT remove from clients after the + // thread ends. need to do it in Tick() so that the + // disconnect event in the pipe is still processed. + // (removing client immediately would mean that the + // pipe is lost and the disconnect event is never + // processed) + + // sendthread might be waiting on ManualResetEvent, + // so let's make sure to end it if the connection + // closed. + // otherwise the send thread would only end if it's + // actually sending data while the connection is + // closed. + sendThread.Interrupt(); + } + catch (Exception exception) + { + Log.Error("Server client thread exception: " + exception); + } + }); + receiveThread.IsBackground = true; + receiveThread.Start(); + } + } + catch (ThreadAbortException exception) + { + // UnityEditor causes AbortException if thread is still + // running when we press Play again next time. that's okay. + Log.Info("Server thread aborted. That's okay. " + exception); + } + catch (SocketException exception) + { + // calling StopServer will interrupt this thread with a + // 'SocketException: interrupted'. that's okay. + Log.Info("Server Thread stopped. That's okay. " + exception); + } + catch (Exception exception) + { + // something went wrong. probably important. + Log.Error("Server Exception: " + exception); + } + } + + // start listening for new connections in a background thread and spawn + // a new thread for each one. + public bool Start(int port) + { + // not if already started + if (Active) return false; + + // create receive pipe with max message size for pooling + // => create new pipes every time! + // if an old receive thread is still finishing up, it might still + // be using the old pipes. we don't want to risk any old data for + // our new start here. + receivePipe = new MagnificentReceivePipe(MaxMessageSize); + + // start the listener thread + // (on low priority. if main thread is too busy then there is not + // much value in accepting even more clients) + Log.Info("Server: Start port=" + port); + listenerThread = new Thread(() => { Listen(port); }); + listenerThread.IsBackground = true; + listenerThread.Priority = ThreadPriority.BelowNormal; + listenerThread.Start(); + return true; + } + + public void Stop() + { + // only if started + if (!Active) return; + + Log.Info("Server: stopping..."); + + // stop listening to connections so that no one can connect while we + // close the client connections + // (might be null if we call Stop so quickly after Start that the + // thread was interrupted before even creating the listener) + listener?.Stop(); + + // kill listener thread at all costs. only way to guarantee that + // .Active is immediately false after Stop. + // -> calling .Join would sometimes wait forever + listenerThread?.Interrupt(); + listenerThread = null; + + // close all client connections + foreach (KeyValuePair kvp in clients) + { + TcpClient client = kvp.Value.client; + // close the stream if not closed yet. it may have been closed + // by a disconnect already, so use try/catch + try { client.GetStream().Close(); } catch {} + client.Close(); + } + + // clear clients list + clients.Clear(); + + // reset the counter in case we start up again so + // clients get connection ID's starting from 1 + counter = 0; + } + + // send message to client using socket connection. + // arraysegment for allocation free sends later. + // -> the segment's array is only used until Send() returns! + public bool Send(int connectionId, ArraySegment message) + { + // respect max message size to avoid allocation attacks. + if (message.Count <= MaxMessageSize) + { + // find the connection + if (clients.TryGetValue(connectionId, out ConnectionState connection)) + { + // check send pipe limit + if (connection.sendPipe.Count < SendQueueLimit) + { + // add to thread safe send pipe and return immediately. + // calling Send here would be blocking (sometimes for long + // times if other side lags or wire was disconnected) + connection.sendPipe.Enqueue(message); + connection.sendPending.Set(); // interrupt SendThread WaitOne() + return true; + } + // disconnect if send queue gets too big. + // -> avoids ever growing queue memory if network is slower + // than input + // -> disconnecting is great for load balancing. better to + // disconnect one connection than risking every + // connection / the whole server + // + // note: while SendThread always grabs the WHOLE send queue + // immediately, it's still possible that the sending + // blocks for so long that the send queue just gets + // way too big. have a limit - better safe than sorry. + else + { + // log the reason + Log.Warning($"Server.Send: sendPipe for connection {connectionId} reached limit of {SendQueueLimit}. This can happen if we call send faster than the network can process messages. Disconnecting this connection for load balancing."); + + // just close it. send thread will take care of the rest. + connection.client.Close(); + return false; + } + } + + // sending to an invalid connectionId is expected sometimes. + // for example, if a client disconnects, the server might still + // try to send for one frame before it calls GetNextMessages + // again and realizes that a disconnect happened. + // so let's not spam the console with log messages. + //Logger.Log("Server.Send: invalid connectionId: " + connectionId); + return false; + } + Log.Error("Server.Send: message too big: " + message.Count + ". Limit: " + MaxMessageSize); + return false; + } + + // client's ip is sometimes needed by the server, e.g. for bans + public string GetClientAddress(int connectionId) + { + // find the connection + if (clients.TryGetValue(connectionId, out ConnectionState connection)) + { + return ((IPEndPoint)connection.client.Client.RemoteEndPoint).Address.ToString(); + } + return ""; + } + + // disconnect (kick) a client + public bool Disconnect(int connectionId) + { + // find the connection + if (clients.TryGetValue(connectionId, out ConnectionState connection)) + { + // just close it. send thread will take care of the rest. + connection.client.Close(); + Log.Info("Server.Disconnect connectionId:" + connectionId); + return true; + } + return false; + } + + // tick: processes up to 'limit' messages for each connection + // => limit parameter to avoid deadlocks / too long freezes if server or + // client is too slow to process network load + // => Mirror & DOTSNET need to have a process limit anyway. + // might as well do it here and make life easier. + // => returns amount of remaining messages to process, so the caller + // can call tick again as many times as needed (or up to a limit) + // + // Tick() may process multiple messages, but Mirror needs a way to stop + // processing immediately if a scene change messages arrives. Mirror + // can't process any other messages during a scene change. + // (could be useful for others too) + // => make sure to allocate the lambda only once in transports + public int Tick(int processLimit, Func checkEnabled = null) + { + // only if pipe was created yet (after start()) + if (receivePipe == null) + return 0; + + // process up to 'processLimit' messages for this connection + for (int i = 0; i < processLimit; ++i) + { + // check enabled in case a Mirror scene message arrived + if (checkEnabled != null && !checkEnabled()) + break; + + // peek first. allows us to process the first queued entry while + // still keeping the pooled byte[] alive by not removing anything. + if (receivePipe.TryPeek(out int connectionId, out EventType eventType, out ArraySegment message)) + { + switch (eventType) + { + case EventType.Connected: + OnConnected?.Invoke(connectionId); + break; + case EventType.Data: + OnData?.Invoke(connectionId, message); + break; + case EventType.Disconnected: + OnDisconnected?.Invoke(connectionId); + // remove disconnected connection now that the final + // disconnected message was processed. + clients.TryRemove(connectionId, out ConnectionState _); + break; + } + + // IMPORTANT: now dequeue and return it to pool AFTER we are + // done processing the event. + receivePipe.TryDequeue(); + } + // no more messages. stop the loop. + else break; + } + + // return what's left to process for next time + return receivePipe.TotalCount; + } + } +} diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Server.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/Server.cs.meta new file mode 100644 index 0000000..9cee8b7 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Server.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb98a16841ccc4338a7e0b4e59136563 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Telepathy.asmdef b/Assets/Mirror/Transports/Telepathy/Telepathy/Telepathy.asmdef new file mode 100644 index 0000000..cd8d16a --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Telepathy.asmdef @@ -0,0 +1,12 @@ +{ + "name": "Telepathy", + "references": [], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Telepathy.asmdef.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/Telepathy.asmdef.meta new file mode 100644 index 0000000..572c127 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Telepathy.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 725ee7191c021de4dbf9269590ded755 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/ThreadFunctions.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/ThreadFunctions.cs new file mode 100644 index 0000000..6f026c9 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/ThreadFunctions.cs @@ -0,0 +1,244 @@ +// IMPORTANT +// force all thread functions to be STATIC. +// => Common.Send/ReceiveLoop is EXTREMELY DANGEROUS because it's too easy to +// accidentally share Common state between threads. +// => header buffer, payload etc. were accidentally shared once after changing +// the thread functions from static to non static +// => C# does not automatically detect data races. best we can do is move all of +// our thread code into static functions and pass all state into them +// +// let's even keep them in a STATIC CLASS so it's 100% obvious that this should +// NOT EVER be changed to non static! +using System; +using System.Net.Sockets; +using System.Threading; + +namespace Telepathy +{ + public static class ThreadFunctions + { + // send message (via stream) with the message structure + // this function is blocking sometimes! + // (e.g. if someone has high latency or wire was cut off) + // -> payload is of multiple < parts + public static bool SendMessagesBlocking(NetworkStream stream, byte[] payload, int packetSize) + { + // stream.Write throws exceptions if client sends with high + // frequency and the server stops + try + { + // write the whole thing + stream.Write(payload, 0, packetSize); + return true; + } + catch (Exception exception) + { + // log as regular message because servers do shut down sometimes + Log.Info("Send: stream.Write exception: " + exception); + return false; + } + } + // read message (via stream) blocking. + // writes into byte[] and returns bytes written to avoid allocations. + public static bool ReadMessageBlocking(NetworkStream stream, int MaxMessageSize, byte[] headerBuffer, byte[] payloadBuffer, out int size) + { + size = 0; + + // buffer needs to be of Header + MaxMessageSize + if (payloadBuffer.Length != 4 + MaxMessageSize) + { + Log.Error($"ReadMessageBlocking: payloadBuffer needs to be of size 4 + MaxMessageSize = {4 + MaxMessageSize} instead of {payloadBuffer.Length}"); + return false; + } + + // read exactly 4 bytes for header (blocking) + if (!stream.ReadExactly(headerBuffer, 4)) + return false; + + // convert to int + size = Utils.BytesToIntBigEndian(headerBuffer); + + // protect against allocation attacks. an attacker might send + // multiple fake '2GB header' packets in a row, causing the server + // to allocate multiple 2GB byte arrays and run out of memory. + // + // also protect against size <= 0 which would cause issues + if (size > 0 && size <= MaxMessageSize) + { + // read exactly 'size' bytes for content (blocking) + return stream.ReadExactly(payloadBuffer, size); + } + Log.Warning("ReadMessageBlocking: possible header attack with a header of: " + size + " bytes."); + return false; + } + + // thread receive function is the same for client and server's clients + public static void ReceiveLoop(int connectionId, TcpClient client, int MaxMessageSize, MagnificentReceivePipe receivePipe, int QueueLimit) + { + // get NetworkStream from client + NetworkStream stream = client.GetStream(); + + // every receive loop needs it's own receive buffer of + // HeaderSize + MaxMessageSize + // to avoid runtime allocations. + // + // IMPORTANT: DO NOT make this a member, otherwise every connection + // on the server would use the same buffer simulatenously + byte[] receiveBuffer = new byte[4 + MaxMessageSize]; + + // avoid header[4] allocations + // + // IMPORTANT: DO NOT make this a member, otherwise every connection + // on the server would use the same buffer simulatenously + byte[] headerBuffer = new byte[4]; + + // absolutely must wrap with try/catch, otherwise thread exceptions + // are silent + try + { + // add connected event to pipe + receivePipe.Enqueue(connectionId, EventType.Connected, default); + + // let's talk about reading data. + // -> normally we would read as much as possible and then + // extract as many , messages + // as we received this time. this is really complicated + // and expensive to do though + // -> instead we use a trick: + // Read(2) -> size + // Read(size) -> content + // repeat + // Read is blocking, but it doesn't matter since the + // best thing to do until the full message arrives, + // is to wait. + // => this is the most elegant AND fast solution. + // + no resizing + // + no extra allocations, just one for the content + // + no crazy extraction logic + while (true) + { + // read the next message (blocking) or stop if stream closed + if (!ReadMessageBlocking(stream, MaxMessageSize, headerBuffer, receiveBuffer, out int size)) + // break instead of return so stream close still happens! + break; + + // create arraysegment for the read message + ArraySegment message = new ArraySegment(receiveBuffer, 0, size); + + // send to main thread via pipe + // -> it'll copy the message internally so we can reuse the + // receive buffer for next read! + receivePipe.Enqueue(connectionId, EventType.Data, message); + + // disconnect if receive pipe gets too big for this connectionId. + // -> avoids ever growing queue memory if network is slower + // than input + // -> disconnecting is great for load balancing. better to + // disconnect one connection than risking every + // connection / the whole server + if (receivePipe.Count(connectionId) >= QueueLimit) + { + // log the reason + Log.Warning($"receivePipe reached limit of {QueueLimit} for connectionId {connectionId}. This can happen if network messages come in way faster than we manage to process them. Disconnecting this connection for load balancing."); + + // IMPORTANT: do NOT clear the whole queue. we use one + // queue for all connections. + //receivePipe.Clear(); + + // just break. the finally{} will close everything. + break; + } + } + } + catch (Exception exception) + { + // something went wrong. the thread was interrupted or the + // connection closed or we closed our own connection or ... + // -> either way we should stop gracefully + Log.Info("ReceiveLoop: finished receive function for connectionId=" + connectionId + " reason: " + exception); + } + finally + { + // clean up no matter what + stream.Close(); + client.Close(); + + // add 'Disconnected' message after disconnecting properly. + // -> always AFTER closing the streams to avoid a race condition + // where Disconnected -> Reconnect wouldn't work because + // Connected is still true for a short moment before the stream + // would be closed. + receivePipe.Enqueue(connectionId, EventType.Disconnected, default); + } + } + // thread send function + // note: we really do need one per connection, so that if one connection + // blocks, the rest will still continue to get sends + public static void SendLoop(int connectionId, TcpClient client, MagnificentSendPipe sendPipe, ManualResetEvent sendPending) + { + // get NetworkStream from client + NetworkStream stream = client.GetStream(); + + // avoid payload[packetSize] allocations. size increases dynamically as + // needed for batching. + // + // IMPORTANT: DO NOT make this a member, otherwise every connection + // on the server would use the same buffer simulatenously + byte[] payload = null; + + try + { + while (client.Connected) // try this. client will get closed eventually. + { + // reset ManualResetEvent before we do anything else. this + // way there is no race condition. if Send() is called again + // while in here then it will be properly detected next time + // -> otherwise Send might be called right after dequeue but + // before .Reset, which would completely ignore it until + // the next Send call. + sendPending.Reset(); // WaitOne() blocks until .Set() again + + // dequeue & serialize all + // a locked{} TryDequeueAll is twice as fast as + // ConcurrentQueue, see SafeQueue.cs! + if (sendPipe.DequeueAndSerializeAll(ref payload, out int packetSize)) + { + // send messages (blocking) or stop if stream is closed + if (!SendMessagesBlocking(stream, payload, packetSize)) + // break instead of return so stream close still happens! + break; + } + + // don't choke up the CPU: wait until queue not empty anymore + sendPending.WaitOne(); + } + } + catch (ThreadAbortException) + { + // happens on stop. don't log anything. + } + catch (ThreadInterruptedException) + { + // happens if receive thread interrupts send thread. + } + catch (Exception exception) + { + // something went wrong. the thread was interrupted or the + // connection closed or we closed our own connection or ... + // -> either way we should stop gracefully + Log.Info("SendLoop Exception: connectionId=" + connectionId + " reason: " + exception); + } + finally + { + // clean up no matter what + // we might get SocketExceptions when sending if the 'host has + // failed to respond' - in which case we should close the connection + // which causes the ReceiveLoop to end and fire the Disconnected + // message. otherwise the connection would stay alive forever even + // though we can't send anymore. + stream.Close(); + client.Close(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/ThreadFunctions.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/ThreadFunctions.cs.meta new file mode 100644 index 0000000..ea536ac --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/ThreadFunctions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d01598bf851164dc48a24c26913460b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Utils.cs b/Assets/Mirror/Transports/Telepathy/Telepathy/Utils.cs new file mode 100644 index 0000000..8f04fe9 --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Utils.cs @@ -0,0 +1,23 @@ +namespace Telepathy +{ + public static class Utils + { + // IntToBytes version that doesn't allocate a new byte[4] each time. + // -> important for MMO scale networking performance. + public static void IntToBytesBigEndianNonAlloc(int value, byte[] bytes, int offset = 0) + { + bytes[offset + 0] = (byte)(value >> 24); + bytes[offset + 1] = (byte)(value >> 16); + bytes[offset + 2] = (byte)(value >> 8); + bytes[offset + 3] = (byte)value; + } + + public static int BytesToIntBigEndian(byte[] bytes) + { + return (bytes[0] << 24) | + (bytes[1] << 16) | + (bytes[2] << 8) | + bytes[3]; + } + } +} diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/Utils.cs.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/Utils.cs.meta new file mode 100644 index 0000000..0a9253b --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 951d08c05297f4b3e8feb5bfcab86531 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/VERSION b/Assets/Mirror/Transports/Telepathy/Telepathy/VERSION new file mode 100644 index 0000000..a0e7ded --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/VERSION @@ -0,0 +1,65 @@ +V1.9 [2023-11-10] +- fix: Always enqueue Disconnected event (imer) + +V1.8 [2021-06-02] +- fix: Do not set timeouts on listener (fixes https://github.com/vis2k/Mirror/issues/2695) +- fix: #104 - ReadSafely now catches ObjectDisposedException too + +V1.7 [2021-02-20] +- ReceiveTimeout: disabled by default for cases where people use Telepathy by + itself without pings etc. + +V1.6 [2021-02-10] +- configurable ReceiveTimeout to avoid TCPs high default timeout +- Server/Client receive queue limit now disconnects instead of showing a + warning. this is necessary for load balancing to avoid situations where one + spamming connection might fill the queue and slow down everyone else. + +V1.5 [2021-02-05] +- fix: client data races & flaky tests fixed by creating a new client state + object every time we connect. fixes data race where an old dieing thread + might still try to modify the current state +- fix: Client.ReceiveThreadFunction catches and ignores ObjectDisposedException + which can happen if Disconnect() closes and disposes the client, while the + ReceiveThread just starts up and still uses the client. +- Server/Client Tick() optional enabled check for Mirror scene changing + +V1.4 [2021-02-03] +- Server/Client.Tick: limit parameter added to process up to 'limit' messages. + makes Mirror & DOTSNET transports easier to implement +- stability: Server/Client send queue limit disconnects instead of showing a + warning. allows for load balancing. better to kick one connection and keep + the server running than slowing everything down for everyone. + +V1.3 [2021-02-02] +- perf: ReceivePipe: byte[] pool for allocation free receives (╯°□°)╯︵ ┻━┻ +- fix: header buffer, payload buffer data races because they were made non + static earlier. server threads would all access the same ones. + => all threaded code was moved into a static ThreadFunctions class to make it + 100% obvious that there should be no shared state in the future + +V1.2 [2021-02-02] +- Client/Server Tick & OnConnected/OnData/OnDisconnected events instead of + having the outside process messages via GetNextMessage. That's easier for + Mirror/DOTSNET and allows for allocation free data message processing later. +- MagnificientSend/RecvPipe to shield Telepathy from all the complexity +- perf: SendPipe: byte[] pool for allocation free sends (╯°□°)╯︵ ┻━┻ + +V1.1 [2021-02-01] +- stability: added more tests +- breaking: Server/Client.Send: ArraySegment parameter and copy internally so + that Transports don't need to worry about it +- perf: Buffer.BlockCopy instead of Array.Copy +- perf: SendMessageBlocking puts message header directly into payload now +- perf: receiveQueues use SafeQueue instead of ConcurrentQueue to avoid + allocations +- Common: removed static state +- perf: SafeQueue.TryDequeueAll: avoid queue.ToArray() allocations. copy into a + list instead. +- Logger.Log/LogWarning/LogError renamed to Log.Info/Warning/Error +- MaxMessageSize is now specified in constructor to prepare for pooling +- flaky tests are ignored for now +- smaller improvements + +V1.0 +- first stable release \ No newline at end of file diff --git a/Assets/Mirror/Transports/Telepathy/Telepathy/VERSION.meta b/Assets/Mirror/Transports/Telepathy/Telepathy/VERSION.meta new file mode 100644 index 0000000..04c1c8a --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/Telepathy/VERSION.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d942af06608be434dbeeaa58207d20bd +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Telepathy/TelepathyTransport.cs b/Assets/Mirror/Transports/Telepathy/TelepathyTransport.cs new file mode 100644 index 0000000..7a1c88d --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/TelepathyTransport.cs @@ -0,0 +1,269 @@ +// wraps Telepathy for use as HLAPI TransportLayer +using System; +using System.Net; +using System.Net.Sockets; +using UnityEngine; + +// Replaced by Kcp November 2020 +namespace Mirror +{ + [HelpURL("https://github.com/vis2k/Telepathy/blob/master/README.md")] + [DisallowMultipleComponent] + public class TelepathyTransport : Transport, PortTransport + { + // scheme used by this transport + // "tcp4" means tcp with 4 bytes header, network byte order + public const string Scheme = "tcp4"; + + public ushort port = 7777; + public ushort Port { get => port; set => port=value; } + + [Header("Common")] + [Tooltip("Nagle Algorithm can be disabled by enabling NoDelay")] + public bool NoDelay = true; + + [Tooltip("Send timeout in milliseconds.")] + public int SendTimeout = 5000; + + [Tooltip("Receive timeout in milliseconds. High by default so users don't time out during scene changes.")] + public int ReceiveTimeout = 30000; + + [Header("Server")] + [Tooltip("Protect against allocation attacks by keeping the max message size small. Otherwise an attacker might send multiple fake packets with 2GB headers, causing the server to run out of memory after allocating multiple large packets.")] + public int serverMaxMessageSize = 16 * 1024; + + [Tooltip("Server processes a limit amount of messages per tick to avoid a deadlock where it might end up processing forever if messages come in faster than we can process them.")] + public int serverMaxReceivesPerTick = 10000; + + [Tooltip("Server send queue limit per connection for pending messages. Telepathy will disconnect a connection's queues reach that limit for load balancing. Better to kick one slow client than slowing down the whole server.")] + public int serverSendQueueLimitPerConnection = 10000; + + [Tooltip("Server receive queue limit per connection for pending messages. Telepathy will disconnect a connection's queues reach that limit for load balancing. Better to kick one slow client than slowing down the whole server.")] + public int serverReceiveQueueLimitPerConnection = 10000; + + [Header("Client")] + [Tooltip("Protect against allocation attacks by keeping the max message size small. Otherwise an attacker host might send multiple fake packets with 2GB headers, causing the connected clients to run out of memory after allocating multiple large packets.")] + public int clientMaxMessageSize = 16 * 1024; + + [Tooltip("Client processes a limit amount of messages per tick to avoid a deadlock where it might end up processing forever if messages come in faster than we can process them.")] + public int clientMaxReceivesPerTick = 1000; + + [Tooltip("Client send queue limit for pending messages. Telepathy will disconnect if the connection's queues reach that limit in order to avoid ever growing latencies.")] + public int clientSendQueueLimit = 10000; + + [Tooltip("Client receive queue limit for pending messages. Telepathy will disconnect if the connection's queues reach that limit in order to avoid ever growing latencies.")] + public int clientReceiveQueueLimit = 10000; + + Telepathy.Client client; + Telepathy.Server server; + + // scene change message needs to halt message processing immediately + // Telepathy.Tick() has a enabledCheck parameter that we can use, but + // let's only allocate it once. + Func enabledCheck; + + void Awake() + { + // tell Telepathy to use Unity's Debug.Log + Telepathy.Log.Info = Debug.Log; + Telepathy.Log.Warning = Debug.LogWarning; + Telepathy.Log.Error = Debug.LogError; + + // allocate enabled check only once + enabledCheck = () => enabled; + + Debug.Log("TelepathyTransport initialized!"); + } + + // C#'s built in TCP sockets run everywhere except on WebGL + // Do not change this back to using Application.platform + // because that doesn't work in the Editor! + public override bool Available() => +#if UNITY_WEBGL + false; +#else + true; +#endif + + // client + private void CreateClient() + { + // create client + client = new Telepathy.Client(clientMaxMessageSize); + // client hooks + // other systems hook into transport events in OnCreate or + // OnStartRunning in no particular order. the only way to avoid + // race conditions where telepathy uses OnConnected before another + // system's hook (e.g. statistics OnData) was added is to wrap + // them all in a lambda and always call the latest hook. + // (= lazy call) + client.OnConnected = () => OnClientConnected.Invoke(); + client.OnData = (segment) => OnClientDataReceived.Invoke(segment, Channels.Reliable); + // fix: https://github.com/vis2k/Mirror/issues/3287 + // Telepathy may call OnDisconnected twice. + // Mirror may have cleared the callback already, so use "?." here. + client.OnDisconnected = () => OnClientDisconnected?.Invoke(); + + // client configuration + client.NoDelay = NoDelay; + client.SendTimeout = SendTimeout; + client.ReceiveTimeout = ReceiveTimeout; + client.SendQueueLimit = clientSendQueueLimit; + client.ReceiveQueueLimit = clientReceiveQueueLimit; + } + public override bool ClientConnected() => client != null && client.Connected; + public override void ClientConnect(string address) + { + CreateClient(); + client.Connect(address, port); + } + + public override void ClientConnect(Uri uri) + { + CreateClient(); + if (uri.Scheme != Scheme) + throw new ArgumentException($"Invalid url {uri}, use {Scheme}://host:port instead", nameof(uri)); + + int serverPort = uri.IsDefaultPort ? port : uri.Port; + client.Connect(uri.Host, serverPort); + } + public override void ClientSend(ArraySegment segment, int channelId) + { + client?.Send(segment); + + // call event. might be null if no statistics are listening etc. + OnClientDataSent?.Invoke(segment, Channels.Reliable); + } + public override void ClientDisconnect() + { + client?.Disconnect(); + client = null; + // client triggers the disconnected event in client.Tick() which won't be run anymore + OnClientDisconnected?.Invoke(); + } + + // messages should always be processed in early update + public override void ClientEarlyUpdate() + { + // note: we need to check enabled in case we set it to false + // when LateUpdate already started. + // (https://github.com/vis2k/Mirror/pull/379) + if (!enabled) return; + + // process a maximum amount of client messages per tick + // IMPORTANT: check .enabled to stop processing immediately after a + // scene change message arrives! + client?.Tick(clientMaxReceivesPerTick, enabledCheck); + } + + // server + public override Uri ServerUri() + { + UriBuilder builder = new UriBuilder(); + builder.Scheme = Scheme; + builder.Host = Dns.GetHostName(); + builder.Port = port; + return builder.Uri; + } + public override bool ServerActive() => server != null && server.Active; + public override void ServerStart() + { + // create server + server = new Telepathy.Server(serverMaxMessageSize); + + // server hooks + // other systems hook into transport events in OnCreate or + // OnStartRunning in no particular order. the only way to avoid + // race conditions where telepathy uses OnConnected before another + // system's hook (e.g. statistics OnData) was added is to wrap + // them all in a lambda and always call the latest hook. + // (= lazy call) + server.OnConnected = (connectionId) => OnServerConnected.Invoke(connectionId); + server.OnData = (connectionId, segment) => OnServerDataReceived.Invoke(connectionId, segment, Channels.Reliable); + server.OnDisconnected = (connectionId) => OnServerDisconnected.Invoke(connectionId); + + // server configuration + server.NoDelay = NoDelay; + server.SendTimeout = SendTimeout; + server.ReceiveTimeout = ReceiveTimeout; + server.SendQueueLimit = serverSendQueueLimitPerConnection; + server.ReceiveQueueLimit = serverReceiveQueueLimitPerConnection; + + server.Start(port); + } + + public override void ServerSend(int connectionId, ArraySegment segment, int channelId) + { + server?.Send(connectionId, segment); + + // call event. might be null if no statistics are listening etc. + OnServerDataSent?.Invoke(connectionId, segment, Channels.Reliable); + } + public override void ServerDisconnect(int connectionId) => server?.Disconnect(connectionId); + public override string ServerGetClientAddress(int connectionId) + { + try + { + return server?.GetClientAddress(connectionId); + } + catch (SocketException) + { + // using server.listener.LocalEndpoint causes an Exception + // in UWP + Unity 2019: + // Exception thrown at 0x00007FF9755DA388 in UWF.exe: + // Microsoft C++ exception: Il2CppExceptionWrapper at memory + // location 0x000000E15A0FCDD0. SocketException: An address + // incompatible with the requested protocol was used at + // System.Net.Sockets.Socket.get_LocalEndPoint () + // so let's at least catch it and recover + return "unknown"; + } + } + public override void ServerStop() + { + server?.Stop(); + server = null; + } + + // messages should always be processed in early update + public override void ServerEarlyUpdate() + { + // note: we need to check enabled in case we set it to false + // when LateUpdate already started. + // (https://github.com/vis2k/Mirror/pull/379) + if (!enabled) return; + + // process a maximum amount of server messages per tick + // IMPORTANT: check .enabled to stop processing immediately after a + // scene change message arrives! + server?.Tick(serverMaxReceivesPerTick, enabledCheck); + } + + // common + public override void Shutdown() + { + Debug.Log("TelepathyTransport Shutdown()"); + client?.Disconnect(); + client = null; + server?.Stop(); + server = null; + } + + public override int GetMaxPacketSize(int channelId) + { + return serverMaxMessageSize; + } + + // Keep it short and simple so it looks nice in the HUD. + // + // printing server.listener.LocalEndpoint causes an Exception + // in UWP + Unity 2019: + // Exception thrown at 0x00007FF9755DA388 in UWF.exe: + // Microsoft C++ exception: Il2CppExceptionWrapper at memory + // location 0x000000E15A0FCDD0. SocketException: An address + // incompatible with the requested protocol was used at + // System.Net.Sockets.Socket.get_LocalEndPoint () + // so just use the regular port instead. + public override string ToString() => $"Telepathy [{port}]"; + } +} diff --git a/Assets/Mirror/Transports/Telepathy/TelepathyTransport.cs.meta b/Assets/Mirror/Transports/Telepathy/TelepathyTransport.cs.meta new file mode 100644 index 0000000..99cde3e --- /dev/null +++ b/Assets/Mirror/Transports/Telepathy/TelepathyTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7424c1070fad4ba2a7a96b02fbeb4bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 1000 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Threaded.meta b/Assets/Mirror/Transports/Threaded.meta new file mode 100644 index 0000000..cef7c07 --- /dev/null +++ b/Assets/Mirror/Transports/Threaded.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4449b05e1376c4120afdce7b134887b4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Transports/Threaded/ThreadedTransport.cs b/Assets/Mirror/Transports/Threaded/ThreadedTransport.cs new file mode 100644 index 0000000..a931d16 --- /dev/null +++ b/Assets/Mirror/Transports/Threaded/ThreadedTransport.cs @@ -0,0 +1,655 @@ +// threaded transport to handle all the magic. +// implementations are automatically elevated to the worker thread +// by simply overwriting all the thread functions +// +// note that ThreadLog.cs is required for Debug.Log from threads to work in builds. +using System; +using System.Collections.Concurrent; +using System.Runtime.CompilerServices; +using System.Threading; +using UnityEngine; + +namespace Mirror +{ + // buffered events for main thread + enum ClientMainEventType + { + OnClientConnected, + OnClientSent, + OnClientReceived, + OnClientError, + OnClientDisconnected, + } + + enum ServerMainEventType + { + OnServerConnected, + OnServerSent, + OnServerReceived, + OnServerError, + OnServerDisconnected, + } + + // buffered events for worker thread + enum ThreadEventType + { + DoServerStart, + DoServerSend, + DoServerDisconnect, + DoServerStop, + + DoClientConnect, + DoClientSend, + DoClientDisconnect, + + DoShutdown + } + + struct ClientMainEvent + { + public ClientMainEventType type; + public object param; + + // some events have value type parameters: connectionId, error. + // store them explicitly to avoid boxing allocations to 'object param'. + public int? channelId; // connect/disconnect don't have a channel + public TransportError? error; + + public ClientMainEvent( + ClientMainEventType type, + object param, + int? channelId = null, + TransportError? error = null) + { + this.type = type; + this.channelId = channelId; + this.error = error; + this.param = param; + } + } + + struct ServerMainEvent + { + public ServerMainEventType type; + public object param; + + // some events have value type parameters: connectionId, error. + // store them explicitly to avoid boxing allocations to 'object param'. + public int? connectionId; // only server needs connectionId + public int? channelId; // connect/disconnect don't have a channel + public TransportError? error; + + public ServerMainEvent( + ServerMainEventType type, + object param, + int? connectionId, + int? channelId = null, + TransportError? error = null) + { + this.type = type; + this.channelId = channelId; + this.connectionId = connectionId; + this.error = error; + this.param = param; + } + } + + struct ThreadEvent + { + public ThreadEventType type; + public object param; + + // some events have value type parameters: connectionId. + // store them explicitly to avoid boxing allocations to 'object param'. + public int? connectionId; + public int? channelId; + + public ThreadEvent( + ThreadEventType type, + object param, + int? connectionId = null, + int? channelId = null) + { + this.type = type; + this.connectionId = connectionId; + this.channelId = channelId; + this.param = param; + } + } + + public abstract class ThreadedTransport : Transport + { + WorkerThread thread; + + // main thread's event queue. + // worker thread puts events in, main thread processes them. + // client & server separate because EarlyUpdate is separate too. + // TODO nonalloc + readonly ConcurrentQueue clientMainQueue = new ConcurrentQueue(); + readonly ConcurrentQueue serverMainQueue = new ConcurrentQueue(); + + // worker thread's event queue + // main thread puts events in, worker thread processes them. + // TODO nonalloc + readonly ConcurrentQueue threadQueue = new ConcurrentQueue(); + + // active flags, since we can't access server/client from main thread + volatile bool serverActive; + volatile bool clientConnected; + + // max number of thread messages to process per tick in main thread. + // very large limit to prevent deadlocks. + const int MaxProcessingPerTick = 10_000_000; + + // communication between main & worker thread ////////////////////////// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void EnqueueClientMain( + ClientMainEventType type, + object param, + int? channelId, + TransportError? error) => + clientMainQueue.Enqueue(new ClientMainEvent(type, param, channelId, error)); + + // add an event for main thread + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void EnqueueServerMain( + ServerMainEventType type, + object param, + int? connectionId, + int? channelId, + TransportError? error) => + serverMainQueue.Enqueue(new ServerMainEvent(type, param, connectionId, channelId, error)); + + void EnqueueThread( + ThreadEventType type, + object param, + int? channelId, + int? connectionId) => + threadQueue.Enqueue(new ThreadEvent(type, param, connectionId, channelId)); + + // Unity callbacks ///////////////////////////////////////////////////// + protected virtual void Awake() + { + // start the thread. + // if main application terminates, this thread needs to terminate too. + thread = new WorkerThread(ToString()); + thread.Tick = ThreadTick; + thread.Cleanup = ThreadedShutdown; + thread.Start(); + } + + protected virtual void OnDestroy() + { + // stop thread fully + Shutdown(); + + // TODO recycle writers. + } + + // worker thread /////////////////////////////////////////////////////// + void ProcessThreadQueue() + { + // TODO deadlock protection. worker thread may be to slow to process all. + while (threadQueue.TryDequeue(out ThreadEvent elem)) + { + switch (elem.type) + { + // SERVER EVENTS /////////////////////////////////////////// + case ThreadEventType.DoServerStart: // start listening + { + // call the threaded function + ThreadedServerStart(); + break; + } + case ThreadEventType.DoServerSend: + { + // call the threaded function + ConcurrentNetworkWriterPooled writer = (ConcurrentNetworkWriterPooled)elem.param; + ThreadedServerSend(elem.connectionId.Value, writer, elem.channelId.Value); + + // recycle writer to thread safe pool for reuse + ConcurrentNetworkWriterPool.Return(writer); + break; + } + case ThreadEventType.DoServerDisconnect: + { + // call the threaded function + ThreadedServerDisconnect(elem.connectionId.Value); + break; + } + case ThreadEventType.DoServerStop: // stop listening + { + // call the threaded function + ThreadedServerStop(); + break; + } + + // CLIENT EVENTS /////////////////////////////////////////// + case ThreadEventType.DoClientConnect: + { + // call the threaded function + if (elem.param is string address) + ThreadedClientConnect(address); + else if (elem.param is Uri uri) + ThreadedClientConnect(uri); + break; + } + case ThreadEventType.DoClientSend: + { + // call the threaded function + ConcurrentNetworkWriterPooled writer = (ConcurrentNetworkWriterPooled)elem.param; + ThreadedClientSend(writer, elem.channelId.Value); + + // recycle writer to thread safe pool for reuse + ConcurrentNetworkWriterPool.Return(writer); + break; + } + case ThreadEventType.DoClientDisconnect: + { + // call the threaded function + ThreadedClientDisconnect(); + break; + } + + // SHUTDOWN //////////////////////////////////////////////// + case ThreadEventType.DoShutdown: + { + // call the threaded function + ThreadedShutdown(); + break; + } + } + } + } + + void ThreadTick() + { + // early update the implementation first + ThreadedClientEarlyUpdate(); + ThreadedServerEarlyUpdate(); + + // process queued user requests + ProcessThreadQueue(); + + // late update the implementation at the end + ThreadedClientLateUpdate(); + ThreadedServerLateUpdate(); + + // save some cpu power. + // TODO update interval and sleep extra time would be ideal + Thread.Sleep(1); + } + + // threaded callbacks to call from transport thread. + // they will be queued up for main thread automatically. + protected void OnThreadedClientConnected() + { + EnqueueClientMain(ClientMainEventType.OnClientConnected, null, null, null); + } + + protected void OnThreadedClientSend(ArraySegment message, int channelId) + { + // ArraySegment is only valid until returning. + // copy to a writer until main thread processes it. + // make sure to recycle the writer in main thread. + ConcurrentNetworkWriterPooled writer = ConcurrentNetworkWriterPool.Get(); + writer.WriteBytes(message.Array, message.Offset, message.Count); + EnqueueClientMain(ClientMainEventType.OnClientSent, writer, channelId, null); + } + + protected void OnThreadedClientReceive(ArraySegment message, int channelId) + { + // ArraySegment is only valid until returning. + // copy to a writer until main thread processes it. + // make sure to recycle the writer in main thread. + ConcurrentNetworkWriterPooled writer = ConcurrentNetworkWriterPool.Get(); + writer.WriteBytes(message.Array, message.Offset, message.Count); + EnqueueClientMain(ClientMainEventType.OnClientReceived, writer, channelId, null); + } + + protected void OnThreadedClientError(TransportError error, string reason) + { + EnqueueClientMain(ClientMainEventType.OnClientError, reason, null, error); + } + + protected void OnThreadedClientDisconnected() + { + EnqueueClientMain(ClientMainEventType.OnClientDisconnected, null, null, null); + } + + protected void OnThreadedServerConnected(int connectionId) + { + EnqueueServerMain(ServerMainEventType.OnServerConnected, null, connectionId, null, null); + } + + protected void OnThreadedServerSend(int connectionId, ArraySegment message, int channelId) + { + // ArraySegment is only valid until returning. + // copy to a writer until main thread processes it. + // make sure to recycle the writer in main thread. + ConcurrentNetworkWriterPooled writer = ConcurrentNetworkWriterPool.Get(); + writer.WriteBytes(message.Array, message.Offset, message.Count); + EnqueueServerMain(ServerMainEventType.OnServerSent, writer, connectionId, channelId, null); + } + + protected void OnThreadedServerReceive(int connectionId, ArraySegment message, int channelId) + { + // ArraySegment is only valid until returning. + // copy to a writer until main thread processes it. + // make sure to recycle the writer in main thread. + ConcurrentNetworkWriterPooled writer = ConcurrentNetworkWriterPool.Get(); + writer.WriteBytes(message.Array, message.Offset, message.Count); + EnqueueServerMain(ServerMainEventType.OnServerReceived, writer, connectionId, channelId, null); + } + + protected void OnThreadedServerError(int connectionId, TransportError error, string reason) + { + EnqueueServerMain(ServerMainEventType.OnServerError, reason, connectionId, null, error); + } + + protected void OnThreadedServerDisconnected(int connectionId) + { + EnqueueServerMain(ServerMainEventType.OnServerDisconnected, null, connectionId, null, null); + } + + protected abstract void ThreadedClientConnect(string address); + protected abstract void ThreadedClientConnect(Uri address); + protected abstract void ThreadedClientSend(ArraySegment message, int channelId); + protected abstract void ThreadedClientDisconnect(); + + protected abstract void ThreadedServerStart(); + protected abstract void ThreadedServerStop(); + protected abstract void ThreadedServerSend(int connectionId, ArraySegment message, int channelId); + protected abstract void ThreadedServerDisconnect(int connectionId); + + // threaded update functions. + // make sure not to call main thread OnReceived etc. events. + // queue everything. + protected abstract void ThreadedClientEarlyUpdate(); + protected abstract void ThreadedClientLateUpdate(); + protected abstract void ThreadedServerEarlyUpdate(); + protected abstract void ThreadedServerLateUpdate(); + + protected abstract void ThreadedShutdown(); + + // client ////////////////////////////////////////////////////////////// + // implementations need to use ThreadedEarlyUpdate + public override void ClientEarlyUpdate() + { + // regular transports process OnReceive etc. from early update. + // need to process the worker thread's queued events here too. + // + // process only up to N messages per tick here. + // if main thread becomes too slow, we don't want to deadlock. + int processed = 0; + while (clientMainQueue.TryDequeue(out ClientMainEvent elem)) + { + switch (elem.type) + { + // CLIENT EVENTS /////////////////////////////////////////// + case ClientMainEventType.OnClientConnected: + { + // call original transport event + OnClientConnected?.Invoke(); + break; + } + case ClientMainEventType.OnClientSent: + { + // call original transport event + ConcurrentNetworkWriterPooled writer = (ConcurrentNetworkWriterPooled)elem.param; + OnClientDataSent?.Invoke(writer, elem.channelId.Value); + + // recycle writer to thread safe pool for reuse + ConcurrentNetworkWriterPool.Return(writer); + break; + } + case ClientMainEventType.OnClientReceived: + { + // call original transport event + ConcurrentNetworkWriterPooled writer = (ConcurrentNetworkWriterPooled)elem.param; + OnClientDataReceived?.Invoke(writer, elem.channelId.Value); + + // recycle writer to thread safe pool for reuse + ConcurrentNetworkWriterPool.Return(writer); + break; + } + case ClientMainEventType.OnClientError: + { + // call original transport event + OnClientError?.Invoke(elem.error.Value, (string)elem.param); + break; + } + case ClientMainEventType.OnClientDisconnected: + { + // call original transport event + OnClientDisconnected?.Invoke(); + break; + } + } + + // process only up to N messages per tick here. + // if main thread becomes too slow, we don't want to deadlock. + if (++processed >= MaxProcessingPerTick) + { + Debug.LogWarning($"ThreadedTransport processed the limit of {MaxProcessingPerTick} messages this tick. Continuing next tick to prevent deadlock."); + break; + } + } + } + + // manual state flag because implementations can't access their + // threaded .server/.client state from main thread. + public override bool ClientConnected() => clientConnected; + + public override void ClientConnect(string address) + { + // don't connect the thread twice + if (ClientConnected()) + { + Debug.LogWarning($"Threaded transport: client already connected!"); + return; + } + + // enqueue to process in worker thread + EnqueueThread(ThreadEventType.DoClientConnect, address, null, null); + + // manual state flag because implementations can't access their + // threaded .server/.client state from main thread. + clientConnected = true; + } + + public override void ClientConnect(Uri uri) + { + // don't connect the thread twice + if (ClientConnected()) + { + Debug.LogWarning($"Threaded transport: client already connected!"); + return; + } + + // enqueue to process in worker thread + EnqueueThread(ThreadEventType.DoClientConnect, uri, null, null); + + // manual state flag because implementations can't access their + // threaded .server/.client state from main thread. + clientConnected = true; + } + + public override void ClientSend(ArraySegment segment, int channelId = Channels.Reliable) + { + if (!ClientConnected()) return; + + // segment is only valid until returning. + // copy it to a writer. + // make sure to recycle it from worker thread. + ConcurrentNetworkWriterPooled writer = ConcurrentNetworkWriterPool.Get(); + writer.WriteBytes(segment.Array, segment.Offset, segment.Count); + + // enqueue to process in worker thread + EnqueueThread(ThreadEventType.DoClientSend, writer, channelId, null); + } + + public override void ClientDisconnect() + { + EnqueueThread(ThreadEventType.DoClientDisconnect, null, null, null); + + // manual state flag because implementations can't access their + // threaded .server/.client state from main thread. + clientConnected = false; + } + + // server ////////////////////////////////////////////////////////////// + // implementations need to use ThreadedEarlyUpdate + public override void ServerEarlyUpdate() + { + // regular transports process OnReceive etc. from early update. + // need to process the worker thread's queued events here too. + // + // process only up to N messages per tick here. + // if main thread becomes too slow, we don't want to deadlock. + int processed = 0; + while (serverMainQueue.TryDequeue(out ServerMainEvent elem)) + { + switch (elem.type) + { + // SERVER EVENTS /////////////////////////////////////////// + case ServerMainEventType.OnServerConnected: + { + // call original transport event + // TODO pass client address in OnConnect here later + OnServerConnected?.Invoke(elem.connectionId.Value);//, (string)elem.param); + break; + } + case ServerMainEventType.OnServerSent: + { + // call original transport event + ConcurrentNetworkWriterPooled writer = (ConcurrentNetworkWriterPooled)elem.param; + OnServerDataSent?.Invoke(elem.connectionId.Value, writer, elem.channelId.Value); + + // recycle writer to thread safe pool for reuse + ConcurrentNetworkWriterPool.Return(writer); + break; + } + case ServerMainEventType.OnServerReceived: + { + // call original transport event + ConcurrentNetworkWriterPooled writer = (ConcurrentNetworkWriterPooled)elem.param; + OnServerDataReceived?.Invoke(elem.connectionId.Value, writer, elem.channelId.Value); + + // recycle writer to thread safe pool for reuse + ConcurrentNetworkWriterPool.Return(writer); + break; + } + case ServerMainEventType.OnServerError: + { + // call original transport event + OnServerError?.Invoke(elem.connectionId.Value, elem.error.Value, (string)elem.param); + break; + } + case ServerMainEventType.OnServerDisconnected: + { + // call original transport event + OnServerDisconnected?.Invoke(elem.connectionId.Value); + break; + } + } + + // process only up to N messages per tick here. + // if main thread becomes too slow, we don't want to deadlock. + if (++processed >= MaxProcessingPerTick) + { + Debug.LogWarning($"ThreadedTransport processed the limit of {MaxProcessingPerTick} messages this tick. Continuing next tick to prevent deadlock."); + break; + } + } + } + + // implementations need to use ThreadedLateUpdate + public override void ServerLateUpdate() {} + + // manual state flag because implementations can't access their + // threaded .server/.client state from main thread. + public override bool ServerActive() => serverActive; + + public override void ServerStart() + { + // don't start the thread twice + if (ServerActive()) + { + Debug.LogWarning($"Threaded transport: server already started!"); + return; + } + + // enqueue to process in worker thread + EnqueueThread(ThreadEventType.DoServerStart, null, null, null); + + // manual state flag because implementations can't access their + // threaded .server/.client state from main thread. + serverActive = true; + } + + public override void ServerSend(int connectionId, ArraySegment segment, int channelId = Channels.Reliable) + { + if (!ServerActive()) return; + + // segment is only valid until returning. + // copy it to a writer. + // make sure to recycle it from worker thread. + ConcurrentNetworkWriterPooled writer = ConcurrentNetworkWriterPool.Get(); + writer.WriteBytes(segment.Array, segment.Offset, segment.Count); + + // enqueue to process in worker thread + EnqueueThread(ThreadEventType.DoServerSend, writer, channelId, connectionId); + } + + public override void ServerDisconnect(int connectionId) + { + // enqueue to process in worker thread + EnqueueThread(ThreadEventType.DoServerDisconnect, null, null, connectionId); + } + + // TODO pass address in OnConnected. + // querying this at runtime won't work for threaded transports. + public override string ServerGetClientAddress(int connectionId) + { + throw new NotImplementedException(); + } + + public override void ServerStop() + { + // enqueue to process in worker thread + EnqueueThread(ThreadEventType.DoServerStop, null, null, null); + + // manual state flag because implementations can't access their + // threaded .server/.client state from main thread. + serverActive = false; + } + + // shutdown //////////////////////////////////////////////////////////// + public override void Shutdown() + { + // enqueue to process in worker thread + EnqueueThread(ThreadEventType.DoShutdown, null, null, null); + + // need to wait a little for worker thread to process the enqueued + // Shutdown event and do proper cleanup. + // + // otherwise if a server with a connected client is stopped, + // and then started, a warning would be shown when starting again + // about an old connection not being found because it wasn't cleared + // in KCP + // TODO cleaner + Thread.Sleep(100); + + // stop thread fully, with timeout + // ?.: 'thread' might be null after script reload -> stop play + thread?.StopBlocking(1); + + // clear queues so we don't process old messages + // when listening again later + clientMainQueue.Clear(); + serverMainQueue.Clear(); + threadQueue.Clear(); + } + } +} diff --git a/Assets/Mirror/Transports/Threaded/ThreadedTransport.cs.meta b/Assets/Mirror/Transports/Threaded/ThreadedTransport.cs.meta new file mode 100644 index 0000000..7b1d0e8 --- /dev/null +++ b/Assets/Mirror/Transports/Threaded/ThreadedTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af1f2befa05c14b2ea463791ae56081e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Version.txt b/Assets/Mirror/Version.txt new file mode 100644 index 0000000..4556dc6 --- /dev/null +++ b/Assets/Mirror/Version.txt @@ -0,0 +1 @@ +89.0.0 \ No newline at end of file diff --git a/Assets/Mirror/Version.txt.meta b/Assets/Mirror/Version.txt.meta new file mode 100644 index 0000000..097f259 --- /dev/null +++ b/Assets/Mirror/Version.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c6b1f72568a9340178b4c34608fbdbc3 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync.meta b/Assets/ParrelSync.meta new file mode 100644 index 0000000..737c5bd --- /dev/null +++ b/Assets/ParrelSync.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bd07209623118fc46a32850135be3f32 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/Examples.meta b/Assets/ParrelSync/Examples.meta new file mode 100644 index 0000000..9d4eb9a --- /dev/null +++ b/Assets/ParrelSync/Examples.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 654be33bd44a76a4c8c180d1da6ad066 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/Examples/CustomArgumentExample.cs b/Assets/ParrelSync/Examples/CustomArgumentExample.cs new file mode 100644 index 0000000..3d9b1a6 --- /dev/null +++ b/Assets/ParrelSync/Examples/CustomArgumentExample.cs @@ -0,0 +1,31 @@ +// This should be editor only +#if UNITY_EDITOR +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace ParrelSync.Example +{ + public class CustomArgumentExample : MonoBehaviour + { + // Start is called before the first frame update + void Start() + { + // Is this editor instance running a clone project? + if (ClonesManager.IsClone()) + { + Debug.Log("This is a clone project."); + + //Argument can be set from the clones manager window. + string customArgument = ClonesManager.GetArgument(); + Debug.Log("The custom argument of this clone project is: " + customArgument); + // Do what ever you need with the argument string. + } + else + { + Debug.Log("This is the original project."); + } + } + } +} +#endif \ No newline at end of file diff --git a/Assets/ParrelSync/Examples/CustomArgumentExample.cs.meta b/Assets/ParrelSync/Examples/CustomArgumentExample.cs.meta new file mode 100644 index 0000000..a7043c3 --- /dev/null +++ b/Assets/ParrelSync/Examples/CustomArgumentExample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 346d302ecc25a9a41b48b857ce51d873 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/LICENSE.md b/Assets/ParrelSync/LICENSE.md new file mode 100644 index 0000000..5324dda --- /dev/null +++ b/Assets/ParrelSync/LICENSE.md @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2018 Greg M +Copyright (c) 2020 Ian and Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Assets/ParrelSync/LICENSE.md.meta b/Assets/ParrelSync/LICENSE.md.meta new file mode 100644 index 0000000..e0f1a8b --- /dev/null +++ b/Assets/ParrelSync/LICENSE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f4b327eab8d866e4087e166da8cafc09 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync.meta b/Assets/ParrelSync/ParrelSync.meta new file mode 100644 index 0000000..890e8df --- /dev/null +++ b/Assets/ParrelSync/ParrelSync.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f5fec620d3bc9546a41a5b67cb9f8b6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor.meta b/Assets/ParrelSync/ParrelSync/Editor.meta new file mode 100644 index 0000000..56fd131 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a31ea7d0315594440839cdb0db6bc411 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock.meta b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock.meta new file mode 100644 index 0000000..3bb4f70 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8b14e706b1e7cb044b23837e8a70cad9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/EditorQuit.cs b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/EditorQuit.cs new file mode 100644 index 0000000..dc181d1 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/EditorQuit.cs @@ -0,0 +1,22 @@ +using UnityEditor; +namespace ParrelSync +{ + [InitializeOnLoad] + public class EditorQuit + { + /// + /// Is editor being closed + /// + static public bool IsQuiting { get; private set; } + static void Quit() + { + IsQuiting = true; + } + + static EditorQuit() + { + IsQuiting = false; + EditorApplication.quitting += Quit; + } + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/EditorQuit.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/EditorQuit.cs.meta new file mode 100644 index 0000000..2296dac --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/EditorQuit.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bf2888ff90706904abc2d851c3e59e00 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/ParrelSyncAssetModificationProcessor.cs b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/ParrelSyncAssetModificationProcessor.cs new file mode 100644 index 0000000..6587482 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/ParrelSyncAssetModificationProcessor.cs @@ -0,0 +1,34 @@ +using UnityEditor; +using UnityEngine; +namespace ParrelSync +{ + /// + /// For preventing assets being modified from the clone instance. + /// + public class ParrelSyncAssetModificationProcessor : UnityEditor.AssetModificationProcessor + { + public static string[] OnWillSaveAssets(string[] paths) + { + if (ClonesManager.IsClone() && Preferences.AssetModPref.Value) + { + if (paths != null && paths.Length > 0 && !EditorQuit.IsQuiting) + { + EditorUtility.DisplayDialog( + ClonesManager.ProjectName + ": Asset modifications saving detected and blocked", + "Asset modifications saving are blocked in the clone instance. \n\n" + + "This is a clone of the original project. \n" + + "Making changes to asset files via the clone editor is not recommended. \n" + + "Please use the original editor window if you want to make changes to the project files.", + "ok" + ); + foreach (var path in paths) + { + Debug.Log("Attempting to save " + path + " are blocked."); + } + } + return new string[0] { }; + } + return paths; + } + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/ParrelSyncAssetModificationProcessor.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/ParrelSyncAssetModificationProcessor.cs.meta new file mode 100644 index 0000000..7158175 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/AssetModBlock/ParrelSyncAssetModificationProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 755e570bd21b39440a923056e60f1450 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/ClonesManager.cs b/Assets/ParrelSync/ParrelSync/Editor/ClonesManager.cs new file mode 100644 index 0000000..9fd125a --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/ClonesManager.cs @@ -0,0 +1,668 @@ +using System.Collections.Generic; +using System.Diagnostics; +using UnityEngine; +using UnityEditor; +using System.Linq; +using System.IO; +using Debug = UnityEngine.Debug; + +namespace ParrelSync +{ + /// + /// Contains all required methods for creating a linked clone of the Unity project. + /// + public class ClonesManager + { + /// + /// Name used for an identifying file created in the clone project directory. + /// + /// + /// (!) Do not change this after the clone was created, because then connection will be lost. + /// + public const string CloneFileName = ".clone"; + + /// + /// Suffix added to the end of the project clone name when it is created. + /// + /// + /// (!) Do not change this after the clone was created, because then connection will be lost. + /// + public const string CloneNameSuffix = "_clone"; + + public const string ProjectName = "ParrelSync"; + + /// + /// The maximum number of clones + /// + public const int MaxCloneProjectCount = 10; + + /// + /// Name of the file for storing clone's argument. + /// + public const string ArgumentFileName = ".parrelsyncarg"; + + /// + /// Default argument of the new clone + /// + public const string DefaultArgument = "client"; + + #region Managing clones + + /// + /// Creates clone from the project currently open in Unity Editor. + /// + /// + public static Project CreateCloneFromCurrent() + { + if (IsClone()) + { + Debug.LogError("This project is already a clone. Cannot clone it."); + return null; + } + + string currentProjectPath = ClonesManager.GetCurrentProjectPath(); + return ClonesManager.CreateCloneFromPath(currentProjectPath); + } + + /// + /// Creates clone of the project located at the given path. + /// + /// + /// + public static Project CreateCloneFromPath(string sourceProjectPath) + { + Project sourceProject = new Project(sourceProjectPath); + + string cloneProjectPath = null; + + //Find available clone suffix id + for (int i = 0; i < MaxCloneProjectCount; i++) + { + string originalProjectPath = ClonesManager.GetCurrentProject().projectPath; + string possibleCloneProjectPath = originalProjectPath + ClonesManager.CloneNameSuffix + "_" + i; + + if (!Directory.Exists(possibleCloneProjectPath)) + { + cloneProjectPath = possibleCloneProjectPath; + break; + } + } + + if (string.IsNullOrEmpty(cloneProjectPath)) + { + Debug.LogError("The number of cloned projects has reach its limit. Limit: " + MaxCloneProjectCount); + return null; + } + + Project cloneProject = new Project(cloneProjectPath); + + Debug.Log("Start cloning project, original project: " + sourceProject + ", clone project: " + cloneProject); + + ClonesManager.CreateProjectFolder(cloneProject); + + //Copy Folders + Debug.Log("Library copy: " + cloneProject.libraryPath); + ClonesManager.CopyDirectoryWithProgressBar(sourceProject.libraryPath, cloneProject.libraryPath, + "Cloning Project Library '" + sourceProject.name + "'. "); + Debug.Log("Packages copy: " + cloneProject.libraryPath); + ClonesManager.CopyDirectoryWithProgressBar(sourceProject.packagesPath, cloneProject.packagesPath, + "Cloning Project Packages '" + sourceProject.name + "'. "); + + + //Link Folders + ClonesManager.LinkFolders(sourceProject.assetPath, cloneProject.assetPath); + ClonesManager.LinkFolders(sourceProject.projectSettingsPath, cloneProject.projectSettingsPath); + ClonesManager.LinkFolders(sourceProject.autoBuildPath, cloneProject.autoBuildPath); + ClonesManager.LinkFolders(sourceProject.localPackages, cloneProject.localPackages); + + ClonesManager.RegisterClone(cloneProject); + + return cloneProject; + } + + /// + /// Registers a clone by placing an identifying ".clone" file in its root directory. + /// + /// + private static void RegisterClone(Project cloneProject) + { + /// Add clone identifier file. + string identifierFile = Path.Combine(cloneProject.projectPath, ClonesManager.CloneFileName); + File.Create(identifierFile).Dispose(); + + //Add argument file with default argument + string argumentFilePath = Path.Combine(cloneProject.projectPath, ClonesManager.ArgumentFileName); + File.WriteAllText(argumentFilePath, DefaultArgument, System.Text.Encoding.UTF8); + + /// Add collabignore.txt to stop the clone from messing with Unity Collaborate if it's enabled. Just in case. + string collabignoreFile = Path.Combine(cloneProject.projectPath, "collabignore.txt"); + File.WriteAllText(collabignoreFile, "*"); /// Make it ignore ALL files in the clone. + } + + /// + /// Opens a project located at the given path (if one exists). + /// + /// + public static void OpenProject(string projectPath) + { + if (!Directory.Exists(projectPath)) + { + Debug.LogError("Cannot open the project - provided folder (" + projectPath + ") does not exist."); + return; + } + + if (projectPath == ClonesManager.GetCurrentProjectPath()) + { + Debug.LogError("Cannot open the project - it is already open."); + return; + } + + //Validate (and update if needed) the "Packages" folder before opening clone project to ensure the clone project will have the + //same "compiling environment" as the original project + ValidateCopiedFoldersIntegrity.ValidateFolder(projectPath, GetOriginalProjectPath(), "Packages"); + + string fileName = GetApplicationPath(); + string args = "-projectPath \"" + projectPath + "\""; + Debug.Log("Opening project \"" + fileName + " " + args + "\""); + ClonesManager.StartHiddenConsoleProcess(fileName, args); + } + + private static string GetApplicationPath() + { + switch (Application.platform) + { + case RuntimePlatform.WindowsEditor: + return EditorApplication.applicationPath; + case RuntimePlatform.OSXEditor: + return EditorApplication.applicationPath + "/Contents/MacOS/Unity"; + case RuntimePlatform.LinuxEditor: + return EditorApplication.applicationPath; + default: + throw new System.NotImplementedException("Platform has not supported yet ;("); + } + } + + /// + /// Is this project being opened by an Unity editor? + /// + /// + /// + public static bool IsCloneProjectRunning(string projectPath) + { + + //Determine whether it is opened in another instance by checking the UnityLockFile + string UnityLockFilePath = new string[] { projectPath, "Temp", "UnityLockfile" } + .Aggregate(Path.Combine); + + switch (Application.platform) + { + case (RuntimePlatform.WindowsEditor): + //Windows editor will lock "UnityLockfile" file when project is being opened. + //Sometime, for instance: windows editor crash, the "UnityLockfile" will not be deleted even the project + //isn't being opened, so a check to the "UnityLockfile" lock status may be necessary. + if (Preferences.AlsoCheckUnityLockFileStaPref.Value) + return File.Exists(UnityLockFilePath) && FileUtilities.IsFileLocked(UnityLockFilePath); + else + return File.Exists(UnityLockFilePath); + case (RuntimePlatform.OSXEditor): + //Mac editor won't lock "UnityLockfile" file when project is being opened + return File.Exists(UnityLockFilePath); + case (RuntimePlatform.LinuxEditor): + return File.Exists(UnityLockFilePath); + default: + throw new System.NotImplementedException("IsCloneProjectRunning: Unsupport Platfrom: " + Application.platform); + } + } + + /// + /// Deletes the clone of the currently open project, if such exists. + /// + public static void DeleteClone(string cloneProjectPath) + { + /// Clone won't be able to delete itself. + if (ClonesManager.IsClone()) return; + + ///Extra precautions. + if (cloneProjectPath == string.Empty) return; + if (cloneProjectPath == ClonesManager.GetOriginalProjectPath()) return; + + //Check what OS is + string identifierFile; + string args; + switch (Application.platform) + { + case (RuntimePlatform.WindowsEditor): + Debug.Log("Attempting to delete folder \"" + cloneProjectPath + "\""); + + //The argument file will be deleted first at the beginning of the project deletion process + //to prevent any further reading and writing to it(There's a File.Exist() check at the (file)editor windows.) + //If there's any file in the directory being write/read during the deletion process, the directory can't be fully removed. + identifierFile = Path.Combine(cloneProjectPath, ClonesManager.ArgumentFileName); + File.Delete(identifierFile); + + args = "/c " + @"rmdir /s/q " + string.Format("\"{0}\"", cloneProjectPath); + StartHiddenConsoleProcess("cmd.exe", args); + + break; + case (RuntimePlatform.OSXEditor): + Debug.Log("Attempting to delete folder \"" + cloneProjectPath + "\""); + + //The argument file will be deleted first at the beginning of the project deletion process + //to prevent any further reading and writing to it(There's a File.Exist() check at the (file)editor windows.) + //If there's any file in the directory being write/read during the deletion process, the directory can't be fully removed. + identifierFile = Path.Combine(cloneProjectPath, ClonesManager.ArgumentFileName); + File.Delete(identifierFile); + + FileUtil.DeleteFileOrDirectory(cloneProjectPath); + + break; + case (RuntimePlatform.LinuxEditor): + Debug.Log("Attempting to delete folder \"" + cloneProjectPath + "\""); + identifierFile = Path.Combine(cloneProjectPath, ClonesManager.ArgumentFileName); + File.Delete(identifierFile); + + FileUtil.DeleteFileOrDirectory(cloneProjectPath); + + break; + default: + Debug.LogWarning("Not in a known editor. Where are you!?"); + break; + } + } + + #endregion + + #region Creating project folders + + /// + /// Creates an empty folder using data in the given Project object + /// + /// + public static void CreateProjectFolder(Project project) + { + string path = project.projectPath; + Debug.Log("Creating new empty folder at: " + path); + Directory.CreateDirectory(path); + } + + /// + /// Copies the full contents of the unity library. We want to do this to avoid the lengthy re-serialization of the whole project when it opens up the clone. + /// + /// + /// + [System.Obsolete] + public static void CopyLibraryFolder(Project sourceProject, Project destinationProject) + { + if (Directory.Exists(destinationProject.libraryPath)) + { + Debug.LogWarning("Library copy: destination path already exists! "); + return; + } + + Debug.Log("Library copy: " + destinationProject.libraryPath); + ClonesManager.CopyDirectoryWithProgressBar(sourceProject.libraryPath, destinationProject.libraryPath, + "Cloning project '" + sourceProject.name + "'. "); + } + + #endregion + + #region Creating symlinks + + /// + /// Creates a symlink between destinationPath and sourcePath (Mac version). + /// + /// + /// + private static void CreateLinkMac(string sourcePath, string destinationPath) + { + sourcePath = sourcePath.Replace(" ", "\\ "); + destinationPath = destinationPath.Replace(" ", "\\ "); + var command = string.Format("ln -s {0} {1}", sourcePath, destinationPath); + + Debug.Log("Mac hard link " + command); + + ClonesManager.ExecuteBashCommand(command); + } + + /// + /// Creates a symlink between destinationPath and sourcePath (Linux version). + /// + /// + /// + private static void CreateLinkLinux(string sourcePath, string destinationPath) + { + sourcePath = sourcePath.Replace(" ", "\\ "); + destinationPath = destinationPath.Replace(" ", "\\ "); + var command = string.Format("ln -s {0} {1}", sourcePath, destinationPath); + + Debug.Log("Linux Symlink " + command); + + ClonesManager.ExecuteBashCommand(command); + } + + /// + /// Creates a symlink between destinationPath and sourcePath (Windows version). + /// + /// + /// + private static void CreateLinkWin(string sourcePath, string destinationPath) + { + string cmd = "/C mklink /J " + string.Format("\"{0}\" \"{1}\"", destinationPath, sourcePath); + Debug.Log("Windows junction: " + cmd); + ClonesManager.StartHiddenConsoleProcess("cmd.exe", cmd); + } + + //TODO(?) avoid terminal calls and use proper api stuff. See below for windows! + ////https://docs.microsoft.com/en-us/windows/desktop/api/ioapiset/nf-ioapiset-deviceiocontrol + //[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + //private static extern bool DeviceIoControl(System.IntPtr hDevice, uint dwIoControlCode, + // System.IntPtr InBuffer, int nInBufferSize, + // System.IntPtr OutBuffer, int nOutBufferSize, + // out int pBytesReturned, System.IntPtr lpOverlapped); + + /// + /// Create a link / junction from the original project to it's clone. + /// + /// + /// + public static void LinkFolders(string sourcePath, string destinationPath) + { + if ((Directory.Exists(destinationPath) == false) && (Directory.Exists(sourcePath) == true)) + { + switch (Application.platform) + { + case (RuntimePlatform.WindowsEditor): + CreateLinkWin(sourcePath, destinationPath); + break; + case (RuntimePlatform.OSXEditor): + CreateLinkMac(sourcePath, destinationPath); + break; + case (RuntimePlatform.LinuxEditor): + CreateLinkLinux(sourcePath, destinationPath); + break; + default: + Debug.LogWarning("Not in a known editor. Application.platform: " + Application.platform); + break; + } + } + else + { + Debug.LogWarning("Skipping Asset link, it already exists: " + destinationPath); + } + } + + #endregion + + #region Utility methods + + private static bool? isCloneFileExistCache = null; + + /// + /// Returns true if the project currently open in Unity Editor is a clone. + /// + /// + public static bool IsClone() + { + if (isCloneFileExistCache == null) + { + /// The project is a clone if its root directory contains an empty file named ".clone". + string cloneFilePath = Path.Combine(ClonesManager.GetCurrentProjectPath(), ClonesManager.CloneFileName); + isCloneFileExistCache = File.Exists(cloneFilePath); + } + + return (bool)isCloneFileExistCache; + } + + /// + /// Get the path to the current unityEditor project folder's info + /// + /// + public static string GetCurrentProjectPath() + { + return Application.dataPath.Replace("/Assets", ""); + } + + /// + /// Return a project object that describes all the paths we need to clone it. + /// + /// + public static Project GetCurrentProject() + { + string pathString = ClonesManager.GetCurrentProjectPath(); + return new Project(pathString); + } + + /// + /// Get the argument of this clone project. + /// If this is the original project, will return an empty string. + /// + /// + public static string GetArgument() + { + string argument = ""; + if (IsClone()) + { + string argumentFilePath = Path.Combine(GetCurrentProjectPath(), ClonesManager.ArgumentFileName); + if (File.Exists(argumentFilePath)) + { + argument = File.ReadAllText(argumentFilePath, System.Text.Encoding.UTF8); + } + } + + return argument; + } + + /// + /// Returns the path to the original project. + /// If currently open project is the original, returns its own path. + /// If the original project folder cannot be found, retuns an empty string. + /// + /// + public static string GetOriginalProjectPath() + { + if (IsClone()) + { + /// If this is a clone... + /// Original project path can be deduced by removing the suffix from the clone's path. + string cloneProjectPath = ClonesManager.GetCurrentProject().projectPath; + + int index = cloneProjectPath.LastIndexOf(ClonesManager.CloneNameSuffix); + if (index > 0) + { + string originalProjectPath = cloneProjectPath.Substring(0, index); + if (Directory.Exists(originalProjectPath)) return originalProjectPath; + } + + return string.Empty; + } + else + { + /// If this is the original, we return its own path. + return ClonesManager.GetCurrentProjectPath(); + } + } + + /// + /// Returns all clone projects path. + /// + /// + public static List GetCloneProjectsPath() + { + List projectsPath = new List(); + for (int i = 0; i < MaxCloneProjectCount; i++) + { + string originalProjectPath = ClonesManager.GetCurrentProject().projectPath; + string cloneProjectPath = originalProjectPath + ClonesManager.CloneNameSuffix + "_" + i; + + if (Directory.Exists(cloneProjectPath)) + projectsPath.Add(cloneProjectPath); + } + + return projectsPath; + } + + /// + /// Copies directory located at sourcePath to destinationPath. Displays a progress bar. + /// + /// Directory to be copied. + /// Destination directory (created automatically if needed). + /// Optional string added to the beginning of the progress bar window header. + public static void CopyDirectoryWithProgressBar(string sourcePath, string destinationPath, + string progressBarPrefix = "") + { + var source = new DirectoryInfo(sourcePath); + var destination = new DirectoryInfo(destinationPath); + + long totalBytes = 0; + long copiedBytes = 0; + + ClonesManager.CopyDirectoryWithProgressBarRecursive(source, destination, ref totalBytes, ref copiedBytes, + progressBarPrefix); + EditorUtility.ClearProgressBar(); + } + + /// + /// Copies directory located at sourcePath to destinationPath. Displays a progress bar. + /// Same as the previous method, but uses recursion to copy all nested folders as well. + /// + /// Directory to be copied. + /// Destination directory (created automatically if needed). + /// Total bytes to be copied. Calculated automatically, initialize at 0. + /// To track already copied bytes. Calculated automatically, initialize at 0. + /// Optional string added to the beginning of the progress bar window header. + private static void CopyDirectoryWithProgressBarRecursive(DirectoryInfo source, DirectoryInfo destination, + ref long totalBytes, ref long copiedBytes, string progressBarPrefix = "") + { + /// Directory cannot be copied into itself. + if (source.FullName.ToLower() == destination.FullName.ToLower()) + { + Debug.LogError("Cannot copy directory into itself."); + return; + } + + /// Calculate total bytes, if required. + if (totalBytes == 0) + { + totalBytes = ClonesManager.GetDirectorySize(source, true, progressBarPrefix); + } + + /// Create destination directory, if required. + if (!Directory.Exists(destination.FullName)) + { + Directory.CreateDirectory(destination.FullName); + } + + /// Copy all files from the source. + foreach (FileInfo file in source.GetFiles()) + { + try + { + file.CopyTo(Path.Combine(destination.ToString(), file.Name), true); + } + catch (IOException) + { + /// Some files may throw IOException if they are currently open in Unity editor. + /// Just ignore them in such case. + } + + /// Account the copied file size. + copiedBytes += file.Length; + + /// Display the progress bar. + float progress = (float)copiedBytes / (float)totalBytes; + bool cancelCopy = EditorUtility.DisplayCancelableProgressBar( + progressBarPrefix + "Copying '" + source.FullName + "' to '" + destination.FullName + "'...", + "(" + (progress * 100f).ToString("F2") + "%) Copying file '" + file.Name + "'...", + progress); + if (cancelCopy) return; + } + + /// Copy all nested directories from the source. + foreach (DirectoryInfo sourceNestedDir in source.GetDirectories()) + { + DirectoryInfo nextDestingationNestedDir = destination.CreateSubdirectory(sourceNestedDir.Name); + ClonesManager.CopyDirectoryWithProgressBarRecursive(sourceNestedDir, nextDestingationNestedDir, + ref totalBytes, ref copiedBytes, progressBarPrefix); + } + } + + /// + /// Calculates the size of the given directory. Displays a progress bar. + /// + /// Directory, which size has to be calculated. + /// If true, size will include all nested directories. + /// Optional string added to the beginning of the progress bar window header. + /// Size of the directory in bytes. + private static long GetDirectorySize(DirectoryInfo directory, bool includeNested = false, + string progressBarPrefix = "") + { + EditorUtility.DisplayProgressBar(progressBarPrefix + "Calculating size of directories...", + "Scanning '" + directory.FullName + "'...", 0f); + + /// Calculate size of all files in directory. + long filesSize = directory.GetFiles().Sum((FileInfo file) => file.Length); + + /// Calculate size of all nested directories. + long directoriesSize = 0; + if (includeNested) + { + IEnumerable nestedDirectories = directory.GetDirectories(); + foreach (DirectoryInfo nestedDir in nestedDirectories) + { + directoriesSize += ClonesManager.GetDirectorySize(nestedDir, true, progressBarPrefix); + } + } + + return filesSize + directoriesSize; + } + + /// + /// Starts process in the system console, taking the given fileName and args. + /// + /// + /// + private static void StartHiddenConsoleProcess(string fileName, string args) + { + System.Diagnostics.Process.Start(fileName, args); + } + + /// + /// Thanks to https://github.com/karl-/unity-symlink-utility/blob/master/SymlinkUtility.cs + /// + /// + private static void ExecuteBashCommand(string command) + { + command = command.Replace("\"", "\"\""); + + var proc = new Process() + { + StartInfo = new ProcessStartInfo + { + FileName = "/bin/bash", + Arguments = "-c \"" + command + "\"", + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + } + }; + + using (proc) + { + proc.Start(); + proc.WaitForExit(); + + if (!proc.StandardError.EndOfStream) + { + UnityEngine.Debug.LogError(proc.StandardError.ReadToEnd()); + } + } + } + + public static void OpenProjectInFileExplorer(string path) + { + System.Diagnostics.Process.Start(@path); + } + #endregion + } +} diff --git a/Assets/ParrelSync/ParrelSync/Editor/ClonesManager.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/ClonesManager.cs.meta new file mode 100644 index 0000000..5800cf8 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/ClonesManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6148e48ed6b61d748b187d06d3687b83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/ClonesManagerWindow.cs b/Assets/ParrelSync/ParrelSync/Editor/ClonesManagerWindow.cs new file mode 100644 index 0000000..ad9619e --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/ClonesManagerWindow.cs @@ -0,0 +1,198 @@ +using UnityEngine; +using UnityEditor; +using System.IO; + +namespace ParrelSync +{ + /// + ///Clones manager Unity editor window + /// + public class ClonesManagerWindow : EditorWindow + { + /// + /// Returns true if project clone exists. + /// + public bool isCloneCreated + { + get { return ClonesManager.GetCloneProjectsPath().Count >= 1; } + } + + [MenuItem("ParrelSync/Clones Manager", priority = 0)] + private static void InitWindow() + { + ClonesManagerWindow window = (ClonesManagerWindow)EditorWindow.GetWindow(typeof(ClonesManagerWindow)); + window.titleContent = new GUIContent("Clones Manager"); + window.Show(); + } + + /// + /// For storing the scroll position of clones list + /// + Vector2 clonesScrollPos; + + private void OnGUI() + { + /// If it is a clone project... + if (ClonesManager.IsClone()) + { + //Find out the original project name and show the help box + string originalProjectPath = ClonesManager.GetOriginalProjectPath(); + if (originalProjectPath == string.Empty) + { + /// If original project cannot be found, display warning message. + EditorGUILayout.HelpBox( + "This project is a clone, but the link to the original seems lost.\nYou have to manually open the original and create a new clone instead of this one.\n", + MessageType.Warning); + } + else + { + /// If original project is present, display some usage info. + EditorGUILayout.HelpBox( + "This project is a clone of the project '" + Path.GetFileName(originalProjectPath) + "'.\nIf you want to make changes the project files or manage clones, please open the original project through Unity Hub.", + MessageType.Info); + } + + //Clone project custom argument. + GUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Arguments", GUILayout.Width(70)); + if (GUILayout.Button("?", GUILayout.Width(20))) + { + Application.OpenURL(ExternalLinks.CustomArgumentHelpLink); + } + GUILayout.EndHorizontal(); + + string argumentFilePath = Path.Combine(ClonesManager.GetCurrentProjectPath(), ClonesManager.ArgumentFileName); + //Need to be careful with file reading / writing since it will effect the deletion of + // the clone project(The directory won't be fully deleted if there's still file inside being read or write). + //The argument file will be deleted first at the beginning of the project deletion process + //to prevent any further being read and write. + //Will need to take some extra cautious if want to change the design of how file editing is handled. + if (File.Exists(argumentFilePath)) + { + string argument = File.ReadAllText(argumentFilePath, System.Text.Encoding.UTF8); + string argumentTextAreaInput = EditorGUILayout.TextArea(argument, + GUILayout.Height(50), + GUILayout.MaxWidth(300) + ); + File.WriteAllText(argumentFilePath, argumentTextAreaInput, System.Text.Encoding.UTF8); + } + else + { + EditorGUILayout.LabelField("No argument file found."); + } + } + else// If it is an original project... + { + if (isCloneCreated) + { + GUILayout.BeginVertical("HelpBox"); + GUILayout.Label("Clones of this Project"); + + //List all clones + clonesScrollPos = + EditorGUILayout.BeginScrollView(clonesScrollPos); + var cloneProjectsPath = ClonesManager.GetCloneProjectsPath(); + for (int i = 0; i < cloneProjectsPath.Count; i++) + { + + GUILayout.BeginVertical("GroupBox"); + string cloneProjectPath = cloneProjectsPath[i]; + + bool isOpenInAnotherInstance = ClonesManager.IsCloneProjectRunning(cloneProjectPath); + + if (isOpenInAnotherInstance == true) + EditorGUILayout.LabelField("Clone " + i + " (Running)", EditorStyles.boldLabel); + else + EditorGUILayout.LabelField("Clone " + i); + + + GUILayout.BeginHorizontal(); + EditorGUILayout.TextField("Clone project path", cloneProjectPath, EditorStyles.textField); + if (GUILayout.Button("View Folder", GUILayout.Width(80))) + { + ClonesManager.OpenProjectInFileExplorer(cloneProjectPath); + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Arguments", GUILayout.Width(70)); + if (GUILayout.Button("?", GUILayout.Width(20))) + { + Application.OpenURL(ExternalLinks.CustomArgumentHelpLink); + } + GUILayout.EndHorizontal(); + + string argumentFilePath = Path.Combine(cloneProjectPath, ClonesManager.ArgumentFileName); + //Need to be careful with file reading/writing since it will effect the deletion of + //the clone project(The directory won't be fully deleted if there's still file inside being read or write). + //The argument file will be deleted first at the beginning of the project deletion process + //to prevent any further being read and write. + //Will need to take some extra cautious if want to change the design of how file editing is handled. + if (File.Exists(argumentFilePath)) + { + string argument = File.ReadAllText(argumentFilePath, System.Text.Encoding.UTF8); + string argumentTextAreaInput = EditorGUILayout.TextArea(argument, + GUILayout.Height(50), + GUILayout.MaxWidth(300) + ); + File.WriteAllText(argumentFilePath, argumentTextAreaInput, System.Text.Encoding.UTF8); + } + else + { + EditorGUILayout.LabelField("No argument file found."); + } + + EditorGUILayout.Space(); + EditorGUILayout.Space(); + EditorGUILayout.Space(); + + + EditorGUI.BeginDisabledGroup(isOpenInAnotherInstance); + + if (GUILayout.Button("Open in New Editor")) + { + ClonesManager.OpenProject(cloneProjectPath); + } + + GUILayout.BeginHorizontal(); + if (GUILayout.Button("Delete")) + { + bool delete = EditorUtility.DisplayDialog( + "Delete the clone?", + "Are you sure you want to delete the clone project '" + ClonesManager.GetCurrentProject().name + "_clone'?", + "Delete", + "Cancel"); + if (delete) + { + ClonesManager.DeleteClone(cloneProjectPath); + } + } + + GUILayout.EndHorizontal(); + EditorGUI.EndDisabledGroup(); + GUILayout.EndVertical(); + + } + EditorGUILayout.EndScrollView(); + + if (GUILayout.Button("Add new clone")) + { + ClonesManager.CreateCloneFromCurrent(); + } + + GUILayout.EndVertical(); + GUILayout.FlexibleSpace(); + } + else + { + /// If no clone created yet, we must create it. + EditorGUILayout.HelpBox("No project clones found. Create a new one!", MessageType.Info); + if (GUILayout.Button("Create new clone")) + { + ClonesManager.CreateCloneFromCurrent(); + } + } + } + } + } +} diff --git a/Assets/ParrelSync/ParrelSync/Editor/ClonesManagerWindow.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/ClonesManagerWindow.cs.meta new file mode 100644 index 0000000..ac75a04 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/ClonesManagerWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a041d83486c20b84bbf5077ddfbbca37 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/ExternalLinks.cs b/Assets/ParrelSync/ParrelSync/Editor/ExternalLinks.cs new file mode 100644 index 0000000..84809bc --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/ExternalLinks.cs @@ -0,0 +1,13 @@ +namespace ParrelSync +{ + public class ExternalLinks + { + public const string RemoteVersionURL = "https://raw.githubusercontent.com/VeriorPies/ParrelSync/master/VERSION.txt"; + public const string Releases = "https://github.com/VeriorPies/ParrelSync/releases"; + public const string CustomArgumentHelpLink = "https://github.com/VeriorPies/ParrelSync/wiki/Argument"; + + public const string GitHubHome = "https://github.com/VeriorPies/ParrelSync/"; + public const string GitHubIssue = "https://github.com/VeriorPies/ParrelSync/issues"; + public const string FAQ = "https://github.com/VeriorPies/ParrelSync/wiki/Troubleshooting-&-FAQs"; + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/ExternalLinks.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/ExternalLinks.cs.meta new file mode 100644 index 0000000..c238b5c --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/ExternalLinks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65daf17fbe5101b41977305639f30c65 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/FileUtilities.cs b/Assets/ParrelSync/ParrelSync/Editor/FileUtilities.cs new file mode 100644 index 0000000..4d0a239 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/FileUtilities.cs @@ -0,0 +1,31 @@ +using System.IO; +using UnityEngine; + +namespace ParrelSync +{ + public class FileUtilities : MonoBehaviour + { + public static bool IsFileLocked(string path) + { + FileInfo file = new FileInfo(path); + try + { + using (FileStream stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None)) + { + stream.Close(); + } + } + catch (IOException) + { + //the file is unavailable because it is: + //still being written to + //or being processed by another thread + //or does not exist (has already been processed) + return true; + } + + //file is not locked + return false; + } + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/FileUtilities.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/FileUtilities.cs.meta new file mode 100644 index 0000000..2733944 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/FileUtilities.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11fdc6f78f8c965499a870ca06dca6bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/NonCore.meta b/Assets/ParrelSync/ParrelSync/Editor/NonCore.meta new file mode 100644 index 0000000..5b4e192 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/NonCore.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 74a7aa389726f964ab34c52e208c2a43 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/NonCore/AskFeedbackDialog.cs b/Assets/ParrelSync/ParrelSync/Editor/NonCore/AskFeedbackDialog.cs new file mode 100644 index 0000000..2bb988a --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/NonCore/AskFeedbackDialog.cs @@ -0,0 +1,78 @@ +namespace ParrelSync.NonCore +{ + using UnityEditor; + using UnityEngine; + + /// + /// A simple script to display feedback/star dialog after certain time of project being opened/re-compiled. + /// Will only pop-up once unless "Remind me next time" are chosen. + /// Removing this file from project wont effect any other functions. + /// + [InitializeOnLoad] + public class AskFeedbackDialog + { + const string InitializeOnLoadCountKey = "ParrelSync_InitOnLoadCount", StopShowingKey = "ParrelSync_StopShowFeedBack"; + static AskFeedbackDialog() + { + if (EditorPrefs.HasKey(StopShowingKey)) { return; } + + int InitializeOnLoadCount = EditorPrefs.GetInt(InitializeOnLoadCountKey, 0); + if (InitializeOnLoadCount > 20) + { + ShowDialog(); + } + else + { + EditorPrefs.SetInt(InitializeOnLoadCountKey, InitializeOnLoadCount + 1); + } + } + + //[MenuItem("ParrelSync/(Debug)Show AskFeedbackDialog ")] + private static void ShowDialog() + { + int option = EditorUtility.DisplayDialogComplex("Do you like " + ParrelSync.ClonesManager.ProjectName + "?", + "Do you like " + ParrelSync.ClonesManager.ProjectName + "?\n" + + "If so, please don't hesitate to star it on GitHub and contribute to the project!", + "Star on GitHub", + "Close", + "Remind me next time" + ); + + switch (option) + { + // First parameter. + case 0: + Debug.Log("AskFeedbackDialog: Star on GitHub selected"); + EditorPrefs.SetBool(StopShowingKey, true); + EditorPrefs.DeleteKey(InitializeOnLoadCountKey); + Application.OpenURL(ExternalLinks.GitHubHome); + break; + // Second parameter. + case 1: + Debug.Log("AskFeedbackDialog: Close and never show again."); + EditorPrefs.SetBool(StopShowingKey, true); + EditorPrefs.DeleteKey(InitializeOnLoadCountKey); + break; + // Third parameter. + case 2: + Debug.Log("AskFeedbackDialog: Remind me next time"); + EditorPrefs.SetInt(InitializeOnLoadCountKey, 0); + break; + default: + //Debug.Log("Close windows."); + break; + } + } + + ///// + ///// For debug purpose + ///// + //[MenuItem("ParrelSync/(Debug)Delete AskFeedbackDialog keys")] + //private static void DebugDeleteAllKeys() + //{ + // EditorPrefs.DeleteKey(InitializeOnLoadCountKey); + // EditorPrefs.DeleteKey(StopShowingKey); + // Debug.Log("AskFeedbackDialog keys deleted"); + //} + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/NonCore/AskFeedbackDialog.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/NonCore/AskFeedbackDialog.cs.meta new file mode 100644 index 0000000..20a2a0b --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/NonCore/AskFeedbackDialog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 894412a5b602e6c4ba2cf2d01f4f92b5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/NonCore/OtherMenuItem.cs b/Assets/ParrelSync/ParrelSync/Editor/NonCore/OtherMenuItem.cs new file mode 100644 index 0000000..0f42af9 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/NonCore/OtherMenuItem.cs @@ -0,0 +1,26 @@ +namespace ParrelSync.NonCore +{ + using UnityEditor; + using UnityEngine; + + public class OtherMenuItem + { + [MenuItem("ParrelSync/GitHub/View this project on GitHub", priority = 10)] + private static void OpenGitHub() + { + Application.OpenURL(ExternalLinks.GitHubHome); + } + + [MenuItem("ParrelSync/GitHub/View FAQ", priority = 11)] + private static void OpenFAQ() + { + Application.OpenURL(ExternalLinks.FAQ); + } + + [MenuItem("ParrelSync/GitHub/View Issues", priority = 12)] + private static void OpenGitHubIssues() + { + Application.OpenURL(ExternalLinks.GitHubIssue); + } + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/NonCore/OtherMenuItem.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/NonCore/OtherMenuItem.cs.meta new file mode 100644 index 0000000..563d7a2 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/NonCore/OtherMenuItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7191fa4bfa12ae749b27f73ed292eaf1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/Preferences.cs b/Assets/ParrelSync/ParrelSync/Editor/Preferences.cs new file mode 100644 index 0000000..3ca653d --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/Preferences.cs @@ -0,0 +1,110 @@ +using UnityEngine; +using UnityEditor; + +namespace ParrelSync +{ + /// + /// To add value caching for functions + /// + public class BoolPreference + { + public string key { get; private set; } + public bool defaultValue { get; private set; } + public BoolPreference(string key, bool defaultValue) + { + this.key = key; + this.defaultValue = defaultValue; + } + + private bool? valueCache = null; + + public bool Value + { + get + { + if (valueCache == null) + valueCache = EditorPrefs.GetBool(key, defaultValue); + + return (bool)valueCache; + } + set + { + if (valueCache == value) + return; + + EditorPrefs.SetBool(key, value); + valueCache = value; + Debug.Log("Editor preference updated. key: " + key + ", value: " + value); + } + } + + public void ClearValue() + { + EditorPrefs.DeleteKey(key); + valueCache = null; + } + } + + public class Preferences : EditorWindow + { + [MenuItem("ParrelSync/Preferences", priority = 1)] + private static void InitWindow() + { + Preferences window = (Preferences)EditorWindow.GetWindow(typeof(Preferences)); + window.titleContent = new GUIContent(ClonesManager.ProjectName + " Preferences"); + window.Show(); + } + + /// + /// Disable asset saving in clone editors? + /// + public static BoolPreference AssetModPref = new BoolPreference("ParrelSync_DisableClonesAssetSaving", true); + + /// + /// In addition of checking the existence of UnityLockFile, + /// also check is the is the UnityLockFile being opened. + /// + public static BoolPreference AlsoCheckUnityLockFileStaPref = new BoolPreference("ParrelSync_CheckUnityLockFileOpenStatus", true); + + private void OnGUI() + { + if (ClonesManager.IsClone()) + { + EditorGUILayout.HelpBox( + "This is a clone project. Please use the original project editor to change preferences.", + MessageType.Info); + return; + } + + GUILayout.BeginVertical("HelpBox"); + GUILayout.Label("Preferences"); + GUILayout.BeginVertical("GroupBox"); + + AssetModPref.Value = EditorGUILayout.ToggleLeft( + new GUIContent( + "(recommended) Disable asset saving in clone editors- require re-open clone editors", + "Disable asset saving in clone editors so all assets can only be modified from the original project editor" + ), + AssetModPref.Value); + + if (Application.platform == RuntimePlatform.WindowsEditor) + { + AlsoCheckUnityLockFileStaPref.Value = EditorGUILayout.ToggleLeft( + new GUIContent( + "Also check UnityLockFile lock status while checking clone projects running status", + "Disable this can slightly increase Clones Manager window performance, but will lead to in-correct clone project running status" + + "(the Clones Manager window show the clone project is still running even it's not) if the clone editor crashed" + ), + AlsoCheckUnityLockFileStaPref.Value); + } + GUILayout.EndVertical(); + if (GUILayout.Button("Reset to default")) + { + AssetModPref.ClearValue(); + AlsoCheckUnityLockFileStaPref.ClearValue(); + Debug.Log("Editor preferences cleared"); + } + GUILayout.EndVertical(); + } + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/Preferences.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/Preferences.cs.meta new file mode 100644 index 0000000..0166f9a --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/Preferences.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24641be1c0410a745b529e61b508679f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/Project.cs b/Assets/ParrelSync/ParrelSync/Editor/Project.cs new file mode 100644 index 0000000..7e7c387 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/Project.cs @@ -0,0 +1,112 @@ +using System.Collections.Generic; +using System.Linq; + +namespace ParrelSync +{ + public class Project : System.ICloneable + { + public string name; + public string projectPath; + string rootPath; + public string assetPath; + public string projectSettingsPath; + public string libraryPath; + public string packagesPath; + public string autoBuildPath; + public string localPackages; + + char[] separator = new char[1] { '/' }; + + + /// + /// Default constructor + /// + public Project() + { + + } + + + /// + /// Initialize the project object by parsing its full path returned by Unity into a bunch of individual folder names and paths. + /// + /// + public Project(string path) + { + ParsePath(path); + } + + + /// + /// Create a new object with the same settings + /// + /// + public object Clone() + { + Project newProject = new Project(); + newProject.rootPath = rootPath; + newProject.projectPath = projectPath; + newProject.assetPath = assetPath; + newProject.projectSettingsPath = projectSettingsPath; + newProject.libraryPath = libraryPath; + newProject.name = name; + newProject.separator = separator; + newProject.packagesPath = packagesPath; + newProject.autoBuildPath = autoBuildPath; + newProject.localPackages = localPackages; + + + return newProject; + } + + + /// + /// Update the project object by renaming and reparsing it. Pass in the new name of a project, and it'll update the other member variables to match. + /// + /// + public void updateNewName(string newName) + { + name = newName; + ParsePath(rootPath + "/" + name + "/Assets"); + } + + + /// + /// Debug override so we can quickly print out the project info. + /// + /// + public override string ToString() + { + string printString = name + "\n" + + rootPath + "\n" + + projectPath + "\n" + + assetPath + "\n" + + projectSettingsPath + "\n" + + packagesPath + "\n" + + autoBuildPath + "\n" + + localPackages + "\n" + + libraryPath; + return (printString); + } + + private void ParsePath(string path) + { + //Unity's Application functions return the Assets path in the Editor. + projectPath = path; + + //pop off the last part of the path for the project name, keep the rest for the root path + List pathArray = projectPath.Split(separator).ToList(); + name = pathArray.Last(); + + pathArray.RemoveAt(pathArray.Count() - 1); + rootPath = string.Join(separator[0].ToString(), pathArray.ToArray()); + + assetPath = projectPath + "/Assets"; + projectSettingsPath = projectPath + "/ProjectSettings"; + libraryPath = projectPath + "/Library"; + packagesPath = projectPath + "/Packages"; + autoBuildPath = projectPath + "/AutoBuild"; + localPackages = projectPath + "/LocalPackages"; + } + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/Project.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/Project.cs.meta new file mode 100644 index 0000000..84d9855 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/Project.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec8d3a1577179ef44815739178cf75b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/UpdateChecker.cs b/Assets/ParrelSync/ParrelSync/Editor/UpdateChecker.cs new file mode 100644 index 0000000..85dbf96 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/UpdateChecker.cs @@ -0,0 +1,60 @@ +using System; +using UnityEditor; +using UnityEngine; +namespace ParrelSync.Update +{ + /// + /// A simple update checker + /// + public class UpdateChecker + { + //const string LocalVersionFilePath = "Assets/ParrelSync/VERSION.txt"; + public const string LocalVersion = "1.5.1"; + [MenuItem("ParrelSync/Check for update", priority = 20)] + static void CheckForUpdate() + { + using (System.Net.WebClient client = new System.Net.WebClient()) + { + try + { + //This won't work with UPM packages + //string localVersionText = AssetDatabase.LoadAssetAtPath(LocalVersionFilePath).text; + + string localVersionText = LocalVersion; + Debug.Log("Local version text : " + LocalVersion); + + string latesteVersionText = client.DownloadString(ExternalLinks.RemoteVersionURL); + Debug.Log("latest version text got: " + latesteVersionText); + string messageBody = "Current Version: " + localVersionText +"\n" + +"Latest Version: " + latesteVersionText + "\n"; + var latestVersion = new Version(latesteVersionText); + var localVersion = new Version(localVersionText); + + if (latestVersion > localVersion) + { + Debug.Log("There's a newer version"); + messageBody += "There's a newer version available"; + if(EditorUtility.DisplayDialog("Check for update.", messageBody, "Get latest release", "Close")) + { + Application.OpenURL(ExternalLinks.Releases); + } + } + else + { + Debug.Log("Current version is up-to-date."); + messageBody += "Current version is up-to-date."; + EditorUtility.DisplayDialog("Check for update.", messageBody,"OK"); + } + + } + catch (Exception exp) + { + Debug.LogError("Error with checking update. Exception: " + exp); + EditorUtility.DisplayDialog("Update Error","Error with checking update. \nSee console for more details.", + "OK" + ); + } + } + } + } +} diff --git a/Assets/ParrelSync/ParrelSync/Editor/UpdateChecker.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/UpdateChecker.cs.meta new file mode 100644 index 0000000..8dcd733 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/UpdateChecker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3453b3f1a20ea148b5028f8556a7be5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/Editor/ValidateCopiedFoldersIntegrity.cs b/Assets/ParrelSync/ParrelSync/Editor/ValidateCopiedFoldersIntegrity.cs new file mode 100644 index 0000000..1ee73bc --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/ValidateCopiedFoldersIntegrity.cs @@ -0,0 +1,73 @@ +namespace ParrelSync +{ + using UnityEditor; + using UnityEngine; + using System; + using System.Text; + using System.Security.Cryptography; + using System.IO; + using System.Linq; + + [InitializeOnLoad] + public class ValidateCopiedFoldersIntegrity + { + const string SessionStateKey = "ValidateCopiedFoldersIntegrity_Init"; + /// + /// Called once on editor startup. + /// Validate copied folders integrity in clone project + /// + static ValidateCopiedFoldersIntegrity() + { + if (!SessionState.GetBool(SessionStateKey, false)) + { + SessionState.SetBool(SessionStateKey, true); + if (!ClonesManager.IsClone()) { return; } + + ValidateFolder(ClonesManager.GetCurrentProjectPath(), ClonesManager.GetOriginalProjectPath(), "Packages"); + } + } + + public static void ValidateFolder(string targetRoot, string originalRoot, string folderName) + { + var targetFolderPath = Path.Combine(targetRoot, folderName); + var targetFolderHash = CreateMd5ForFolder(targetFolderPath); + + var originalFolderPath = Path.Combine(originalRoot, folderName); + var originalFolderHash = CreateMd5ForFolder(originalFolderPath); + + if (targetFolderHash != originalFolderHash) + { + Debug.Log("ParrelSync: Detected changes in '" + folderName + "' directory. Updating cloned project..."); + FileUtil.ReplaceDirectory(originalFolderPath, targetFolderPath); + } + } + + static string CreateMd5ForFolder(string path) + { + // assuming you want to include nested folders + var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories) + .OrderBy(p => p).ToList(); + + MD5 md5 = MD5.Create(); + + for (int i = 0; i < files.Count; i++) + { + string file = files[i]; + + // hash path + string relativePath = file.Substring(path.Length + 1); + byte[] pathBytes = Encoding.UTF8.GetBytes(relativePath.ToLower()); + md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0); + + // hash contents + byte[] contentBytes = File.ReadAllBytes(file); + if (i == files.Count - 1) + md5.TransformFinalBlock(contentBytes, 0, contentBytes.Length); + else + md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0); + } + + return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower(); + } + } +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/Editor/ValidateCopiedFoldersIntegrity.cs.meta b/Assets/ParrelSync/ParrelSync/Editor/ValidateCopiedFoldersIntegrity.cs.meta new file mode 100644 index 0000000..daab522 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/Editor/ValidateCopiedFoldersIntegrity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d8fb344b9abf5274abd744833474b087 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/package.json b/Assets/ParrelSync/ParrelSync/package.json new file mode 100644 index 0000000..29776fb --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/package.json @@ -0,0 +1,10 @@ +{ + "name": "com.veriorpies.parrelsync", + "displayName": "ParrelSync", + "version": "1.5.1", + "unity": "2018.4", + "description": "ParrelSync is a Unity editor extension that allows users to test multiplayer gameplay without building the project by having another Unity editor window opened and mirror the changes from the original project.", + "license": "MIT", + "keywords": [ "Networking", "Utils", "Editor", "Extensions" ], + "dependencies": {} +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/package.json.meta b/Assets/ParrelSync/ParrelSync/package.json.meta new file mode 100644 index 0000000..4ced740 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a2a889c264e34b47a7349cbcb2cbedd7 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/ParrelSync/projectCloner.asmdef b/Assets/ParrelSync/ParrelSync/projectCloner.asmdef new file mode 100644 index 0000000..1e56b06 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/projectCloner.asmdef @@ -0,0 +1,15 @@ +{ + "name": "ParrelSync", + "references": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/ParrelSync/ParrelSync/projectCloner.asmdef.meta b/Assets/ParrelSync/ParrelSync/projectCloner.asmdef.meta new file mode 100644 index 0000000..3aa8857 --- /dev/null +++ b/Assets/ParrelSync/ParrelSync/projectCloner.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 894a6cc6ed5cd2645bb542978cbed6a9 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/README.md b/Assets/ParrelSync/README.md new file mode 100644 index 0000000..18ec606 --- /dev/null +++ b/Assets/ParrelSync/README.md @@ -0,0 +1,91 @@ +# ParrelSync +[![Release](https://img.shields.io/github/v/release/VeriorPies/ParrelSync?include_prereleases)](https://github.com/VeriorPies/ParrelSync/releases) [![Documentation](https://img.shields.io/badge/documentation-brightgreen.svg)](https://github.com/VeriorPies/ParrelSync/wiki) [![License](https://img.shields.io/badge/license-MIT-green)](https://github.com/VeriorPies/ParrelSync/blob/master/LICENSE.md) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-blue.svg)](https://github.com/VeriorPies/ParrelSync/pulls) [![Chats](https://img.shields.io/discord/710688100996743200)](https://discord.gg/TmQk2qG) + +ParrelSync is a Unity editor extension that allows users to test multiplayer gameplay without building the project by having another Unity editor window opened and mirror the changes from the original project. + +
+ +![ShortGif](https://raw.githubusercontent.com/VeriorPies/ParrelSync/master/Images/Showcase%201.gif) +

+Test project changes on clients and server within seconds - both in editor + +
+

+ +## Features +1. Test multiplayer gameplay without building the project +2. GUI tools for managing all project clones +3. Protected assets from being modified by other clone instances +4. Handy APIs to speed up testing workflows +## Installation + +1. Backup your project folder or use a version control system such as [Git](https://git-scm.com/) or [SVN](https://subversion.apache.org/) +2. Download .unitypackage from the [latest release](https://github.com/VeriorPies/ParrelSync/releases) and import it to your project. +3. ParrelSync should appreared in the menu item bar after imported +![UpdateButtonInMenu](https://github.com/VeriorPies/ParrelSync/raw/master/Images/AfterImported.png) + +Check out the [Installation-and-Update](https://github.com/VeriorPies/ParrelSync/wiki/Installation-and-Update) page for more details. + +### UPM Package +ParrelSync can also be installed via UPM package. +After Unity 2019.3.4f1, Unity 2020.1a21, which support path query parameter of git package. You can install ParrelSync by adding the following to Package Manager. + +``` +https://github.com/VeriorPies/ParrelSync.git?path=/ParrelSync +``` + + +![UPM_Image](https://github.com/VeriorPies/ParrelSync/raw/master/Images/UPM_1.png?raw=true) ![UPM_Image2](https://github.com/VeriorPies/ParrelSync/raw/master/Images/UPM_2.png?raw=true) + +or by adding + +``` +"com.veriorpies.parrelsync": "https://github.com/VeriorPies/ParrelSync.git?path=/ParrelSync" +``` + +to the `Packages/manifest.json` file + + +## Supported Platform +Currently, ParrelSync supports Windows, macOS and Linux editors. + +ParrelSync has been tested with the following Unity version. However, it should also work with other versions as well. +* *2020.3.1f1* +* *2019.3.0f6* +* *2018.4.22f1* + + +## APIs +There's some useful APIs for speeding up the multiplayer testing workflow. +Here's a basic example: +``` +if (ClonesManager.IsClone()) { + // Automatically connect to local host if this is the clone editor +}else{ + // Automatically start server if this is the original editor +} +``` +Check out [the doc](https://github.com/VeriorPies/ParrelSync/wiki/List-of-APIs) to view the complete API list. + +## How does it work? +For each clone instance, ParrelSync will make a copy of the original project folder and reference the ```Asset```, ```Packages``` and ```ProjectSettings``` folder back to the original project with [symbolic link](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/mklink). Other folders such as ```Library```, ```Temp```, and ```obj``` will remain independent for each clone project. + +All clones are placed right next to the original project with suffix *```_clone_x```*, which will be something like this in the folder hierarchy. +``` +/ProjectName +/ProjectName_clone_0 +/ProjectName_clone_1 +... +``` +## Discord Server +We have a [Discord server](https://discord.gg/TmQk2qG). + +## Need Help? +Some common questions and troubleshooting can be found under the [Troubleshooting & FAQs](https://github.com/VeriorPies/ParrelSync/wiki/Troubleshooting-&-FAQs) page. +You can also [create a question post](https://github.com/VeriorPies/ParrelSync/issues/new/choose), or ask on [Discord](https://discord.gg/TmQk2qG) if you prefer to have a real-time conversation. + +## Support this project +A star will be appreciated :) + +## Credits +This project is originated from hwaet's [UnityProjectCloner](https://github.com/hwaet/UnityProjectCloner) diff --git a/Assets/ParrelSync/README.md.meta b/Assets/ParrelSync/README.md.meta new file mode 100644 index 0000000..5bc8ca5 --- /dev/null +++ b/Assets/ParrelSync/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fa3f2fa6aced9b54b970c8996957df3b +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ParrelSync/VERSION.txt b/Assets/ParrelSync/VERSION.txt new file mode 100644 index 0000000..8e03717 --- /dev/null +++ b/Assets/ParrelSync/VERSION.txt @@ -0,0 +1 @@ +1.5.1 \ No newline at end of file diff --git a/Assets/ParrelSync/VERSION.txt.meta b/Assets/ParrelSync/VERSION.txt.meta new file mode 100644 index 0000000..52f8b6b --- /dev/null +++ b/Assets/ParrelSync/VERSION.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9833b240625d4e14995c296b87e34b96 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs.meta b/Assets/Prefabs.meta new file mode 100644 index 0000000..42c4b8e --- /dev/null +++ b/Assets/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2146d4c2bef1eee4887b41b5fef0ea19 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Lobby_PlayerMesh.prefab b/Assets/Prefabs/Lobby_PlayerMesh.prefab new file mode 100644 index 0000000..e265ae7 --- /dev/null +++ b/Assets/Prefabs/Lobby_PlayerMesh.prefab @@ -0,0 +1,131 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &268687697814956617 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5961685106953509118} + - component: {fileID: 7047780453335258601} + - component: {fileID: 8375182496356266698} + - component: {fileID: -4523946980089260949} + m_Layer: 0 + m_Name: Lobby_PlayerMesh + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5961685106953509118 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 268687697814956617} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 5502079341116129236} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &7047780453335258601 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 268687697814956617} + m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8375182496356266698 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 268687697814956617} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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 &-4523946980089260949 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 268687697814956617} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b27e9af7236205e4cb5c6aceca60c9a7, type: 3} + m_Name: + m_EditorClassIdentifier: + nametagPos: {fileID: 5502079341116129236} +--- !u!1 &1558986086654912480 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5502079341116129236} + m_Layer: 0 + m_Name: namtag_pos + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5502079341116129236 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1558986086654912480} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1.24, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5961685106953509118} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Prefabs/Lobby_PlayerMesh.prefab.meta b/Assets/Prefabs/Lobby_PlayerMesh.prefab.meta new file mode 100644 index 0000000..d743ce9 --- /dev/null +++ b/Assets/Prefabs/Lobby_PlayerMesh.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 53f9b17a77863de4294a4588ac92219e +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Player.prefab b/Assets/Prefabs/Player.prefab new file mode 100644 index 0000000..ba95631 --- /dev/null +++ b/Assets/Prefabs/Player.prefab @@ -0,0 +1,482 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &213412464678433787 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1142460997963465055} + - component: {fileID: 3643573506939251918} + - component: {fileID: 797422653874731177} + m_Layer: 0 + m_Name: Capsule + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1142460997963465055 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 213412464678433787} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2045213762160769814} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &3643573506939251918 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 213412464678433787} + m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &797422653874731177 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 213412464678433787} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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!1 &709993642344972423 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8153937580464344507} + m_Layer: 0 + m_Name: CameraHolder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8153937580464344507 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 709993642344972423} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1.6, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8060763933786335874} + m_Father: {fileID: 8622478986360528058} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &902180511398826461 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2045213762160769814} + m_Layer: 0 + m_Name: Mesh + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2045213762160769814 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 902180511398826461} + 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: 1142460997963465055} + m_Father: {fileID: 8622478986360528058} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &3139356448881828875 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6524190671148023887} + - component: {fileID: 7665465332328192992} + - component: {fileID: -4927202924902917292} + - component: {fileID: 7377670043996277089} + - component: {fileID: 4841028295872287541} + m_Layer: 0 + m_Name: Player + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6524190671148023887 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3139356448881828875} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.697, y: -0.162, z: 2.709} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8622478986360528058} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &7665465332328192992 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3139356448881828875} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3} + m_Name: + m_EditorClassIdentifier: + sceneId: 0 + _assetId: 3385617076 + serverOnly: 0 + visibility: 0 + hasSpawned: 0 +--- !u!143 &-4927202924902917292 +CharacterController: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3139356448881828875} + 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_Height: 2 + m_Radius: 0.5 + m_SlopeLimit: 45 + m_StepOffset: 0.3 + m_SkinWidth: 0.08 + m_MinMoveDistance: 0.001 + m_Center: {x: 0, y: 0, z: 0} +--- !u!114 &7377670043996277089 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3139356448881828875} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4c4b5dc7895a402408126e4e9a847dd6, type: 3} + m_Name: + m_EditorClassIdentifier: + syncDirection: 0 + syncMode: 0 + syncInterval: 0 + playerInfo: + username: + steamId: 0 + IsReady: 0 + controllerObj: {fileID: 5520587450603064363} + meshObj: {fileID: 902180511398826461} + camHolder: {fileID: 709993642344972423} + controllerComponents: + - {fileID: 4841028295872287541} +--- !u!114 &4841028295872287541 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3139356448881828875} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1345dc4c8b97453448fc9e22f2205527, type: 3} + m_Name: + m_EditorClassIdentifier: + syncDirection: 0 + syncMode: 0 + syncInterval: 0 + walkingSpeed: 7.5 + runningSpeed: 11.5 + jumpHeight: 8 + gravity: 20 + playerCamera: {fileID: 7853375424490858487} + groundMask: + serializedVersion: 2 + m_Bits: 1 + groundedCheck: {fileID: 4052873746696461485} + groundedDistance: 0.3 + camHolder: {fileID: 8153937580464344507} + lookSpeed: 2 + lookXLimit: 885 +--- !u!1 &5520587450603064363 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8622478986360528058} + m_Layer: 0 + m_Name: Controller + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &8622478986360528058 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5520587450603064363} + 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: 8153937580464344507} + - {fileID: 2045213762160769814} + - {fileID: 4052873746696461485} + m_Father: {fileID: 6524190671148023887} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8267927316272890771 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4052873746696461485} + m_Layer: 0 + m_Name: GroundCheck + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4052873746696461485 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8267927316272890771} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.211, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8622478986360528058} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8570964176092585696 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8060763933786335874} + - component: {fileID: 7853375424490858487} + - component: {fileID: 8313991119025768267} + - component: {fileID: 1865695375216555035} + m_Layer: 0 + m_Name: Camera + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8060763933786335874 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8570964176092585696} + 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: 8153937580464344507} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &7853375424490858487 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8570964176092585696} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 90 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &8313991119025768267 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8570964176092585696} + m_Enabled: 1 +--- !u!114 &1865695375216555035 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8570964176092585696} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + quality: 3 + frameInfluence: 0.1 + jitterScale: 1 + mipBias: 0 + varianceClampScale: 0.9 + contrastAdaptiveSharpening: 0 diff --git a/Assets/Prefabs/Player.prefab.meta b/Assets/Prefabs/Player.prefab.meta new file mode 100644 index 0000000..9c902dd --- /dev/null +++ b/Assets/Prefabs/Player.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5ded421dd04e00040ae1324ded1917d9 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/UI.meta b/Assets/Prefabs/UI.meta new file mode 100644 index 0000000..5f8a1e4 --- /dev/null +++ b/Assets/Prefabs/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 64931231b6641224e80cd19c342ec6c6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/UI/Buttom_Element.prefab b/Assets/Prefabs/UI/Buttom_Element.prefab new file mode 100644 index 0000000..cfd2c86 --- /dev/null +++ b/Assets/Prefabs/UI/Buttom_Element.prefab @@ -0,0 +1,333 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3525742193764371438 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6472670963702568390} + - component: {fileID: 8959420264127861981} + - component: {fileID: 1841577163924007550} + m_Layer: 5 + m_Name: Sidebar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6472670963702568390 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3525742193764371438} + 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: 4060705358705524266} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 4.9054, y: 0} + m_SizeDelta: {x: 9.8107, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8959420264127861981 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3525742193764371438} + m_CullTransparentMesh: 1 +--- !u!114 &1841577163924007550 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3525742193764371438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &4757903881983467744 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7859886673612682557} + - component: {fileID: 4197065212714437525} + - component: {fileID: 2086726451323268952} + m_Layer: 5 + m_Name: Title_Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7859886673612682557 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4757903881983467744} + 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: 4060705358705524266} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 19.2117, y: 0} + m_SizeDelta: {x: -38.4235, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4197065212714437525 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4757903881983467744} + m_CullTransparentMesh: 1 +--- !u!114 &2086726451323268952 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4757903881983467744} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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: SINGLEPLAYER + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 40 + m_fontSizeBase: 40 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 0 + m_fontSizeMax: 0 + m_fontStyle: 17 + 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: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &6668870933609579488 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4060705358705524266} + - component: {fileID: 7181096425323223984} + - component: {fileID: 3868939535138574128} + - component: {fileID: 1830634547527162540} + m_Layer: 5 + m_Name: Buttom_Element + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4060705358705524266 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6668870933609579488} + 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: 7859886673612682557} + - {fileID: 6472670963702568390} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 600, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7181096425323223984 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6668870933609579488} + m_CullTransparentMesh: 1 +--- !u!114 &3868939535138574128 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6668870933609579488} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &1830634547527162540 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6668870933609579488} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0, g: 0, b: 0, a: 0.7019608} + m_HighlightedColor: {r: 0.59607846, g: 0.41568628, b: 0.25490198, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0, g: 0, b: 0, a: 0.7019608} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 3868939535138574128} + m_OnClick: + m_PersistentCalls: + m_Calls: [] diff --git a/Assets/Prefabs/UI/Buttom_Element.prefab.meta b/Assets/Prefabs/UI/Buttom_Element.prefab.meta new file mode 100644 index 0000000..f4e77a7 --- /dev/null +++ b/Assets/Prefabs/UI/Buttom_Element.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 346d6982b88c8cd42bb414912972cfaa +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/UI/Friend_Element.prefab b/Assets/Prefabs/UI/Friend_Element.prefab new file mode 100644 index 0000000..655496a --- /dev/null +++ b/Assets/Prefabs/UI/Friend_Element.prefab @@ -0,0 +1,361 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &868074393274563534 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6075690294995065130} + - component: {fileID: 7687715583933576772} + - component: {fileID: 9157386037182494100} + - component: {fileID: 5890214456607459570} + - component: {fileID: 411603505650460573} + m_Layer: 5 + m_Name: Friend_Element + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6075690294995065130 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 868074393274563534} + 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: 7579313597881734784} + - {fileID: 1477542367598077300} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 125} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7687715583933576772 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 868074393274563534} + m_CullTransparentMesh: 1 +--- !u!114 &9157386037182494100 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 868074393274563534} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &5890214456607459570 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 868074393274563534} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 39424224dc4222c4a803fa7e76838603, type: 3} + m_Name: + m_EditorClassIdentifier: + _iconImage: {fileID: 1879919663617341578} + _statusImage: {fileID: 0} + _usernameText: {fileID: 7630029040620516886} +--- !u!114 &411603505650460573 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 868074393274563534} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0, g: 0, b: 0, a: 0.3882353} + m_HighlightedColor: {r: 0.1981132, g: 0.1981132, b: 0.1981132, a: 0.6666667} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0, g: 0, b: 0, a: 0.3882353} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 9157386037182494100} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 5890214456607459570} + m_TargetAssemblyTypeName: FriendItem, Assembly-CSharp + m_MethodName: InviteFriend + 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 +--- !u!1 &2276251388514561626 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1477542367598077300} + - component: {fileID: 5804804057613663868} + - component: {fileID: 1879919663617341578} + m_Layer: 5 + m_Name: Image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1477542367598077300 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2276251388514561626} + m_LocalRotation: {x: -0, y: -0, z: -1, w: -0.00000035762784} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 6075690294995065130} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: -180} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 62.5, y: 0} + m_SizeDelta: {x: 125, y: 125} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5804804057613663868 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2276251388514561626} + m_CullTransparentMesh: 1 +--- !u!114 &1879919663617341578 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2276251388514561626} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &7143819254998492902 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7579313597881734784} + - component: {fileID: 1141131211529272064} + - component: {fileID: 7630029040620516886} + m_Layer: 5 + m_Name: username + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7579313597881734784 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7143819254998492902} + 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: 6075690294995065130} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 62.5, y: 0} + m_SizeDelta: {x: -125, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1141131211529272064 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7143819254998492902} + m_CullTransparentMesh: 1 +--- !u!114 &7630029040620516886 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7143819254998492902} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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: USERNAME + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 70 + m_fontSizeBase: 74.83 + m_fontWeight: 400 + m_enableAutoSizing: 1 + m_fontSizeMin: 18 + m_fontSizeMax: 70 + 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: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} diff --git a/Assets/Prefabs/UI/Friend_Element.prefab.meta b/Assets/Prefabs/UI/Friend_Element.prefab.meta new file mode 100644 index 0000000..d4ce05c --- /dev/null +++ b/Assets/Prefabs/UI/Friend_Element.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ed41cb43487d1944c8a4a1207f3fe173 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources.meta b/Assets/Resources.meta new file mode 100644 index 0000000..8fe249a --- /dev/null +++ b/Assets/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8e6fbdb7739fae54db56898efdef1a4f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Markers.meta b/Assets/Resources/Markers.meta new file mode 100644 index 0000000..2cb3b52 --- /dev/null +++ b/Assets/Resources/Markers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9ff4f19917c4956488263c7ae8139b55 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Markers/Nametag_Marker.asset b/Assets/Resources/Markers/Nametag_Marker.asset new file mode 100644 index 0000000..6c2a38c --- /dev/null +++ b/Assets/Resources/Markers/Nametag_Marker.asset @@ -0,0 +1,23 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 35a98cf24352f1f4d99d7a33c0b4d1e0, type: 3} + m_Name: Nametag_Marker + m_EditorClassIdentifier: + id: 0 + markerLocalObj: {fileID: 3472063188260564299, guid: d2b18e33b98b06f489aaa75955227efc, + type: 3} + markerWorldObj: {fileID: 0} + lifeDuration: 0 + unlimitedLife: 1 + minFadeAmount: 0 + fadeByDotProduct: 0 + fadeByAim: 0 diff --git a/Assets/Resources/Markers/Nametag_Marker.asset.meta b/Assets/Resources/Markers/Nametag_Marker.asset.meta new file mode 100644 index 0000000..2964d40 --- /dev/null +++ b/Assets/Resources/Markers/Nametag_Marker.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e317482851e1cd6418a579729c6c209f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Markers/Party_Nametag.prefab b/Assets/Resources/Markers/Party_Nametag.prefab new file mode 100644 index 0000000..5c80b21 --- /dev/null +++ b/Assets/Resources/Markers/Party_Nametag.prefab @@ -0,0 +1,553 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &110800288667802246 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7366305830974906220} + - component: {fileID: 3945997673843071374} + - component: {fileID: 8385899542627404907} + m_Layer: 5 + m_Name: ready_image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7366305830974906220 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 110800288667802246} + 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: 8760400328363394836} + 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: 20.900024, y: 90.4} + m_SizeDelta: {x: 23.84, y: 14.6} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3945997673843071374 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 110800288667802246} + m_CullTransparentMesh: 1 +--- !u!114 &8385899542627404907 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 110800288667802246} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0, b: 0, 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_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &2232980809971329370 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6969969062343849306} + - component: {fileID: 9213508317649506919} + - component: {fileID: 6556378692167425230} + m_Layer: 5 + m_Name: ready_text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6969969062343849306 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2232980809971329370} + 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: 8760400328363394836} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 20.9, y: 59.8177} + m_SizeDelta: {x: -120.1955, y: -26.3645} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &9213508317649506919 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2232980809971329370} + m_CullTransparentMesh: 1 +--- !u!114 &6556378692167425230 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2232980809971329370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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: NOT READY + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 25.7 + m_fontSizeBase: 25.7 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 66 + m_fontStyle: 16 + 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: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &3472063188260564299 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8760400328363394836} + - component: {fileID: 8319268938656606210} + m_Layer: 5 + m_Name: Party_Nametag + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8760400328363394836 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3472063188260564299} + 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: 222093856708298302} + - {fileID: 8278123848985926762} + - {fileID: 7366305830974906220} + - {fileID: 6969969062343849306} + m_Father: {fileID: 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: 119, y: 424} + m_SizeDelta: {x: 400, y: 70} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &8319268938656606210 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3472063188260564299} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 79b83d359693de5458001ffa4e86801e, type: 3} + m_Name: + m_EditorClassIdentifier: + markerDefinition: {fileID: 11400000, guid: e317482851e1cd6418a579729c6c209f, type: 2} + username_text: {fileID: 7051736273625582493} + ready_text: {fileID: 6556378692167425230} + ready_image: {fileID: 8385899542627404907} + pfp_Image: {fileID: 7164568316738688523} +--- !u!1 &4292589593336520016 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8278123848985926762} + - component: {fileID: 2917851553234281669} + - component: {fileID: 7164568316738688523} + m_Layer: 5 + m_Name: pfp + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8278123848985926762 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4292589593336520016} + m_LocalRotation: {x: -1, y: -0, z: 0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8760400328363394836} + m_LocalEulerAnglesHint: {x: 0, y: -180, z: 180} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 49, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2917851553234281669 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4292589593336520016} + m_CullTransparentMesh: 1 +--- !u!114 &7164568316738688523 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4292589593336520016} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &6327201661557887652 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 222093856708298302} + - component: {fileID: 4173320101907203950} + - component: {fileID: 3159902090424032646} + m_Layer: 5 + m_Name: bg + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &222093856708298302 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6327201661557887652} + 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: 7444820724150182208} + m_Father: {fileID: 8760400328363394836} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4173320101907203950 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6327201661557887652} + m_CullTransparentMesh: 1 +--- !u!114 &3159902090424032646 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6327201661557887652} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 0.72156864} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &8457395752180701970 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7444820724150182208} + - component: {fileID: 1660540433952427266} + - component: {fileID: 7051736273625582493} + m_Layer: 5 + m_Name: name_text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7444820724150182208 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8457395752180701970} + 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: 222093856708298302} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 51.7791, y: 0} + m_SizeDelta: {x: -120.1955, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1660540433952427266 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8457395752180701970} + m_CullTransparentMesh: 1 +--- !u!114 &7051736273625582493 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8457395752180701970} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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: username + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 45.6 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 1 + m_fontSizeMin: 18 + m_fontSizeMax: 66 + m_fontStyle: 17 + 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: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} diff --git a/Assets/Resources/Markers/Party_Nametag.prefab.meta b/Assets/Resources/Markers/Party_Nametag.prefab.meta new file mode 100644 index 0000000..f766d4c --- /dev/null +++ b/Assets/Resources/Markers/Party_Nametag.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d2b18e33b98b06f489aaa75955227efc +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes.meta b/Assets/Scenes.meta new file mode 100644 index 0000000..f8d032e --- /dev/null +++ b/Assets/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b79f48a9a660f8b49ba58ce40bf97bba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/MainMenu.unity b/Assets/Scenes/MainMenu.unity new file mode 100644 index 0000000..2efb6f1 --- /dev/null +++ b/Assets/Scenes/MainMenu.unity @@ -0,0 +1,4753 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1001 &6244710 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1368295248} + m_Modifications: + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 175947125} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: StartSinglePlayer + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: MainMenu, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6668870933609579488, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Name + value: Singeplayer_Buttom_Element + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 346d6982b88c8cd42bb414912972cfaa, type: 3} +--- !u!224 &6244711 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 6244710} + m_PrefabAsset: {fileID: 0} +--- !u!1 &40274433 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 40274434} + - component: {fileID: 40274436} + - component: {fileID: 40274435} + m_Layer: 5 + m_Name: Title + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &40274434 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 40274433} + 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: 1824664576} + 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: 792} + m_SizeDelta: {x: 794.4, y: 194.3} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &40274435 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 40274433} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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: INVITE A FRIEND + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 47.26 + m_fontSizeBase: 47.26 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 1 + 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_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 00000000 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &40274436 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 40274433} + m_CullTransparentMesh: 1 +--- !u!1 &95399539 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 95399542} + - component: {fileID: 95399541} + - component: {fileID: 95399543} + - component: {fileID: 95399544} + - component: {fileID: 95399545} + m_Layer: 0 + m_Name: NetworkManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &95399541 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 95399539} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 123bbac7f620cae42b421b72cf58d0bd, type: 3} + m_Name: + m_EditorClassIdentifier: + dontDestroyOnLoad: 1 + runInBackground: 1 + headlessStartMode: 1 + editorAutoStart: 0 + sendRate: 60 + autoStartServerBuild: 0 + autoConnectClientBuild: 0 + offlineScene: Assets/Scenes/MainMenu.unity + onlineScene: + transport: {fileID: 95399543} + networkAddress: localhost + maxConnections: 4 + disconnectInactiveConnections: 0 + disconnectInactiveTimeout: 60 + authenticator: {fileID: 0} + playerPrefab: {fileID: 3139356448881828875, guid: 5ded421dd04e00040ae1324ded1917d9, + type: 3} + autoCreatePlayer: 1 + playerSpawnMethod: 1 + spawnPrefabs: [] + exceptionsDisconnect: 0 + snapshotSettings: + bufferTimeMultiplier: 2 + bufferLimit: 32 + catchupNegativeThreshold: -1 + catchupPositiveThreshold: 1 + catchupSpeed: 0.019999999552965164 + slowdownSpeed: 0.03999999910593033 + driftEmaDuration: 1 + dynamicAdjustment: 1 + dynamicAdjustmentTolerance: 1 + deliveryTimeEmaDuration: 2 + evaluationMethod: 0 + evaluationInterval: 3 + timeInterpolationGui: 0 + allClients: [] +--- !u!4 &95399542 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 95399539} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 52.369995, y: 194.375, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &95399543 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 95399539} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e6e55fca1f4e4844593a3dd65a3ecb39, type: 3} + m_Name: + m_EditorClassIdentifier: + Channels: 0200000001000000 + Timeout: 25 + AllowSteamRelay: 1 + UseNextGenSteamNetworking: 1 +--- !u!114 &95399544 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 95399539} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 74a3fc7eda8dd2747bbcb9546db2aee3, type: 3} + m_Name: + m_EditorClassIdentifier: + allLobbies: [] +--- !u!114 &95399545 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 95399539} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9ba7df8027f02f94c92f43d9d02d5b7c, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &117194702 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 117194703} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &117194703 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 117194702} + 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: 393397516} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &175947120 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 175947124} + - component: {fileID: 175947123} + - component: {fileID: 175947122} + - component: {fileID: 175947121} + - component: {fileID: 175947125} + m_Layer: 5 + m_Name: MainMenu_Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &175947121 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 175947120} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &175947122 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 175947120} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 3840, y: 2160} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0.5 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &175947123 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 175947120} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &175947124 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 175947120} + 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: + - {fileID: 979820852} + - {fileID: 727777085} + - {fileID: 728542851} + - {fileID: 592730441} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &175947125 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 175947120} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 284b6fd5c3191dc4fac424b5f10dfa81, type: 3} + m_Name: + m_EditorClassIdentifier: + state: 0 + homeUI: {fileID: 979820851} + partyUI: {fileID: 727777084} + readyButton_Image: {fileID: 595332848} + readyButton_Text: {fileID: 568551892} + readyColor: {r: 0.20091248, g: 1, b: 0, a: 1} + notReadyColor: {r: 1, g: 0.019607844, b: 0, a: 1} +--- !u!1 &330585543 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 330585546} + - component: {fileID: 330585545} + - component: {fileID: 330585544} + - component: {fileID: 330585547} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &330585544 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 330585543} + m_Enabled: 1 +--- !u!20 &330585545 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 330585543} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0, g: 0, b: 0, a: 1} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &330585546 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 330585543} + serializedVersion: 2 + m_LocalRotation: {x: 0.038780626, y: -0, z: -0, w: 0.99924785} + m_LocalPosition: {x: 0.47, y: 1.55, z: -0.78} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 4.445, y: 0, z: 0} +--- !u!114 &330585547 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 330585543} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 1 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 +--- !u!1001 &339571624 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1368295248} + m_Modifications: + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 175947125} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: FindMatch + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: MainMenu, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_text + value: FIND MATCH + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6668870933609579488, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Name + value: FindMatch_Buttom_Element + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 346d6982b88c8cd42bb414912972cfaa, type: 3} +--- !u!224 &339571625 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 339571624} + m_PrefabAsset: {fileID: 0} +--- !u!1 &375604164 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 375604165} + - component: {fileID: 375604168} + - component: {fileID: 375604167} + - component: {fileID: 375604166} + m_Layer: 5 + m_Name: Viewport + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &375604165 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 375604164} + 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: 937080729} + m_Father: {fileID: 1824664576} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -17, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &375604166 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 375604164} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 0 +--- !u!114 &375604167 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 375604164} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10917, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &375604168 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 375604164} + m_CullTransparentMesh: 1 +--- !u!1 &393397515 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 393397516} + - component: {fileID: 393397519} + - component: {fileID: 393397518} + - component: {fileID: 393397517} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &393397516 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393397515} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.9996778, z: -0, w: 0.025385052} + m_LocalPosition: {x: -0.3722986, y: 0.50841004, z: 0.4547567} + m_LocalScale: {x: 0.5325624, y: 1.804699, z: 0.53133565} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 117194703} + m_Father: {fileID: 1019480629} + m_LocalEulerAnglesHint: {x: 0, y: -35.153, z: 0} +--- !u!65 &393397517 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393397515} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &393397518 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393397515} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &393397519 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393397515} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &408054733 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 408054734} + - component: {fileID: 408054735} + m_Layer: 0 + m_Name: StartPosition + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &408054734 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 408054733} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.697, y: -0.162, z: 2.709} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &408054735 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 408054733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &410087039 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 410087041} + - component: {fileID: 410087040} + - component: {fileID: 410087042} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &410087040 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410087039} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 1 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 2 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 5000 + m_UseColorTemperature: 1 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &410087041 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410087039} + serializedVersion: 2 + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!114 &410087042 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410087039} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 1 +--- !u!114 &568551892 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 958053463} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &592730439 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 592730441} + - component: {fileID: 592730440} + m_Layer: 0 + m_Name: PopupManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &592730440 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 592730439} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 379041cc65f409e41b6ab54e09095c0f, type: 3} + m_Name: + m_EditorClassIdentifier: + text_title: {fileID: 1096692136} + popUp: {fileID: 1357199462} +--- !u!224 &592730441 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 592730439} + 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: 1357199463} + m_Father: {fileID: 175947124} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &595332848 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 1841577163924007550, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 958053463} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &615982979 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 615982980} + m_Layer: 0 + m_Name: Map + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &615982980 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 615982979} + 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: 408054734} + - {fileID: 1147238474} + - {fileID: 2125853218} + - {fileID: 1447145128} + - {fileID: 1541976207} + - {fileID: 828025626} + - {fileID: 1019480629} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &727777084 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 727777085} + m_Layer: 5 + m_Name: Party_Screen + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &727777085 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727777084} + 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: 958053464} + - {fileID: 2119601174} + - {fileID: 1824664576} + m_Father: {fileID: 175947124} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &728542850 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 728542851} + m_Layer: 5 + m_Name: CharacterUI + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &728542851 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 728542850} + 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: 175947124} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1001 &760984675 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1368295248} + m_Modifications: + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 175947125} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: CreateParty + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: MainMenu, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_text + value: CREATE A PARTY + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6668870933609579488, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Name + value: CreateParty_Buttom_Element + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 346d6982b88c8cd42bb414912972cfaa, type: 3} +--- !u!224 &760984676 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 760984675} + m_PrefabAsset: {fileID: 0} +--- !u!1 &828025625 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 828025626} + m_Layer: 0 + m_Name: Rock + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &828025626 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 828025625} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0.9606732, z: -0, w: -0.27768135} + m_LocalPosition: {x: 2.96, y: 0.63, z: 9.61} + m_LocalScale: {x: 2.3724446, y: 1.6915479, z: 1.5371715} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1070089436} + - {fileID: 1849245962} + - {fileID: 1517980880} + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &832575517 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 832575519} + - component: {fileID: 832575518} + m_Layer: 0 + m_Name: Global Volume + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &832575518 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 832575517} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IsGlobal: 1 + priority: 0 + blendDistance: 0 + weight: 1 + sharedProfile: {fileID: 11400000, guid: a6560a915ef98420e9faacc1c7438823, type: 2} +--- !u!4 &832575519 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 832575517} + 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: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &909289947 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 909289948} + - component: {fileID: 909289950} + - component: {fileID: 909289949} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &909289948 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 909289947} + 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: 1819503696} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &909289949 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 909289947} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.2735849, g: 0.2735849, b: 0.2735849, 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_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &909289950 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 909289947} + m_CullTransparentMesh: 1 +--- !u!1 &937080728 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 937080729} + - component: {fileID: 937080731} + - component: {fileID: 937080730} + m_Layer: 5 + m_Name: Content + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &937080729 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 937080728} + 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: 375604165} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0.00019807967} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &937080730 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 937080728} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!114 &937080731 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 937080728} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 10 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 1 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1001 &958053463 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 727777085} + m_Modifications: + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 175947125} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: ToggleReady + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: MainMenu, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 1841577163924007550, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Color.b + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1841577163924007550, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Color.g + value: 0.020420859 + objectReference: {fileID: 0} + - target: {fileID: 1841577163924007550, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Color.r + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_text + value: NOT READY + objectReference: {fileID: 0} + - target: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_HorizontalAlignment + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 107 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6472670963702568390, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6472670963702568390, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6472670963702568390, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6472670963702568390, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6472670963702568390, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 6472670963702568390, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 16.699997 + objectReference: {fileID: 0} + - target: {fileID: 6472670963702568390, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6472670963702568390, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -8.349998 + objectReference: {fileID: 0} + - target: {fileID: 6668870933609579488, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Name + value: Ready_Buttom_Element + objectReference: {fileID: 0} + - target: {fileID: 7859886673612682557, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: -0.00030518 + objectReference: {fileID: 0} + - target: {fileID: 7859886673612682557, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: -16.7 + objectReference: {fileID: 0} + - target: {fileID: 7859886673612682557, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: -0.00024414062 + objectReference: {fileID: 0} + - target: {fileID: 7859886673612682557, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -8.350006 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 346d6982b88c8cd42bb414912972cfaa, type: 3} +--- !u!224 &958053464 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 958053463} + m_PrefabAsset: {fileID: 0} +--- !u!1001 &978189670 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1319193669} + m_Modifications: + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 175947125} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: StartLocalClient + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: MainMenu, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_text + value: START LOCAL CLIENT + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 350.90002 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -374.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6668870933609579488, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Name + value: StartLocalClient_Buttom_Element + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 346d6982b88c8cd42bb414912972cfaa, type: 3} +--- !u!224 &978189671 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 978189670} + m_PrefabAsset: {fileID: 0} +--- !u!1 &979820851 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 979820852} + m_Layer: 5 + m_Name: Home_Screen + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &979820852 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 979820851} + 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: 1368295248} + - {fileID: 1319193669} + m_Father: {fileID: 175947124} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 363.688, y: 233} + m_SizeDelta: {x: 627.375, y: 321.685} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1019480628 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1019480629} + m_Layer: 0 + m_Name: Rock (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1019480629 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1019480628} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.7311311, z: -0, w: -0.682237} + m_LocalPosition: {x: -1.64, y: 0.63, z: 5.06} + m_LocalScale: {x: 2.3724446, y: 1.6915479, z: 1.5371715} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1305261509} + - {fileID: 393397516} + - {fileID: 2046918407} + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: -93.963, z: 0} +--- !u!1001 &1053502563 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 2119601174} + m_Modifications: + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 175947125} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: StartGame + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: MainMenu, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_text + value: START GAME + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 300 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -50 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6668870933609579488, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Name + value: StartGame_Buttom_Element + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 346d6982b88c8cd42bb414912972cfaa, type: 3} +--- !u!224 &1053502564 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 1053502563} + m_PrefabAsset: {fileID: 0} +--- !u!1 &1070089435 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1070089436} + - component: {fileID: 1070089439} + - component: {fileID: 1070089438} + - component: {fileID: 1070089437} + m_Layer: 0 + m_Name: Cube (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1070089436 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1070089435} + 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: 828025626} + m_LocalEulerAnglesHint: {x: 0, y: -212.244, z: 0} +--- !u!65 &1070089437 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1070089435} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1070089438 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1070089435} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &1070089439 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1070089435} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1096692134 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1096692135} + - component: {fileID: 1096692137} + - component: {fileID: 1096692136} + m_Layer: 0 + m_Name: title_text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1096692135 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1096692134} + 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: 1357199463} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: -46, y: 43} + m_SizeDelta: {x: 496.499, y: 88.161} + m_Pivot: {x: 0.5, y: 0} +--- !u!114 &1096692136 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1096692134} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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: CREATING MATCH + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 51 + m_fontSizeBase: 86 + m_fontWeight: 400 + m_enableAutoSizing: 1 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 1 + m_HorizontalAlignment: 4 + 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_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 00000000 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1096692137 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1096692134} + m_CullTransparentMesh: 1 +--- !u!1 &1147238473 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1147238474} + - component: {fileID: 1147238475} + m_Layer: 0 + m_Name: StartPosition (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1147238474 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1147238473} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 1.947, y: -0.162, z: 3.459} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1147238475 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1147238473} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &1200274991 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1200274992} + - component: {fileID: 1200274995} + - component: {fileID: 1200274994} + - component: {fileID: 1200274993} + m_Layer: 5 + m_Name: Scrollbar Vertical + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1200274992 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1200274991} + 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: 1819503696} + m_Father: {fileID: 1824664576} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: -17} + m_Pivot: {x: 1, y: 1} +--- !u!114 &1200274993 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1200274991} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2a4db7a114972834c8e4117be1d82ba3, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 909289949} + m_HandleRect: {fileID: 909289948} + m_Direction: 2 + m_Value: 0 + m_Size: 1 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &1200274994 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1200274991} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6509434, g: 0.6509434, b: 0.6509434, 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_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1200274995 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1200274991} + m_CullTransparentMesh: 1 +--- !u!1 &1305261508 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1305261509} + - component: {fileID: 1305261512} + - component: {fileID: 1305261511} + - component: {fileID: 1305261510} + m_Layer: 0 + m_Name: Cube (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1305261509 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305261508} + 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: 1019480629} + m_LocalEulerAnglesHint: {x: 0, y: -212.244, z: 0} +--- !u!65 &1305261510 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305261508} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1305261511 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305261508} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &1305261512 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305261508} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1319193668 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1319193669} + m_Layer: 5 + m_Name: DevUI + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1319193669 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319193668} + 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: 2111335289} + - {fileID: 978189671} + m_Father: {fileID: 979820852} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 1556.312, y: 847} + m_SizeDelta: {x: 3212.625, y: 1838.315} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1332214901 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1332214904} + - component: {fileID: 1332214903} + - component: {fileID: 1332214902} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1332214902 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1332214901} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1332214903 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1332214901} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1332214904 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1332214901} + 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: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1357199462 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1357199463} + m_Layer: 0 + m_Name: Popup + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1357199463 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1357199462} + 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: 1634709546} + - {fileID: 1096692135} + - {fileID: 1550580365} + m_Father: {fileID: 592730441} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1368295247 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1368295248} + - component: {fileID: 1368295249} + m_Layer: 5 + m_Name: Main_Buttons + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1368295248 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368295247} + 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: 6244711} + - {fileID: 760984676} + - {fileID: 339571625} + m_Father: {fileID: 979820852} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 313.6875, y: 160.84253} + m_SizeDelta: {x: 627.375, y: 321.685} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1368295249 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368295247} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 24.59 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &1402023607 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1402023608} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1402023608 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1402023607} + 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: 2046918407} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1402974729 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1402974731} + - component: {fileID: 1402974730} + m_Layer: 0 + m_Name: MarkerHandler + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1402974730 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1402974729} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5c3fa5eb1f4aef54a91cc6c50111cc9e, type: 3} + m_Name: + m_EditorClassIdentifier: + allMarkerDefinitions: + - {fileID: 11400000, guid: e317482851e1cd6418a579729c6c209f, type: 2} + markerContainer: {fileID: 728542851} +--- !u!4 &1402974731 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1402974729} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 1.2901233, y: 1.2059157, z: 5.845375} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1447145127 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1447145128} + - component: {fileID: 1447145129} + m_Layer: 0 + m_Name: StartPosition (3) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1447145128 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1447145127} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 3.197, y: -0.162, z: 4.709} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1447145129 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1447145127} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &1517980879 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1517980880} + - component: {fileID: 1517980883} + - component: {fileID: 1517980882} + - component: {fileID: 1517980881} + m_Layer: 0 + m_Name: Cube (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1517980880 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517980879} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.86945814, z: -0, w: 0.49400666} + m_LocalPosition: {x: -0.4473228, y: 0, z: 0.9662192} + m_LocalScale: {x: 0.7188414, y: 1.804699, z: 0.37978923} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1537298478} + m_Father: {fileID: 828025626} + m_LocalEulerAnglesHint: {x: 0, y: -91.452, z: 0} +--- !u!65 &1517980881 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517980879} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1517980882 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517980879} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &1517980883 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517980879} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1537298477 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1537298478} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1537298478 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1537298477} + 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: 1517980880} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1541976206 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1541976207} + - component: {fileID: 1541976210} + - component: {fileID: 1541976209} + - component: {fileID: 1541976208} + m_Layer: 0 + m_Name: Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1541976207 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1541976206} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0, z: 7.4443} + m_LocalScale: {x: 2.6819, y: 1, z: 1.5829} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!64 &1541976208 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1541976206} + 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: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1541976209 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1541976206} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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!33 &1541976210 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1541976206} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1550580364 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1550580365} + - component: {fileID: 1550580367} + - component: {fileID: 1550580366} + m_Layer: 0 + m_Name: loading_icon + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1550580365 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1550580364} + 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: 1357199463} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 310, y: 93} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1550580366 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1550580364} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1550580367 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1550580364} + m_CullTransparentMesh: 1 +--- !u!1 &1634709545 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1634709546} + - component: {fileID: 1634709548} + - component: {fileID: 1634709547} + m_Layer: 0 + m_Name: bg + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1634709546 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1634709545} + 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: 1357199463} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1634709547 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1634709545} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.20754719, g: 0.20754719, b: 0.20754719, a: 0.72156864} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1634709548 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1634709545} + m_CullTransparentMesh: 1 +--- !u!1001 &1807394934 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 2119601174} + m_Modifications: + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 175947125} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: LeaveParty + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: MainMenu, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_text + value: LEAVE PARTY + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 300 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -223.1375 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6668870933609579488, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Name + value: LeaveParty_Buttom_Element + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 346d6982b88c8cd42bb414912972cfaa, type: 3} +--- !u!224 &1807394935 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 1807394934} + m_PrefabAsset: {fileID: 0} +--- !u!1 &1819503695 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1819503696} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1819503696 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1819503695} + 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: 909289948} + m_Father: {fileID: 1200274992} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1824664575 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1824664576} + - component: {fileID: 1824664579} + - component: {fileID: 1824664578} + - component: {fileID: 1824664577} + - component: {fileID: 1824664580} + m_Layer: 5 + m_Name: FriendList + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1824664576 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1824664575} + 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: 375604165} + - {fileID: 1200274992} + - {fileID: 40274434} + m_Father: {fileID: 727777085} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: -489, y: 0} + m_SizeDelta: {x: 800, y: 1500} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1824664577 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1824664575} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1aa08ab6e0800fa44ae55d278d1423e3, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 937080729} + m_Horizontal: 1 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 375604165} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 1200274993} + m_HorizontalScrollbarVisibility: 2 + m_VerticalScrollbarVisibility: 2 + m_HorizontalScrollbarSpacing: -3 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &1824664578 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1824664575} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 0.392} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1824664579 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1824664575} + m_CullTransparentMesh: 1 +--- !u!114 &1824664580 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1824664575} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9083ffff4021744597068b92d1df3db, type: 3} + m_Name: + m_EditorClassIdentifier: + _steamFriendItem: {fileID: 868074393274563534, guid: ed41cb43487d1944c8a4a1207f3fe173, + type: 3} + _friendListContainer: {fileID: 937080729} + _friendList: [] + timeToRefreshList: 30 +--- !u!1 &1849245961 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1849245962} + - component: {fileID: 1849245965} + - component: {fileID: 1849245964} + - component: {fileID: 1849245963} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1849245962 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849245961} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.9996778, z: -0, w: 0.025385052} + m_LocalPosition: {x: -0.3722986, y: 0.50841004, z: 0.4547567} + m_LocalScale: {x: 0.5325624, y: 1.804699, z: 0.53133565} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1915777234} + m_Father: {fileID: 828025626} + m_LocalEulerAnglesHint: {x: 0, y: -35.153, z: 0} +--- !u!65 &1849245963 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849245961} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1849245964 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849245961} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &1849245965 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849245961} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1915777233 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1915777234} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1915777234 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1915777233} + 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: 1849245962} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2010138959 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2010138961} + - component: {fileID: 2010138960} + m_Layer: 0 + m_Name: CharacterSkinHandler + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2010138960 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2010138959} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 57d18d537abc50e4fa7a309050dfbbe5, type: 3} + m_Name: + m_EditorClassIdentifier: + characterSkinPrefab: {fileID: 268687697814956617, guid: 53f9b17a77863de4294a4588ac92219e, + type: 3} + spawnPositions: + - {fileID: 408054734} + - {fileID: 1147238474} + - {fileID: 2125853218} + - {fileID: 1447145128} + clientsCharacters: [] +--- !u!4 &2010138961 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2010138959} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 1.2901233, y: 1.2059157, z: 5.845375} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2046918406 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2046918407} + - component: {fileID: 2046918410} + - component: {fileID: 2046918409} + - component: {fileID: 2046918408} + m_Layer: 0 + m_Name: Cube (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2046918407 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2046918406} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.86945814, z: -0, w: 0.49400666} + m_LocalPosition: {x: -0.4473228, y: 0, z: 0.9662192} + m_LocalScale: {x: 0.7188414, y: 1.804699, z: 0.37978923} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1402023608} + m_Father: {fileID: 1019480629} + m_LocalEulerAnglesHint: {x: 0, y: -91.452, z: 0} +--- !u!65 &2046918408 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2046918406} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &2046918409 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2046918406} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &2046918410 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2046918406} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1001 &2111335288 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1319193669} + m_Modifications: + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 175947125} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: StartLocalHost + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: MainMenu, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 1830634547527162540, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 2086726451323268952, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_text + value: START LOCAL HOST + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.x + value: 600 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 350.90002 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -256.5 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6668870933609579488, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + propertyPath: m_Name + value: StartLocalHost_Buttom_Element + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 346d6982b88c8cd42bb414912972cfaa, type: 3} +--- !u!224 &2111335289 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4060705358705524266, guid: 346d6982b88c8cd42bb414912972cfaa, + type: 3} + m_PrefabInstance: {fileID: 2111335288} + m_PrefabAsset: {fileID: 0} +--- !u!1 &2119601173 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2119601174} + - component: {fileID: 2119601175} + m_Layer: 5 + m_Name: Main_Buttons + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2119601174 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2119601173} + 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: 1053502564} + - {fileID: 1807394935} + m_Father: {fileID: 727777085} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 367, y: 197} + m_SizeDelta: {x: 627.375, y: 321.685} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2119601175 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2119601173} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 24.59 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &2125853217 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2125853218} + - component: {fileID: 2125853219} + m_Layer: 0 + m_Name: StartPosition (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2125853218 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2125853217} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.30299997, y: -0.162, z: 3.709} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2125853219 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2125853217} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 330585546} + - {fileID: 410087041} + - {fileID: 832575519} + - {fileID: 1332214904} + - {fileID: 95399542} + - {fileID: 2010138961} + - {fileID: 1402974731} + - {fileID: 175947124} + - {fileID: 615982980} diff --git a/Assets/Scenes/MainMenu.unity.meta b/Assets/Scenes/MainMenu.unity.meta new file mode 100644 index 0000000..76e14d5 --- /dev/null +++ b/Assets/Scenes/MainMenu.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 12157234c67dbe34d896282161c213b6 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Stage_1.unity b/Assets/Scenes/Stage_1.unity new file mode 100644 index 0000000..52e71b4 --- /dev/null +++ b/Assets/Scenes/Stage_1.unity @@ -0,0 +1,1514 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &117194702 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 117194703} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &117194703 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 117194702} + 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: 393397516} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &393397515 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 393397516} + - component: {fileID: 393397519} + - component: {fileID: 393397518} + - component: {fileID: 393397517} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &393397516 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393397515} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.9996778, z: -0, w: 0.025385052} + m_LocalPosition: {x: -0.3722986, y: 0.50841004, z: 0.4547567} + m_LocalScale: {x: 0.5325624, y: 1.804699, z: 0.53133565} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 117194703} + m_Father: {fileID: 1019480629} + m_LocalEulerAnglesHint: {x: 0, y: -35.153, z: 0} +--- !u!65 &393397517 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393397515} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &393397518 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393397515} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &393397519 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393397515} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &408054733 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 408054734} + - component: {fileID: 408054735} + m_Layer: 0 + m_Name: StartPosition + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &408054734 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 408054733} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.697, y: 1.49, z: 2.709} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &408054735 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 408054733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &410087039 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 410087041} + - component: {fileID: 410087040} + - component: {fileID: 410087042} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &410087040 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410087039} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 2 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 5000 + m_UseColorTemperature: 1 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &410087041 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410087039} + serializedVersion: 2 + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!114 &410087042 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410087039} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 1 +--- !u!1 &615982979 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 615982980} + m_Layer: 0 + m_Name: Map + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &615982980 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 615982979} + 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: 408054734} + - {fileID: 1147238474} + - {fileID: 2125853218} + - {fileID: 1447145128} + - {fileID: 1541976207} + - {fileID: 828025626} + - {fileID: 1019480629} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &828025625 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 828025626} + m_Layer: 0 + m_Name: Rock + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &828025626 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 828025625} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0.9606732, z: -0, w: -0.27768135} + m_LocalPosition: {x: 2.96, y: 0.63, z: 9.61} + m_LocalScale: {x: 2.3724446, y: 1.6915479, z: 1.5371715} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1070089436} + - {fileID: 1849245962} + - {fileID: 1517980880} + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &832575517 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 832575519} + - component: {fileID: 832575518} + m_Layer: 0 + m_Name: Global Volume + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &832575518 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 832575517} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IsGlobal: 1 + priority: 0 + blendDistance: 0 + weight: 1 + sharedProfile: {fileID: 11400000, guid: a6560a915ef98420e9faacc1c7438823, type: 2} +--- !u!4 &832575519 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 832575517} + 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: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1019480628 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1019480629} + m_Layer: 0 + m_Name: Rock (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1019480629 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1019480628} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.7311311, z: -0, w: -0.682237} + m_LocalPosition: {x: -1.64, y: 0.63, z: 5.06} + m_LocalScale: {x: 2.3724446, y: 1.6915479, z: 1.5371715} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1305261509} + - {fileID: 393397516} + - {fileID: 2046918407} + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: -93.963, z: 0} +--- !u!1 &1070089435 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1070089436} + - component: {fileID: 1070089439} + - component: {fileID: 1070089438} + - component: {fileID: 1070089437} + m_Layer: 0 + m_Name: Cube (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1070089436 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1070089435} + 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: 828025626} + m_LocalEulerAnglesHint: {x: 0, y: -212.244, z: 0} +--- !u!65 &1070089437 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1070089435} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1070089438 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1070089435} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &1070089439 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1070089435} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1147238473 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1147238474} + - component: {fileID: 1147238475} + m_Layer: 0 + m_Name: StartPosition (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1147238474 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1147238473} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 1.947, y: 1.49, z: 3.459} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1147238475 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1147238473} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &1305261508 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1305261509} + - component: {fileID: 1305261512} + - component: {fileID: 1305261511} + - component: {fileID: 1305261510} + m_Layer: 0 + m_Name: Cube (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1305261509 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305261508} + 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: 1019480629} + m_LocalEulerAnglesHint: {x: 0, y: -212.244, z: 0} +--- !u!65 &1305261510 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305261508} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1305261511 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305261508} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &1305261512 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305261508} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1332214901 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1332214904} + - component: {fileID: 1332214903} + - component: {fileID: 1332214902} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1332214902 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1332214901} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1332214903 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1332214901} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1332214904 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1332214901} + 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: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1402023607 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1402023608} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1402023608 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1402023607} + 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: 2046918407} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1447145127 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1447145128} + - component: {fileID: 1447145129} + m_Layer: 0 + m_Name: StartPosition (3) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1447145128 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1447145127} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 3.197, y: 1.49, z: 4.709} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1447145129 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1447145127} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &1517980879 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1517980880} + - component: {fileID: 1517980883} + - component: {fileID: 1517980882} + - component: {fileID: 1517980881} + m_Layer: 0 + m_Name: Cube (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1517980880 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517980879} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.86945814, z: -0, w: 0.49400666} + m_LocalPosition: {x: -0.4473228, y: 0, z: 0.9662192} + m_LocalScale: {x: 0.7188414, y: 1.804699, z: 0.37978923} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1537298478} + m_Father: {fileID: 828025626} + m_LocalEulerAnglesHint: {x: 0, y: -91.452, z: 0} +--- !u!65 &1517980881 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517980879} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1517980882 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517980879} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &1517980883 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517980879} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1537298477 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1537298478} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1537298478 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1537298477} + 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: 1517980880} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1541976206 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1541976207} + - component: {fileID: 1541976210} + - component: {fileID: 1541976209} + - component: {fileID: 1541976208} + m_Layer: 0 + m_Name: Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1541976207 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1541976206} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 1.2581} + m_LocalScale: {x: 2.6819, y: 1, z: 2.8200948} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!64 &1541976208 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1541976206} + 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: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1541976209 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1541976206} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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!33 &1541976210 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1541976206} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1849245961 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1849245962} + - component: {fileID: 1849245965} + - component: {fileID: 1849245964} + - component: {fileID: 1849245963} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1849245962 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849245961} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.9996778, z: -0, w: 0.025385052} + m_LocalPosition: {x: -0.3722986, y: 0.50841004, z: 0.4547567} + m_LocalScale: {x: 0.5325624, y: 1.804699, z: 0.53133565} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1915777234} + m_Father: {fileID: 828025626} + m_LocalEulerAnglesHint: {x: 0, y: -35.153, z: 0} +--- !u!65 &1849245963 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849245961} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1849245964 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849245961} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &1849245965 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849245961} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1915777233 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1915777234} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1915777234 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1915777233} + 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: 1849245962} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2046918406 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2046918407} + - component: {fileID: 2046918410} + - component: {fileID: 2046918409} + - component: {fileID: 2046918408} + m_Layer: 0 + m_Name: Cube (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2046918407 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2046918406} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.86945814, z: -0, w: 0.49400666} + m_LocalPosition: {x: -0.4473228, y: 0, z: 0.9662192} + m_LocalScale: {x: 0.7188414, y: 1.804699, z: 0.37978923} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1402023608} + m_Father: {fileID: 1019480629} + m_LocalEulerAnglesHint: {x: 0, y: -91.452, z: 0} +--- !u!65 &2046918408 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2046918406} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &2046918409 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2046918406} + m_Enabled: 1 + 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: + - {fileID: 2100000, guid: c7ae0124944d0364984ad3872a6720f9, 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!33 &2046918410 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2046918406} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &2125853217 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2125853218} + - component: {fileID: 2125853219} + m_Layer: 0 + m_Name: StartPosition (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2125853218 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2125853217} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.30299997, y: 1.49, z: 3.709} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 615982980} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2125853219 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2125853217} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 410087041} + - {fileID: 832575519} + - {fileID: 1332214904} + - {fileID: 615982980} diff --git a/Assets/Scenes/Stage_1.unity.meta b/Assets/Scenes/Stage_1.unity.meta new file mode 100644 index 0000000..f5de25c --- /dev/null +++ b/Assets/Scenes/Stage_1.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 35feab57cfbaea048a5dacffd1f9d5b9 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts.meta b/Assets/Scripts.meta new file mode 100644 index 0000000..2ffabd6 --- /dev/null +++ b/Assets/Scripts.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: c842633c5b5d85447b5b01d3847400db +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Scripts/CharacterSkinElement.cs b/Assets/Scripts/CharacterSkinElement.cs new file mode 100644 index 0000000..8336841 --- /dev/null +++ b/Assets/Scripts/CharacterSkinElement.cs @@ -0,0 +1,67 @@ +using Steamworks; +using System; +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; + +public class CharacterSkinElement : MonoBehaviour +{ + public Transform nametagPos; + + public MyClient client { get; private set; } + public CSteamID steamId { get; private set; } + public NametagMarker nametagMarker { get; set; } + + bool initialized = false; + Sprite icon; + protected Callback avatarImageLoaded; + + private void OnAvatarImageLoaded(AvatarImageLoaded_t callback) + { + if (callback.m_steamID != steamId) return; + + Texture2D tex = SteamHelper.GetAvatar(steamId); + if(tex) + icon = SteamHelper.ConvertTextureToSprite(tex); + nametagMarker.UpdatePFP(icon); + } + + public void Initialize(MyClient client, bool _isReady) + { + string username = SteamFriends.GetPersonaName(); + bool isReady = _isReady; + + steamId = client ? new CSteamID(client.playerInfo.steamId) : SteamUser.GetSteamID(); + + if (nametagMarker == null) + nametagMarker = (NametagMarker)MarkerHandler.instance.SpawnMarker(0, nametagPos.position, null); + + if (client != null) + { + this.client = client; + username = client.playerInfo.username; + icon = client.icon; + } + + if (!initialized) + { + initialized = true; + avatarImageLoaded = Callback.Create(OnAvatarImageLoaded); + + Texture2D tex = SteamHelper.GetAvatar(steamId); + if (tex) + icon = SteamHelper.ConvertTextureToSprite(tex); nametagMarker.UpdatePFP(icon); + } + + nametagMarker.UpdateTag(username, isReady); + nametagMarker.UpdatePFP(icon); + } + + private void OnDestroy() + { + if (nametagMarker) + nametagMarker.DestroyMarker(); + } + +} diff --git a/Assets/Scripts/CharacterSkinElement.cs.meta b/Assets/Scripts/CharacterSkinElement.cs.meta new file mode 100644 index 0000000..19a6515 --- /dev/null +++ b/Assets/Scripts/CharacterSkinElement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b27e9af7236205e4cb5c6aceca60c9a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/CharacterSkinHandler.cs b/Assets/Scripts/CharacterSkinHandler.cs new file mode 100644 index 0000000..8283a4b --- /dev/null +++ b/Assets/Scripts/CharacterSkinHandler.cs @@ -0,0 +1,88 @@ +using Mirror; +using Steamworks; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + + +public class CharacterSkinHandler : MonoBehaviour +{ + public static CharacterSkinHandler instance; + + [SerializeField] private GameObject characterSkinPrefab; + [SerializeField] private Transform[] spawnPositions; + public CharacterSkinElement[] clientsCharacters; + private void Awake() + { + instance = this; + } + + private void Start() + { + clientsCharacters = new CharacterSkinElement[NetworkManager.singleton.maxConnections]; + + StartCoroutine(WaitTillSteamInitialized()); + } + + IEnumerator WaitTillSteamInitialized() + { + while (!SteamManager.Initialized) + yield return new WaitForEndOfFrame(); + + SpawnCharacterMesh(null); + } + public void SpawnCharacterMesh(MyClient client) + { + int index = GetNextPlatformIndex(client); + + if(client && client.isLocalPlayer) + { + client.characterInstance = clientsCharacters[0]; + client.characterInstance.Initialize(client, client.IsReady); + + return; + } + + clientsCharacters[index] = Instantiate(characterSkinPrefab, spawnPositions[index]).GetComponent(); + clientsCharacters[index].Initialize(client, client ? client.IsReady : false); + + + if (client) + client.characterInstance = clientsCharacters[index]; + } + + public int GetNextPlatformIndex(MyClient client) + { + if (client == null || client.isLocalPlayer) + return 0; + + for (int i = 0; i < clientsCharacters.Length; i++) + { + if(clientsCharacters[i] == null) + return i; + } + return 0; + } + + public void DestroyCharacterMesh(MyClient client) + { + foreach (var character in clientsCharacters) + { + if(character == null) + continue; + + if (character.client == client) + { + if (character == clientsCharacters[0]) + { + clientsCharacters[0].Initialize(client, false); + MainMenu.instance.UpdateReadyButton(false); + } + else + Destroy(character.gameObject); + + break; + } + } + } +} diff --git a/Assets/Scripts/CharacterSkinHandler.cs.meta b/Assets/Scripts/CharacterSkinHandler.cs.meta new file mode 100644 index 0000000..e0f3a06 --- /dev/null +++ b/Assets/Scripts/CharacterSkinHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57d18d537abc50e4fa7a309050dfbbe5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Extensions.meta b/Assets/Scripts/Extensions.meta new file mode 100644 index 0000000..06c45c8 --- /dev/null +++ b/Assets/Scripts/Extensions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3c3aed70129c830468c2963252484828 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Extensions/ArrayExtension.cs b/Assets/Scripts/Extensions/ArrayExtension.cs new file mode 100644 index 0000000..274798a --- /dev/null +++ b/Assets/Scripts/Extensions/ArrayExtension.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +public static class ArrayExtension +{ + + public static T GetRandomFromArray(T[] array) + { + if (array.Length > 0) + { + return array[Random.Range(0, array.Length)]; + } + return default; + } + +} diff --git a/Assets/Scripts/Extensions/ArrayExtension.cs.meta b/Assets/Scripts/Extensions/ArrayExtension.cs.meta new file mode 100644 index 0000000..f70d0ad --- /dev/null +++ b/Assets/Scripts/Extensions/ArrayExtension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c0653a9321e8014ea8aaade33c69f45 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Extensions/MonoBehaviourExtensions.cs b/Assets/Scripts/Extensions/MonoBehaviourExtensions.cs new file mode 100644 index 0000000..ec93d62 --- /dev/null +++ b/Assets/Scripts/Extensions/MonoBehaviourExtensions.cs @@ -0,0 +1,49 @@ +using System.Collections; +using UnityEngine; +using System; +using System.Collections.Generic; + +public static class MonoBehaviourExtensions +{ + + + /// + /// This will Call a method wtih a delay (including being able to use delegates unlike Invoke(nameof(method), delay);) + /// + /// + /// + /// + public static void CallWithDelay(this MonoBehaviour mono, Action method, float delay) + => mono.StartCoroutine(CallWithDelayRoutine(method, delay)); + + static IEnumerator CallWithDelayRoutine(Action method, float delay) + { + yield return new WaitForSeconds(delay); + method(); + } + + + public static GameObject[] ShuffleList(this MonoBehaviour mono, List list) + { + GameObject[] array = list.ToArray(); + + // Shuffle the array using Fisher-Yates algorithm + for (int i = 0; i < array.Length - 1; i++) + { + int randomIndex = UnityEngine.Random.Range(i, array.Length); + GameObject temp = array[i]; + array[i] = array[randomIndex]; + array[randomIndex] = temp; + } + + return array; + } + + public static float RoundValue(float value, int decimalAmount) + { + float multiplier = Mathf.Pow(10.0f, decimalAmount); + return Mathf.Round(value * multiplier) / multiplier; + } + +} + diff --git a/Assets/Scripts/Extensions/MonoBehaviourExtensions.cs.meta b/Assets/Scripts/Extensions/MonoBehaviourExtensions.cs.meta new file mode 100644 index 0000000..f2faa2f --- /dev/null +++ b/Assets/Scripts/Extensions/MonoBehaviourExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8546b79ebab6cc544b7e02354332a262 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Extensions/SteamHelper.cs b/Assets/Scripts/Extensions/SteamHelper.cs new file mode 100644 index 0000000..c70756f --- /dev/null +++ b/Assets/Scripts/Extensions/SteamHelper.cs @@ -0,0 +1,56 @@ +using Steamworks; +using System.Collections.Generic; +using UnityEngine; + +public static class SteamHelper +{ + + public static Texture2D GetAvatar(CSteamID steamID) + { + int imageID = SteamFriends.GetLargeFriendAvatar(steamID); + if (imageID == -1) return null; + + Texture2D texture = null; + + bool isValid = SteamUtils.GetImageSize(imageID, out uint width, out uint height); + + if (isValid) + { + byte[] image = new byte[width * height * 4]; + + isValid = SteamUtils.GetImageRGBA(imageID, image, (int)(width * height * 4)); + + if (isValid) + { + texture = new Texture2D((int)width, (int)height, TextureFormat.RGBA32, false, false); + texture.LoadRawTextureData(image); + texture.Apply(); + } + } + + return texture; + } + + + + public static Sprite ConvertTextureToSprite(Texture2D texture) + { + return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero); + } + + + public static List GetMembersInLobby() + { + List members = new List(); + int memberAmount = SteamMatchmaking.GetNumLobbyMembers(SteamLobby.LobbyID); + + for (int i = 0; i < memberAmount; i++) + { + CSteamID cSteamID = SteamMatchmaking.GetLobbyMemberByIndex(SteamLobby.LobbyID, i); + members.Add(cSteamID); + } + + return members; + } +} + diff --git a/Assets/Scripts/Extensions/SteamHelper.cs.meta b/Assets/Scripts/Extensions/SteamHelper.cs.meta new file mode 100644 index 0000000..4888134 --- /dev/null +++ b/Assets/Scripts/Extensions/SteamHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7faf9027c4eb4594798d708da42bd056 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/FriendItem.cs b/Assets/Scripts/FriendItem.cs new file mode 100644 index 0000000..a0238d8 --- /dev/null +++ b/Assets/Scripts/FriendItem.cs @@ -0,0 +1,62 @@ +using Steamworks; +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class FriendItem : MonoBehaviour +{ + [SerializeField] private Image _iconImage; + [SerializeField] private Image _statusImage; + [SerializeField] private TMP_Text _usernameText; + +/* [SerializeField] private Color onlineColor; + [SerializeField] private Color offlineColor;*/ + private string username; + private CSteamID steamID; + private bool isOnline; + + private void Start() + { + avatarImageLoaded = Callback.Create(OnAvatarImageLoaded); + } + public void InitializeFriendItem(string name, ulong id, bool status) + { + username = name; + steamID = new CSteamID(id); + isOnline = status; + + _usernameText.text = username; + //_statusImage.color = isOnline ? onlineColor : offlineColor; + + //_iconImage.sprite = SteamHelper.GetAvatar(steamID); + GetIcon(); + + } + + public void InviteFriend() + { + SteamMatchmaking.InviteUserToLobby(SteamLobby.LobbyID, steamID); + } + + + Sprite icon; + protected Callback avatarImageLoaded; + + private void OnAvatarImageLoaded(AvatarImageLoaded_t callback) + { + if (callback.m_steamID != steamID) return; + GetIcon(); + } + + void GetIcon() + { + Texture2D tex = SteamHelper.GetAvatar(steamID); + if (tex) + { + icon = SteamHelper.ConvertTextureToSprite(tex); + _iconImage.sprite = icon; + } + } +} diff --git a/Assets/Scripts/FriendItem.cs.meta b/Assets/Scripts/FriendItem.cs.meta new file mode 100644 index 0000000..7f43d86 --- /dev/null +++ b/Assets/Scripts/FriendItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 39424224dc4222c4a803fa7e76838603 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/FriendListManager.cs b/Assets/Scripts/FriendListManager.cs new file mode 100644 index 0000000..d002183 --- /dev/null +++ b/Assets/Scripts/FriendListManager.cs @@ -0,0 +1,102 @@ +using Steamworks; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class FriendListManager : MonoBehaviour +{ + [SerializeField] private GameObject _steamFriendItem; + [SerializeField] private Transform _friendListContainer; + [SerializeField] private List _friendList = new List(); + + private Dictionary friendDictionary = new Dictionary(); + + + [SerializeField] private float timeToRefreshList = 30f; + float timer; + + bool initialized = false; + private void Start() + { + + } + private void Update() + { + if (SteamManager.Initialized) + { + if (!initialized) + { + GetSteamFriends(); + initialized = true; + return; + } + + timer += Time.deltaTime; + if (timer > timeToRefreshList) + { + GetSteamFriends(); + timer = 0; + } + } + } + + private void GetSteamFriends() + { + if (_friendList.Count > 0) + { + foreach (FriendItem friend in _friendList) + { + Destroy(friend.gameObject); + } + _friendList.Clear(); + } + + int friendsCount = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate); + int currentOnlineCount = 0; + + if (friendsCount == -1) + { + Debug.LogError("Friend count returned at -1, the user is not logged in"); + friendsCount = 0; + } + + //ONLINE FIRST + for (int i = 0; i < friendsCount; i++) + { + CSteamID friendSteamID = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate); + string friendName = SteamFriends.GetFriendPersonaName(friendSteamID); + EPersonaState friendState = SteamFriends.GetFriendPersonaState(friendSteamID); + + bool isOnline = false; + + if (friendState == EPersonaState.k_EPersonaStateOffline) + continue; + else + isOnline = true; + + FriendItem friendItem = Instantiate(_steamFriendItem, _friendListContainer).GetComponent(); + friendItem.InitializeFriendItem(friendName, friendSteamID.m_SteamID, isOnline); + _friendList.Add(friendItem); + currentOnlineCount++; + } + + //OFFLINE LAST + for (int i = 0; i < friendsCount; i++) + { + CSteamID friendSteamID = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate); + string friendName = SteamFriends.GetFriendPersonaName(friendSteamID); + EPersonaState friendState = SteamFriends.GetFriendPersonaState(friendSteamID); + + bool isOnline = false; + + if (friendState == EPersonaState.k_EPersonaStateOffline) + isOnline = false; + else + continue; + + FriendItem friendItem = Instantiate(_steamFriendItem, _friendListContainer).GetComponent(); + friendItem.InitializeFriendItem(friendName, friendSteamID.m_SteamID, isOnline); + _friendList.Add(friendItem); + } + } +} diff --git a/Assets/Scripts/FriendListManager.cs.meta b/Assets/Scripts/FriendListManager.cs.meta new file mode 100644 index 0000000..7c2d0a3 --- /dev/null +++ b/Assets/Scripts/FriendListManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9083ffff4021744597068b92d1df3db +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/LobbyController.cs b/Assets/Scripts/LobbyController.cs new file mode 100644 index 0000000..cd137f9 --- /dev/null +++ b/Assets/Scripts/LobbyController.cs @@ -0,0 +1,53 @@ +using Mirror; +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class LobbyController : MonoBehaviour +{ + public static LobbyController instance; + + private void Awake() + { + instance = this; + } + + + public void StartGameWithParty() + { + if (AllPlayersReady()) + { + StartGame(); + } + } + + + public void StartGameSolo() + { + StartCoroutine(StartSinglePlayer()); + } + IEnumerator StartSinglePlayer() + { + NetworkManager.singleton.StartHost(); + + while(NetworkClient.localPlayer == null) + yield return new WaitForEndOfFrame(); + + ((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(false); + StartGame(); + } + + private void StartGame() + { + NetworkManager.singleton.ServerChangeScene("Stage_1"); + } + + private bool AllPlayersReady() + { + foreach (MyClient client in ((MyNetworkManager)NetworkManager.singleton).allClients) + if (!client.IsReady) + return false; + return true; + } +} diff --git a/Assets/Scripts/LobbyController.cs.meta b/Assets/Scripts/LobbyController.cs.meta new file mode 100644 index 0000000..dd191d6 --- /dev/null +++ b/Assets/Scripts/LobbyController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9ba7df8027f02f94c92f43d9d02d5b7c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/MainMenu.cs b/Assets/Scripts/MainMenu.cs new file mode 100644 index 0000000..5e224cc --- /dev/null +++ b/Assets/Scripts/MainMenu.cs @@ -0,0 +1,93 @@ +using Mirror; +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public enum MenuState { Home, InParty} +public class MainMenu : MonoBehaviour +{ + public static MainMenu instance; + + public MenuState state = MenuState.Home; + [SerializeField] private GameObject homeUI, partyUI; + + [Header("Ready Button")] + [SerializeField] private Image readyButton_Image; + [SerializeField] private TMP_Text readyButton_Text; + public Color readyColor, notReadyColor; + private void Awake() + { + instance = this; + } + + public void SetMenuState(MenuState state) + { + this.state = state; + + homeUI.SetActive(state == MenuState.Home); + partyUI.SetActive(state == MenuState.InParty); + } + + public void CreateParty() + { + + PopupManager.instance.Popup_Show("Creating Party"); + + ((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(true); + SteamLobby.instance.CreateLobby(); + } + + public void StartSinglePlayer() + { + LobbyController.instance.StartGameSolo(); + } + + public void LeaveParty() + { + if (!NetworkClient.active) return; + + if(NetworkClient.localPlayer.isServer) + NetworkManager.singleton.StopHost(); + else + NetworkManager.singleton.StopClient(); + + SteamLobby.instance.Leave(); + } + + public void FindMatch() + { + SteamLobby.instance.FindMatch(); + } + + public void StartGame() + { + LobbyController.instance.StartGameWithParty(); + } + + public void StartLocalClient() + { + ((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(true); + NetworkManager.singleton.StartClient(); + } + + public void StartLocalHost() + { + ((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(true); + NetworkManager.singleton.StartHost(); + } + + public void ToggleReady() + { + if (!NetworkClient.active) return; + + NetworkClient.localPlayer.GetComponent().ToggleReady(); + } + + public void UpdateReadyButton(bool value) + { + readyButton_Text.text = value ? "Ready" : "Not Ready"; + readyButton_Image.color = value ? readyColor : notReadyColor; + } +} diff --git a/Assets/Scripts/MainMenu.cs.meta b/Assets/Scripts/MainMenu.cs.meta new file mode 100644 index 0000000..6027fd9 --- /dev/null +++ b/Assets/Scripts/MainMenu.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 284b6fd5c3191dc4fac424b5f10dfa81 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Markers.meta b/Assets/Scripts/Markers.meta new file mode 100644 index 0000000..a2969c7 --- /dev/null +++ b/Assets/Scripts/Markers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9df7d0ffa0b65b419c8bf6b476132f7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Markers/Marker.cs b/Assets/Scripts/Markers/Marker.cs new file mode 100644 index 0000000..0b6bdc5 --- /dev/null +++ b/Assets/Scripts/Markers/Marker.cs @@ -0,0 +1,54 @@ +using Mirror; +using System; +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; + +public class Marker : MonoBehaviour +{ + public MarkerDefinition markerDefinition; +/* public CanvasGroup fadeGroup; + public CanvasGroup aimFadeGroup; + public AnimationCurve fadeRemap;*/ + + public Vector3 targetPos { get; private set; } + public GameObject worldObject { get; private set; } + + MarkerHandler markerHandler; + Transform objToFollow; + + float timeAlive; + + private void Update() + { + if (objToFollow) + { + targetPos = objToFollow.transform.position; + } + + + if (markerDefinition.unlimitedLife) return; + + timeAlive += Time.deltaTime; + if (timeAlive > markerDefinition.lifeDuration) + { + DestroyMarker(); + } + } + + public virtual void InitializeMarker(MarkerHandler markerHandler, GameObject worldObject, Vector3 targetPos, Transform objToFollow) + { + this.markerHandler = markerHandler; + this.worldObject = worldObject; + this.targetPos = targetPos; + this.objToFollow = objToFollow; +/* aimFadeGroup.alpha = 0; + fadeGroup.alpha = 0;*/ + } + + public virtual void DestroyMarker() + { + markerHandler.RemoveMarker(this); + } +} diff --git a/Assets/Scripts/Markers/Marker.cs.meta b/Assets/Scripts/Markers/Marker.cs.meta new file mode 100644 index 0000000..3a99a41 --- /dev/null +++ b/Assets/Scripts/Markers/Marker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2cd7a42d3a95a6469836350e9008ffc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Markers/MarkerDefinition.cs b/Assets/Scripts/Markers/MarkerDefinition.cs new file mode 100644 index 0000000..d9cb58c --- /dev/null +++ b/Assets/Scripts/Markers/MarkerDefinition.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +[CreateAssetMenu(menuName = "Markers/Marker")] +public class MarkerDefinition : ScriptableObject +{ + public byte id; + + [Space(10)] + public GameObject markerLocalObj, markerWorldObj; + public float lifeDuration; + public bool unlimitedLife; + public float minFadeAmount; + public bool fadeByDotProduct; + public bool fadeByAim; +} + diff --git a/Assets/Scripts/Markers/MarkerDefinition.cs.meta b/Assets/Scripts/Markers/MarkerDefinition.cs.meta new file mode 100644 index 0000000..e7c0344 --- /dev/null +++ b/Assets/Scripts/Markers/MarkerDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 35a98cf24352f1f4d99d7a33c0b4d1e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Markers/MarkerHandler.cs b/Assets/Scripts/Markers/MarkerHandler.cs new file mode 100644 index 0000000..96083b7 --- /dev/null +++ b/Assets/Scripts/Markers/MarkerHandler.cs @@ -0,0 +1,89 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class MarkerHandler : MonoBehaviour +{ + public static MarkerHandler instance; + + [SerializeField] private MarkerDefinition[] allMarkerDefinitions; + [SerializeField] private Transform markerContainer; + + List markerInstances = new List(); + Camera cam; + + private void Awake() + { + instance = this; + } + + private void Start() + { + cam = Camera.main; + } + + private void LateUpdate() + { + UpdateMarkers(); + } + void UpdateMarkers() + { + + for (int i = 0; i < markerInstances.Count; i++) + { + var currentMarker = markerInstances[i]; + currentMarker.transform.position = cam.WorldToScreenPoint(currentMarker.targetPos); + // aimFadeAmount = 1 - player.weaponManager.aim.aimAmount; + + bool isBehindCam = currentMarker.transform.position.z < 0; + float dot = Vector3.Dot(cam.transform.forward, (cam.transform.position - currentMarker.targetPos).normalized); + //Debug.Log(dot); + + /* + if (currentMarker.markerDefinition.fadeByAim) + currentMarker.aimFadeGroup.alpha = isBehindCam ? 0 : Mathf.Max(aimFadeAmount, currentMarker.markerDefinition.minFadeAmount); + + if (currentMarker.markerDefinition.fadeByDotProduct) + currentMarker.fadeGroup.alpha = isBehindCam ? 0 : Mathf.Clamp01(Mathf.Clamp(currentMarker.fadeRemap.Evaluate(Mathf.Clamp01(-dot)), currentMarker.markerDefinition.minFadeAmount, 1)); + + currentMarker.gameObject.SetActive(!player.IsUIOpen());*/ + } + + } + + public Marker SpawnMarker(byte markerID, Vector3 targetPos, Transform objToFollow) + { + MarkerDefinition markerDef = allMarkerDefinitions[markerID]; + + GameObject localObj = Instantiate(markerDef.markerLocalObj, markerContainer); + GameObject worldObj = null; + Marker marker = localObj.GetComponent(); + + if (markerDef.markerWorldObj) + { + worldObj = Instantiate(markerDef.markerWorldObj, targetPos, Quaternion.identity); + } + + marker.InitializeMarker(this, worldObj, targetPos, objToFollow); + + AddMarker(marker); + + return marker; + } + + public void AddMarker(Marker marker) + { + markerInstances.Add(marker); + } + + public void RemoveMarker(Marker marker) + { + markerInstances.Remove(marker); + + if (marker.worldObject) + Destroy(marker.worldObject); + + Destroy(marker.gameObject); + } + +} diff --git a/Assets/Scripts/Markers/MarkerHandler.cs.meta b/Assets/Scripts/Markers/MarkerHandler.cs.meta new file mode 100644 index 0000000..63d0e98 --- /dev/null +++ b/Assets/Scripts/Markers/MarkerHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c3fa5eb1f4aef54a91cc6c50111cc9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Markers/NametagMarker.cs b/Assets/Scripts/Markers/NametagMarker.cs new file mode 100644 index 0000000..a21ad9e --- /dev/null +++ b/Assets/Scripts/Markers/NametagMarker.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class NametagMarker : Marker +{ + public TMP_Text username_text, ready_text; + public Image ready_image, pfp_Image; + + public void UpdateTag(string username, bool isReady) + { + username_text.text = username; + ready_image.color = isReady ? MainMenu.instance.readyColor : MainMenu.instance.notReadyColor; + ready_text.text = isReady ? "Ready" : "Not Ready"; + ready_text.color = isReady ? MainMenu.instance.readyColor : MainMenu.instance.notReadyColor; + } + + public void UpdatePFP(Sprite icon) + { + pfp_Image.sprite = icon; + } +} diff --git a/Assets/Scripts/Markers/NametagMarker.cs.meta b/Assets/Scripts/Markers/NametagMarker.cs.meta new file mode 100644 index 0000000..c9b2ba1 --- /dev/null +++ b/Assets/Scripts/Markers/NametagMarker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 79b83d359693de5458001ffa4e86801e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Movement.cs b/Assets/Scripts/Movement.cs new file mode 100644 index 0000000..a920d16 --- /dev/null +++ b/Assets/Scripts/Movement.cs @@ -0,0 +1,94 @@ +using Mirror; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Movement : NetworkBehaviour +{ + [Header("Movement Settings")] + [SerializeField] private float walkingSpeed = 7.5f; + [SerializeField] private float runningSpeed = 11.5f; + [SerializeField] private float jumpHeight = 8.0f; + [SerializeField] private float gravity = 20.0f; + public Camera playerCamera; + + [Header("Grounding")] + [SerializeField] private LayerMask groundMask; + [SerializeField] private Transform groundedCheck; + [SerializeField] private float groundedDistance = 2; + + [Header("Camera")] + [SerializeField] private Transform camHolder; + [SerializeField] private float lookSpeed = 2.0f; + [SerializeField] private float lookXLimit = 45.0f; + float rotationX = 0; + Vector2 inputDir; + + + + public CharacterController characterController { get; private set; } + public bool isGrounded { get; private set; } + + Vector3 velocity; + + void Start() + { + Cursor.lockState = CursorLockMode.Locked; + characterController = GetComponent(); + } + + + void FixedUpdate() + { + if (!isLocalPlayer) return; + + CheckIfGrounded(); + bool isRunning = Input.GetKey(KeyCode.LeftShift); + MovementHandler(isRunning); + } + + private void MovementHandler(bool isRunning) + { + if (isGrounded && velocity.y < 0) + velocity.y = 0f; + + Vector3 moveDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized; + Vector3 fixedMoveDir; + + moveDir *= (isRunning ? runningSpeed : walkingSpeed); + moveDir = transform.TransformDirection(moveDir); + + if (Input.GetButtonDown("Jump") && isGrounded) + velocity.y += Mathf.Sqrt(jumpHeight * -3.0f * -gravity); + + velocity.y -= gravity * Time.deltaTime; + + fixedMoveDir = moveDir; + fixedMoveDir.y = velocity.y; + + characterController.Move(fixedMoveDir * Time.deltaTime); + } + + public void CheckIfGrounded() + { + isGrounded = Physics.Raycast(groundedCheck.position, Vector3.down, groundedDistance, groundMask); + } + + + private void LateUpdate() + { + if (!isLocalPlayer) return; + + inputDir = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")); + rotationX += -inputDir.y * lookSpeed; + rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit); + camHolder.transform.localRotation = Quaternion.Euler(rotationX, 0, 0); + transform.rotation *= Quaternion.Euler(0, inputDir.x * lookSpeed, 0); + } + + private void OnDrawGizmos() + { + if (groundedCheck) + Gizmos.DrawRay(groundedCheck.position, Vector3.down * groundedDistance); + } +} diff --git a/Assets/Scripts/Movement.cs.meta b/Assets/Scripts/Movement.cs.meta new file mode 100644 index 0000000..9daf83d --- /dev/null +++ b/Assets/Scripts/Movement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1345dc4c8b97453448fc9e22f2205527 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/MyClient.cs b/Assets/Scripts/MyClient.cs new file mode 100644 index 0000000..e8549e7 --- /dev/null +++ b/Assets/Scripts/MyClient.cs @@ -0,0 +1,133 @@ +using Mirror; +using Steamworks; +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; + +[System.Serializable] +public struct PlayerInfoData +{ + public string username; + public ulong steamId; + + public PlayerInfoData(string username, ulong steamId) + { + this.username = username; + this.steamId = steamId; + } +} +public class MyClient : NetworkBehaviour +{ + [SyncVar(hook = nameof(PlayerInfoUpdate))] + public PlayerInfoData playerInfo; + + [SyncVar(hook = nameof(IsReadyUpdate))] + public bool IsReady; + + [Header("Controller")] + [SerializeField] private GameObject controllerObj; + [SerializeField] private GameObject meshObj; + [SerializeField] private GameObject camHolder; + [SerializeField] private Behaviour[] controllerComponents; + + public Sprite icon { get; private set; } + public CharacterSkinElement characterInstance { get; set; } + + #region Steam PFP + protected Callback avatarImageLoaded; + private void OnAvatarImageLoaded(AvatarImageLoaded_t callback) + { + Debug.Log("Avatar loaded " + callback.m_steamID); + if (callback.m_steamID.m_SteamID != playerInfo.steamId) return; + SetIcon(callback.m_steamID); + } + + void SetIcon(CSteamID steamId) + { + Texture2D tex = SteamHelper.GetAvatar(steamId); + if (tex) + icon = SteamHelper.ConvertTextureToSprite(tex); + } + #endregion + + private void Start() + { + ((MyNetworkManager)NetworkManager.singleton).allClients.Add(this); + + if(CharacterSkinHandler.instance) CharacterSkinHandler.instance.SpawnCharacterMesh(this); + avatarImageLoaded = Callback.Create(OnAvatarImageLoaded); + + if (SceneManager.GetActiveScene().name != "MainMenu") + { + ToggleController(true); + } + else + { + ToggleController(false); + } + } + + void ToggleController(bool value) + { + controllerObj.SetActive(value); + meshObj.SetActive(value ? !isLocalPlayer : false); + camHolder.SetActive(value ? isLocalPlayer : false); + + if (!isLocalPlayer) + value = false; + + + foreach (var component in controllerComponents) + { + component.enabled = value; + } + + GetComponent().enabled = value; + } + + #region Ready Up + public void ToggleReady() => Cmd_ToggleReady(); + + [Command] + private void Cmd_ToggleReady() + { + IsReady = !IsReady; + } + #endregion + + #region SyncVar Hooks + private void PlayerInfoUpdate(PlayerInfoData _, PlayerInfoData data) + { + if (characterInstance) + characterInstance.Initialize(this, IsReady); + + SetIcon(new CSteamID(data.steamId)); + } + + public void IsReadyUpdate(bool _, bool value) + { + if (characterInstance) + characterInstance.Initialize(this, value); + if (isLocalPlayer) + { + MainMenu.instance.UpdateReadyButton(value); + } + } + + #endregion + + + + private void OnDestroy() + { + if (this && ((MyNetworkManager)NetworkManager.singleton)) + ((MyNetworkManager)NetworkManager.singleton).allClients.Remove(this); + + if (characterInstance && !isLocalPlayer) + { + CharacterSkinHandler.instance.DestroyCharacterMesh(this); + } + } +} diff --git a/Assets/Scripts/MyClient.cs.meta b/Assets/Scripts/MyClient.cs.meta new file mode 100644 index 0000000..3e3dfac --- /dev/null +++ b/Assets/Scripts/MyClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c4b5dc7895a402408126e4e9a847dd6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/MyNetworkManager.cs b/Assets/Scripts/MyNetworkManager.cs new file mode 100644 index 0000000..1afcfb9 --- /dev/null +++ b/Assets/Scripts/MyNetworkManager.cs @@ -0,0 +1,58 @@ +using Mirror; +using Steamworks; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class MyNetworkManager : NetworkManager +{ + public static bool isMulitplayer; + + public List allClients = new List(); + public override void OnServerAddPlayer(NetworkConnectionToClient conn) + { + base.OnServerAddPlayer(conn); + + MyClient client = conn.identity.GetComponent(); + CSteamID steamId = SteamLobby.LobbyID.m_SteamID == 0 ? SteamUser.GetSteamID() : SteamMatchmaking.GetLobbyMemberByIndex(SteamLobby.LobbyID, allClients.Count); + client.playerInfo = new PlayerInfoData(SteamFriends.GetFriendPersonaName(steamId), steamId.m_SteamID); + } + + public override void OnServerDisconnect(NetworkConnectionToClient conn) + { + base.OnServerDisconnect(conn); + } + + public override void OnStartClient() + { + if (isMulitplayer) + { + MainMenu.instance.SetMenuState(MenuState.InParty); + PopupManager.instance.Popup_Close(); + } + + base.OnStartClient(); + } + + public override void OnStopClient() + { + if (isMulitplayer) + { + MainMenu.instance.SetMenuState(MenuState.Home); + } + + base.OnStopClient(); + } + + public void SetMultiplayer(bool value) + { + isMulitplayer = value; + + if (isMulitplayer) + + NetworkServer.dontListen = false; + else + + NetworkServer.dontListen = true; + } +} diff --git a/Assets/Scripts/MyNetworkManager.cs.meta b/Assets/Scripts/MyNetworkManager.cs.meta new file mode 100644 index 0000000..9eb11e8 --- /dev/null +++ b/Assets/Scripts/MyNetworkManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 123bbac7f620cae42b421b72cf58d0bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/PopupManager.cs b/Assets/Scripts/PopupManager.cs new file mode 100644 index 0000000..d2daec8 --- /dev/null +++ b/Assets/Scripts/PopupManager.cs @@ -0,0 +1,68 @@ +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class PopupManager : MonoBehaviour +{ + public static PopupManager instance; + + public TMP_Text text_title; + + public GameObject popUp; + + private void Awake() + { + instance = this; + } + + public void Popup_Show(string title) + { + text_title.text = title; + popUp.SetActive(true); + } + public void Popup_Close() + { + popUp.SetActive(false); + } + +} +/*public class PopupContent +{ + public string title; + public string text; + public Sprite icon; + public PopupContent_Button[] buttons; + + public PopupContent(string popup_title, string popup_text, Sprite popup_icon, PopupContent_Button[] popup_buttons) + { + title = popup_title; + text = popup_text; + icon = popup_icon; + buttons = popup_buttons; + } +} + +public class PopupContent_Button +{ + public string text = "OK"; + public string function = ""; + public MonoBehaviour function_caller; + + //shows default ok button + public PopupContent_Button() + { + text = "OK"; + function = ""; + function_caller = null; + } + + //show special button + public PopupContent_Button(string button_text, string button_function, MonoBehaviour button_function_caller) + { + text = button_text; + function = button_function; + function_caller = button_function_caller; + } +}*/ diff --git a/Assets/Scripts/PopupManager.cs.meta b/Assets/Scripts/PopupManager.cs.meta new file mode 100644 index 0000000..ddca3e9 --- /dev/null +++ b/Assets/Scripts/PopupManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 379041cc65f409e41b6ab54e09095c0f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/SteamLobby.cs b/Assets/Scripts/SteamLobby.cs new file mode 100644 index 0000000..6ceed88 --- /dev/null +++ b/Assets/Scripts/SteamLobby.cs @@ -0,0 +1,195 @@ +using Mirror; +using Steamworks; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.UI; + +[System.Serializable] +public class Lobby +{ + public CSteamID lobbyID; + public string name; + + public Lobby(CSteamID lobbyID, string name) + { + this.lobbyID = lobbyID; + this.name = name; + } +} + +public class SteamLobby : MonoBehaviour +{ + private const string HOST_ADDRESS_KEY = "HostAddress"; + + public static SteamLobby instance; + public static CSteamID LobbyID; + + public List allLobbies = new List(); + + //CallBacks + protected Callback lobbyCreated; + protected Callback joinRequested; + protected Callback lobbyEntered; + protected Callback lobbyMatchList; + + + private void Awake() + { + if (instance == null) + instance = this; + + lobbyMatchList = Callback.Create(OnLobbyMatchList); + } + + private void Start() + { + if (!SteamManager.Initialized) return; + + lobbyCreated = Callback.Create(OnLobbyCreated); + joinRequested = Callback.Create(OnJoinRequest); + lobbyEntered = Callback.Create(OnLobbyEntered); + + ReloadLobbyList(); + } + + + #region Steam Lobby + public void ReloadLobbyList() + { + allLobbies.Clear(); + + SteamMatchmaking.AddRequestLobbyListDistanceFilter(ELobbyDistanceFilter.k_ELobbyDistanceFilterWorldwide); + SteamMatchmaking.AddRequestLobbyListStringFilter("displayable", "true", ELobbyComparison.k_ELobbyComparisonEqual); + SteamMatchmaking.RequestLobbyList(); + } + void OnLobbyMatchList(LobbyMatchList_t param) + { + for (int i = 0; i < param.m_nLobbiesMatching; i++) + { + CSteamID lobbyID = SteamMatchmaking.GetLobbyByIndex(i); + CSteamID ownerID = SteamMatchmaking.GetLobbyOwner(lobbyID); + + allLobbies.Add(new Lobby(lobbyID, SteamMatchmaking.GetLobbyData(lobbyID, "name"))); + } + + allLobbies.Sort((a, b) => SteamMatchmaking.GetNumLobbyMembers(b.lobbyID).CompareTo(SteamMatchmaking.GetNumLobbyMembers(a.lobbyID))); + + /*for (int i = 0; i < allLobbies.Count; i++) + { + + if (SteamMatchmaking.GetLobbyData(allLobbies[i].lobbyID, "displayable") == "true") + { + var lobbyElement = Instantiate(MainMenu.instance.lobbyElementPrefab, MainMenu.instance.lobbyListContainer).GetComponent(); + lobbyElement.Initialize(allLobbies[i]); + allLobbies[i].listElement = lobbyElement.gameObject; + } + }*/ + } + + + public void CreateLobby() + { + SteamMatchmaking.CreateLobby(ELobbyType.k_ELobbyTypePublic, ((MyNetworkManager)NetworkManager.singleton).maxConnections); + } + + + public void JoinLobby(CSteamID lobby) + { + + SteamMatchmaking.JoinLobby(lobby); + } + + + private void OnLobbyCreated(LobbyCreated_t callback) + { + if (callback.m_eResult != EResult.k_EResultOK) { return; } + + string lobbyName = SteamFriends.GetFriendPersonaName(SteamUser.GetSteamID()); + + LobbyID = new CSteamID(callback.m_ulSteamIDLobby); + + + ((MyNetworkManager)NetworkManager.singleton).StartHost(); + + SteamMatchmaking.SetLobbyData(LobbyID, HOST_ADDRESS_KEY, SteamUser.GetSteamID().ToString()); + SteamMatchmaking.SetLobbyData(LobbyID, "name", lobbyName); + SteamMatchmaking.SetLobbyData(LobbyID, "displayable", "true"); + + SetLobbyLocation(); + } + + + private void OnJoinRequest(GameLobbyJoinRequested_t callback) + { + PopupManager.instance.Popup_Show("Joining Party"); + SteamMatchmaking.JoinLobby(callback.m_steamIDLobby); + } + + private void OnLobbyEntered(LobbyEnter_t callback) + { + //if lobby full leave + if (callback.m_bLocked) + { + SteamMatchmaking.LeaveLobby((CSteamID)callback.m_ulSteamIDLobby); + PopupManager.instance.Popup_Close(); + return; + } + + Debug.Log($"Entered Lobby {LobbyID}"); + LobbyID = new CSteamID(callback.m_ulSteamIDLobby); + + + if (NetworkServer.active) + return; + ((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(true); + + ((MyNetworkManager)NetworkManager.singleton).networkAddress = SteamMatchmaking.GetLobbyData(new CSteamID(LobbyID.m_SteamID), HOST_ADDRESS_KEY); + ((MyNetworkManager)NetworkManager.singleton).StartClient(); + } + #endregion + + public void Leave() + { + SteamMatchmaking.LeaveLobby(LobbyID); + } + + + public static void SetLobbyLocation() + { + SteamNetworkingUtils.GetLocalPingLocation(out SteamNetworkPingLocation_t pingLocation); + SteamNetworkingUtils.ConvertPingLocationToString(ref pingLocation, out string result, 1024); + SteamMatchmaking.SetLobbyData(LobbyID, "location", result); + } + + public void FindMatch() + { + StartCoroutine(FindMatchRoutine()); + } + + IEnumerator FindMatchRoutine() + { + PopupManager.instance.Popup_Show("Finding Match.."); + bool foundMatch = false; + + while (!foundMatch) + { + ReloadLobbyList(); + yield return new WaitForSeconds(1); + + foreach (var lobby in allLobbies) + { + if (SteamMatchmaking.GetNumLobbyMembers(lobby.lobbyID) < NetworkManager.singleton.maxConnections) + { + JoinLobby(lobby.lobbyID); + foundMatch = true; + } + } + } + PopupManager.instance.Popup_Close(); + + } +} + \ No newline at end of file diff --git a/Assets/Scripts/SteamLobby.cs.meta b/Assets/Scripts/SteamLobby.cs.meta new file mode 100644 index 0000000..27d71ab --- /dev/null +++ b/Assets/Scripts/SteamLobby.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 74a3fc7eda8dd2747bbcb9546db2aee3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Steamworks.NET.meta b/Assets/Scripts/Steamworks.NET.meta new file mode 100644 index 0000000..bbf13f6 --- /dev/null +++ b/Assets/Scripts/Steamworks.NET.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 62ddefd95a62cbc4ea1a2aabc009a378 +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Scripts/Steamworks.NET/SteamManager.cs b/Assets/Scripts/Steamworks.NET/SteamManager.cs new file mode 100644 index 0000000..63930c1 --- /dev/null +++ b/Assets/Scripts/Steamworks.NET/SteamManager.cs @@ -0,0 +1,182 @@ +// The SteamManager is designed to work with Steamworks.NET +// This file is released into the public domain. +// Where that dedication is not recognized you are granted a perpetual, +// irrevocable license to copy and modify this file as you see fit. +// +// Version: 1.0.13 + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +using UnityEngine; +#if !DISABLESTEAMWORKS +using System.Collections; +using Steamworks; +#endif + +// +// The SteamManager provides a base implementation of Steamworks.NET on which you can build upon. +// It handles the basics of starting up and shutting down the SteamAPI for use. +// +[DisallowMultipleComponent] +public class SteamManager : MonoBehaviour { +#if !DISABLESTEAMWORKS + protected static bool s_EverInitialized = false; + + protected static SteamManager s_instance; + protected static SteamManager Instance { + get { + if (s_instance == null) { + return new GameObject("SteamManager").AddComponent(); + } + else { + return s_instance; + } + } + } + + protected bool m_bInitialized = false; + public static bool Initialized { + get { + return Instance.m_bInitialized; + } + } + + protected SteamAPIWarningMessageHook_t m_SteamAPIWarningMessageHook; + + [AOT.MonoPInvokeCallback(typeof(SteamAPIWarningMessageHook_t))] + protected static void SteamAPIDebugTextHook(int nSeverity, System.Text.StringBuilder pchDebugText) { + Debug.LogWarning(pchDebugText); + } + +#if UNITY_2019_3_OR_NEWER + // In case of disabled Domain Reload, reset static members before entering Play Mode. + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] + private static void InitOnPlayMode() + { + s_EverInitialized = false; + s_instance = null; + } +#endif + + protected virtual void Awake() { + // Only one instance of SteamManager at a time! + if (s_instance != null) { + Destroy(gameObject); + return; + } + s_instance = this; + + if(s_EverInitialized) { + // This is almost always an error. + // The most common case where this happens is when SteamManager gets destroyed because of Application.Quit(), + // and then some Steamworks code in some other OnDestroy gets called afterwards, creating a new SteamManager. + // You should never call Steamworks functions in OnDestroy, always prefer OnDisable if possible. + throw new System.Exception("Tried to Initialize the SteamAPI twice in one session!"); + } + + // We want our SteamManager Instance to persist across scenes. + DontDestroyOnLoad(gameObject); + + if (!Packsize.Test()) { + Debug.LogError("[Steamworks.NET] Packsize Test returned false, the wrong version of Steamworks.NET is being run in this platform.", this); + } + + if (!DllCheck.Test()) { + Debug.LogError("[Steamworks.NET] DllCheck Test returned false, One or more of the Steamworks binaries seems to be the wrong version.", this); + } + + try { + // If Steam is not running or the game wasn't started through Steam, SteamAPI_RestartAppIfNecessary starts the + // Steam client and also launches this game again if the User owns it. This can act as a rudimentary form of DRM. + // Note that this will run which ever version you have installed in steam. Which may not be the precise executable + // we were currently running. + + // Once you get a Steam AppID assigned by Valve, you need to replace AppId_t.Invalid with it and + // remove steam_appid.txt from the game depot. eg: "(AppId_t)480" or "new AppId_t(480)". + // See the Valve documentation for more information: https://partner.steamgames.com/doc/sdk/api#initialization_and_shutdown + if (SteamAPI.RestartAppIfNecessary(AppId_t.Invalid)) { + Debug.Log("[Steamworks.NET] Shutting down because RestartAppIfNecessary returned true. Steam will restart the application."); + + Application.Quit(); + return; + } + } + catch (System.DllNotFoundException e) { // We catch this exception here, as it will be the first occurrence of it. + Debug.LogError("[Steamworks.NET] Could not load [lib]steam_api.dll/so/dylib. It's likely not in the correct location. Refer to the README for more details.\n" + e, this); + + Application.Quit(); + return; + } + + // Initializes the Steamworks API. + // If this returns false then this indicates one of the following conditions: + // [*] The Steam client isn't running. A running Steam client is required to provide implementations of the various Steamworks interfaces. + // [*] The Steam client couldn't determine the App ID of game. If you're running your application from the executable or debugger directly then you must have a [code-inline]steam_appid.txt[/code-inline] in your game directory next to the executable, with your app ID in it and nothing else. Steam will look for this file in the current working directory. If you are running your executable from a different directory you may need to relocate the [code-inline]steam_appid.txt[/code-inline] file. + // [*] Your application is not running under the same OS user context as the Steam client, such as a different user or administration access level. + // [*] Ensure that you own a license for the App ID on the currently active Steam account. Your game must show up in your Steam library. + // [*] Your App ID is not completely set up, i.e. in Release State: Unavailable, or it's missing default packages. + // Valve's documentation for this is located here: + // https://partner.steamgames.com/doc/sdk/api#initialization_and_shutdown + m_bInitialized = SteamAPI.Init(); + if (!m_bInitialized) { + Debug.LogError("[Steamworks.NET] SteamAPI_Init() failed. Refer to Valve's documentation or the comment above this line for more information.", this); + + return; + } + + s_EverInitialized = true; + } + + // This should only ever get called on first load and after an Assembly reload, You should never Disable the Steamworks Manager yourself. + protected virtual void OnEnable() { + if (s_instance == null) { + s_instance = this; + } + + if (!m_bInitialized) { + return; + } + + if (m_SteamAPIWarningMessageHook == null) { + // Set up our callback to receive warning messages from Steam. + // You must launch with "-debug_steamapi" in the launch args to receive warnings. + m_SteamAPIWarningMessageHook = new SteamAPIWarningMessageHook_t(SteamAPIDebugTextHook); + SteamClient.SetWarningMessageHook(m_SteamAPIWarningMessageHook); + } + } + + // OnApplicationQuit gets called too early to shutdown the SteamAPI. + // Because the SteamManager should be persistent and never disabled or destroyed we can shutdown the SteamAPI here. + // Thus it is not recommended to perform any Steamworks work in other OnDestroy functions as the order of execution can not be garenteed upon Shutdown. Prefer OnDisable(). + protected virtual void OnDestroy() { + if (s_instance != this) { + return; + } + + s_instance = null; + + if (!m_bInitialized) { + return; + } + + SteamAPI.Shutdown(); + } + + protected virtual void Update() { + if (!m_bInitialized) { + return; + } + + // Run Steam client callbacks + SteamAPI.RunCallbacks(); + } +#else + public static bool Initialized { + get { + return false; + } + } +#endif // !DISABLESTEAMWORKS +} diff --git a/Assets/Scripts/Steamworks.NET/SteamManager.cs.meta b/Assets/Scripts/Steamworks.NET/SteamManager.cs.meta new file mode 100644 index 0000000..9281178 --- /dev/null +++ b/Assets/Scripts/Steamworks.NET/SteamManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ef4bffeda13d7a748973ff9204401c07 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Scripts/Tools.meta b/Assets/Scripts/Tools.meta new file mode 100644 index 0000000..d6dbcc9 --- /dev/null +++ b/Assets/Scripts/Tools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 71fa19c60d0d2a6448a115315ee1d8a1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Tools/SceneSwitcher.cs b/Assets/Scripts/Tools/SceneSwitcher.cs new file mode 100644 index 0000000..18ba2f9 --- /dev/null +++ b/Assets/Scripts/Tools/SceneSwitcher.cs @@ -0,0 +1,78 @@ +#if UNITY_EDITOR + +using System.Linq; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.SceneManagement; + +public struct SceneInfo +{ + public string name; + public string path; + + public SceneInfo(string name, string path) + { + this.name = name; + this.path = path; + } +} + +[InitializeOnLoad] +public class SceneSwitcher : EditorWindow +{ + private static SceneInfo[] scenes; + private static int selectedSceneIndex = 0; + + static SceneSwitcher() + { + EditorApplication.update += UpdateSceneList; + EditorSceneManager.sceneOpened += SceneOpened; + } + + [MenuItem("Tools/Scene Switcher")] + static void ShowWindow() + { + GetWindow("Scene Switcher"); + } + + private static void UpdateSceneList() + { + int sceneCount = SceneManager.sceneCountInBuildSettings; + scenes = new SceneInfo[sceneCount]; + + for (int i = 0; i < sceneCount; i++) + { + string path = SceneUtility.GetScenePathByBuildIndex(i); + string name = System.IO.Path.GetFileNameWithoutExtension(path); + scenes[i] = new SceneInfo(name, path); + } + } + + private static void SceneOpened(Scene scene, OpenSceneMode mode) + { + UpdateSceneList(); + } + + private void OnGUI() + { + if (scenes != null && scenes.Length > 0) + { + selectedSceneIndex = EditorGUILayout.Popup("Switch Scene", selectedSceneIndex, scenes.Select(s => s.name).ToArray()); + + if (GUILayout.Button("Load Scene")) + { + if (selectedSceneIndex >= 0 && selectedSceneIndex < scenes.Length) + { + EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); + EditorSceneManager.OpenScene(scenes[selectedSceneIndex].path); + } + } + } + else + { + GUILayout.Label("No Scenes in Build Settings"); + } + } +} +#endif diff --git a/Assets/Scripts/Tools/SceneSwitcher.cs.meta b/Assets/Scripts/Tools/SceneSwitcher.cs.meta new file mode 100644 index 0000000..51b32bc --- /dev/null +++ b/Assets/Scripts/Tools/SceneSwitcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12cc48ad2517efa4ab8aa80c4353ef80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIElements.meta b/Assets/Scripts/UIElements.meta new file mode 100644 index 0000000..56fc689 --- /dev/null +++ b/Assets/Scripts/UIElements.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6ae0037d7e04d4b4281cf93ecc407525 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings.meta b/Assets/Settings.meta new file mode 100644 index 0000000..39b94dd --- /dev/null +++ b/Assets/Settings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 709f11a7f3c4041caa4ef136ea32d874 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/SampleSceneProfile.asset b/Assets/Settings/SampleSceneProfile.asset new file mode 100644 index 0000000..37e401d --- /dev/null +++ b/Assets/Settings/SampleSceneProfile.asset @@ -0,0 +1,123 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-7893295128165547882 +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: 0b2db86121404754db890f4c8dfe81b2, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + m_AdvancedMode: 0 + threshold: + m_OverrideState: 1 + m_Value: 1 + min: 0 + intensity: + m_OverrideState: 1 + m_Value: 1 + min: 0 + scatter: + m_OverrideState: 0 + m_Value: 0.7 + min: 0 + max: 1 + clamp: + m_OverrideState: 0 + m_Value: 65472 + min: 0 + tint: + m_OverrideState: 0 + m_Value: {r: 1, g: 1, b: 1, a: 1} + hdr: 0 + showAlpha: 0 + showEyeDropper: 1 + highQualityFiltering: + m_OverrideState: 0 + m_Value: 0 + skipIterations: + m_OverrideState: 0 + m_Value: 1 + min: 0 + max: 16 + dirtTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + dirtIntensity: + m_OverrideState: 0 + m_Value: 0 + min: 0 +--- !u!114 &-7011558710299706105 +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: 899c54efeace73346a0a16faa3afe726, type: 3} + m_Name: Vignette + m_EditorClassIdentifier: + active: 1 + m_AdvancedMode: 0 + color: + m_OverrideState: 0 + m_Value: {r: 0, g: 0, b: 0, a: 1} + hdr: 0 + showAlpha: 0 + showEyeDropper: 1 + center: + m_OverrideState: 0 + m_Value: {x: 0.5, y: 0.5} + intensity: + m_OverrideState: 1 + m_Value: 0.25 + min: 0 + max: 1 + smoothness: + m_OverrideState: 1 + m_Value: 0.4 + min: 0.01 + max: 1 + rounded: + m_OverrideState: 0 + m_Value: 0 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: SampleSceneProfile + m_EditorClassIdentifier: + components: + - {fileID: 849379129802519247} + - {fileID: -7893295128165547882} + - {fileID: -7011558710299706105} +--- !u!114 &849379129802519247 +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: 97c23e3b12dc18c42a140437e53d3951, type: 3} + m_Name: Tonemapping + m_EditorClassIdentifier: + active: 1 + m_AdvancedMode: 0 + mode: + m_OverrideState: 1 + m_Value: 1 diff --git a/Assets/Settings/SampleSceneProfile.asset.meta b/Assets/Settings/SampleSceneProfile.asset.meta new file mode 100644 index 0000000..f8cce64 --- /dev/null +++ b/Assets/Settings/SampleSceneProfile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a6560a915ef98420e9faacc1c7438823 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/URP-Balanced-Renderer.asset b/Assets/Settings/URP-Balanced-Renderer.asset new file mode 100644 index 0000000..20bd4d4 --- /dev/null +++ b/Assets/Settings/URP-Balanced-Renderer.asset @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-1878332245247344467 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: f62c9c65cf3354c93be831c8bc075510, type: 3} + m_Name: SSAO + m_EditorClassIdentifier: + m_Active: 1 + m_Shader: {fileID: 0} + m_Settings: + Downsample: 1 + AfterOpaque: 0 + Source: 0 + NormalSamples: 0 + Intensity: 0.5 + DirectLightingStrength: 0.25 + Radius: 0.25 + SampleCount: 4 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: URP-Balanced-Renderer + m_EditorClassIdentifier: + debugShaders: + debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, + type: 3} + m_RendererFeatures: + - {fileID: -1878332245247344467} + m_RendererFeatureMap: adc0de57c6d2eee5 + m_UseNativeRenderPass: 0 + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + shaders: + blitPS: {fileID: 4800000, guid: c17132b1f77d20942aa75f8429c0f8bc, type: 3} + copyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + screenSpaceShadowPS: {fileID: 0} + samplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + stencilDeferredPS: {fileID: 4800000, guid: e9155b26e1bc55942a41e518703fe304, type: 3} + fallbackErrorPS: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} + materialErrorPS: {fileID: 4800000, guid: 5fd9a8feb75a4b5894c241777f519d4e, type: 3} + coreBlitPS: {fileID: 0} + coreBlitColorAndDepthPS: {fileID: 0} + cameraMotionVector: {fileID: 0} + objectMotionVector: {fileID: 0} + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 2 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 1 + m_RenderingMode: 0 + m_DepthPrimingMode: 0 + m_AccurateGbufferNormals: 0 + m_ClusteredRendering: 0 + m_TileSize: 32 diff --git a/Assets/Settings/URP-Balanced-Renderer.asset.meta b/Assets/Settings/URP-Balanced-Renderer.asset.meta new file mode 100644 index 0000000..8fa7f17 --- /dev/null +++ b/Assets/Settings/URP-Balanced-Renderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e634585d5c4544dd297acaee93dc2beb +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/URP-Balanced.asset b/Assets/Settings/URP-Balanced.asset new file mode 100644 index 0000000..4adcfe8 --- /dev/null +++ b/Assets/Settings/URP-Balanced.asset @@ -0,0 +1,136 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: URP-Balanced + m_EditorClassIdentifier: + k_AssetVersion: 12 + k_AssetPreviousVersion: 12 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: e634585d5c4544dd297acaee93dc2beb, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsTerrainHoles: 1 + m_SupportsHDR: 1 + m_HDRColorBufferPrecision: 0 + m_MSAA: 1 + m_RenderScale: 1 + m_UpscalingFilter: 0 + m_FsrOverrideSharpness: 0 + m_FsrSharpness: 0.92 + m_EnableLODCrossFade: 1 + m_LODCrossFadeDitheringType: 1 + m_ShEvalMode: 0 + m_LightProbeSystem: 0 + m_ProbeVolumeMemoryBudget: 1024 + m_ProbeVolumeBlendingMemoryBudget: 256 + m_SupportProbeVolumeGPUStreaming: 0 + m_SupportProbeVolumeDiskStreaming: 0 + m_SupportProbeVolumeScenarios: 0 + m_SupportProbeVolumeScenarioBlending: 0 + m_ProbeVolumeSHBands: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 1024 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 2 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 512 + m_AdditionalLightsShadowResolutionTierLow: 128 + m_AdditionalLightsShadowResolutionTierMedium: 256 + m_AdditionalLightsShadowResolutionTierHigh: 512 + m_ReflectionProbeBlending: 0 + m_ReflectionProbeBoxProjection: 0 + m_ShadowDistance: 50 + m_ShadowCascadeCount: 1 + m_Cascade2Split: 0.25 + m_Cascade3Split: {x: 0.1, y: 0.3} + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_CascadeBorder: 0.1 + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_AnyShadowsSupported: 1 + m_SoftShadowsSupported: 1 + m_ConservativeEnclosingSphere: 0 + m_NumIterationsEnclosingSphere: 64 + m_SoftShadowQuality: 2 + m_AdditionalLightsCookieResolution: 512 + m_AdditionalLightsCookieFormat: 1 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_SupportsLightCookies: 1 + m_SupportsLightLayers: 0 + m_DebugLevel: 0 + m_StoreActionsOptimization: 0 + m_UseAdaptivePerformance: 1 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_AllowPostProcessAlphaOutput: 0 + m_UseFastSRGBLinearConversion: 0 + m_SupportDataDrivenLensFlare: 1 + m_SupportScreenSpaceLensFlare: 1 + m_GPUResidentDrawerMode: 0 + m_SmallMeshScreenPercentage: 0 + m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_VolumeFrameworkUpdateMode: 0 + m_VolumeProfile: {fileID: 0} + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + m_PrefilteringModeMainLightShadows: 1 + m_PrefilteringModeAdditionalLight: 4 + m_PrefilteringModeAdditionalLightShadows: 1 + m_PrefilterXRKeywords: 0 + m_PrefilteringModeForwardPlus: 1 + m_PrefilteringModeDeferredRendering: 1 + m_PrefilteringModeScreenSpaceOcclusion: 1 + m_PrefilterDebugKeywords: 0 + m_PrefilterWriteRenderingLayers: 0 + m_PrefilterHDROutput: 0 + m_PrefilterAlphaOutput: 0 + m_PrefilterSSAODepthNormals: 0 + m_PrefilterSSAOSourceDepthLow: 0 + m_PrefilterSSAOSourceDepthMedium: 0 + m_PrefilterSSAOSourceDepthHigh: 0 + m_PrefilterSSAOInterleaved: 0 + m_PrefilterSSAOBlueNoise: 0 + m_PrefilterSSAOSampleCountLow: 0 + m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOSampleCountHigh: 0 + m_PrefilterDBufferMRT1: 0 + m_PrefilterDBufferMRT2: 0 + m_PrefilterDBufferMRT3: 0 + m_PrefilterSoftShadowsQualityLow: 0 + m_PrefilterSoftShadowsQualityMedium: 0 + m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterSoftShadows: 0 + m_PrefilterScreenCoord: 0 + m_PrefilterNativeRenderPass: 0 + m_PrefilterUseLegacyLightmaps: 0 + m_ShaderVariantLogLevel: 0 + m_ShadowCascades: 0 + m_Textures: + blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} diff --git a/Assets/Settings/URP-Balanced.asset.meta b/Assets/Settings/URP-Balanced.asset.meta new file mode 100644 index 0000000..f524db0 --- /dev/null +++ b/Assets/Settings/URP-Balanced.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e1260c1148f6143b28bae5ace5e9c5d1 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/URP-HighFidelity-Renderer.asset b/Assets/Settings/URP-HighFidelity-Renderer.asset new file mode 100644 index 0000000..c02db2f --- /dev/null +++ b/Assets/Settings/URP-HighFidelity-Renderer.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-1878332245247344467 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: f62c9c65cf3354c93be831c8bc075510, type: 3} + m_Name: SSAO + m_EditorClassIdentifier: + m_Active: 1 + m_Settings: + AOMethod: 1 + Downsample: 0 + AfterOpaque: 0 + Source: 1 + NormalSamples: 1 + Intensity: 0.5 + DirectLightingStrength: 0.25 + Radius: 0.25 + Samples: 0 + BlurQuality: 0 + Falloff: 100 + SampleCount: -1 + m_BlueNoise256Textures: + - {fileID: 2800000, guid: 36f118343fc974119bee3d09e2111500, type: 3} + - {fileID: 2800000, guid: 4b7b083e6b6734e8bb2838b0b50a0bc8, type: 3} + - {fileID: 2800000, guid: c06cc21c692f94f5fb5206247191eeee, type: 3} + - {fileID: 2800000, guid: cb76dd40fa7654f9587f6a344f125c9a, type: 3} + - {fileID: 2800000, guid: e32226222ff144b24bf3a5a451de54bc, type: 3} + - {fileID: 2800000, guid: 3302065f671a8450b82c9ddf07426f3a, type: 3} + - {fileID: 2800000, guid: 56a77a3e8d64f47b6afe9e3c95cb57d5, type: 3} + m_Shader: {fileID: 4800000, guid: 0849e84e3d62649e8882e9d6f056a017, type: 3} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: URP-HighFidelity-Renderer + m_EditorClassIdentifier: + debugShaders: + debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, + type: 3} + hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3} + probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, + type: 3} + probeVolumeResources: + probeVolumeDebugShader: {fileID: 0} + probeVolumeFragmentationDebugShader: {fileID: 0} + probeVolumeOffsetDebugShader: {fileID: 0} + probeVolumeSamplingDebugShader: {fileID: 0} + probeSamplingDebugMesh: {fileID: 0} + probeSamplingDebugTexture: {fileID: 0} + probeVolumeBlendStatesCS: {fileID: 0} + m_RendererFeatures: + - {fileID: -1878332245247344467} + m_RendererFeatureMap: adc0de57c6d2eee5 + m_UseNativeRenderPass: 0 + xrSystemData: {fileID: 11400000, guid: 60e1133243b97e347b653163a8c01b64, type: 2} + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + m_AssetVersion: 2 + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 2 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 1 + m_RenderingMode: 0 + m_DepthPrimingMode: 0 + m_CopyDepthMode: 0 + m_DepthAttachmentFormat: 0 + m_DepthTextureFormat: 0 + m_AccurateGbufferNormals: 0 + m_IntermediateTextureMode: 1 diff --git a/Assets/Settings/URP-HighFidelity-Renderer.asset.meta b/Assets/Settings/URP-HighFidelity-Renderer.asset.meta new file mode 100644 index 0000000..bcdff02 --- /dev/null +++ b/Assets/Settings/URP-HighFidelity-Renderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c40be3174f62c4acf8c1216858c64956 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/URP-HighFidelity.asset b/Assets/Settings/URP-HighFidelity.asset new file mode 100644 index 0000000..8b270bf --- /dev/null +++ b/Assets/Settings/URP-HighFidelity.asset @@ -0,0 +1,136 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: URP-HighFidelity + m_EditorClassIdentifier: + k_AssetVersion: 12 + k_AssetPreviousVersion: 12 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: c40be3174f62c4acf8c1216858c64956, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsTerrainHoles: 1 + m_SupportsHDR: 1 + m_HDRColorBufferPrecision: 0 + m_MSAA: 4 + m_RenderScale: 1 + m_UpscalingFilter: 0 + m_FsrOverrideSharpness: 0 + m_FsrSharpness: 0.92 + m_EnableLODCrossFade: 1 + m_LODCrossFadeDitheringType: 1 + m_ShEvalMode: 0 + m_LightProbeSystem: 0 + m_ProbeVolumeMemoryBudget: 1024 + m_ProbeVolumeBlendingMemoryBudget: 256 + m_SupportProbeVolumeGPUStreaming: 0 + m_SupportProbeVolumeDiskStreaming: 0 + m_SupportProbeVolumeScenarios: 0 + m_SupportProbeVolumeScenarioBlending: 0 + m_ProbeVolumeSHBands: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 4096 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 8 + m_AdditionalLightShadowsSupported: 1 + m_AdditionalLightsShadowmapResolution: 4096 + m_AdditionalLightsShadowResolutionTierLow: 128 + m_AdditionalLightsShadowResolutionTierMedium: 256 + m_AdditionalLightsShadowResolutionTierHigh: 512 + m_ReflectionProbeBlending: 1 + m_ReflectionProbeBoxProjection: 1 + m_ShadowDistance: 150 + m_ShadowCascadeCount: 4 + m_Cascade2Split: 0.25 + m_Cascade3Split: {x: 0.1, y: 0.3} + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_CascadeBorder: 0.1 + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_AnyShadowsSupported: 1 + m_SoftShadowsSupported: 1 + m_ConservativeEnclosingSphere: 0 + m_NumIterationsEnclosingSphere: 64 + m_SoftShadowQuality: 2 + m_AdditionalLightsCookieResolution: 4096 + m_AdditionalLightsCookieFormat: 4 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_SupportsLightCookies: 1 + m_SupportsLightLayers: 0 + m_DebugLevel: 0 + m_StoreActionsOptimization: 0 + m_UseAdaptivePerformance: 1 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_AllowPostProcessAlphaOutput: 0 + m_UseFastSRGBLinearConversion: 0 + m_SupportDataDrivenLensFlare: 1 + m_SupportScreenSpaceLensFlare: 1 + m_GPUResidentDrawerMode: 0 + m_SmallMeshScreenPercentage: 0 + m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_VolumeFrameworkUpdateMode: 0 + m_VolumeProfile: {fileID: 0} + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + m_PrefilteringModeMainLightShadows: 1 + m_PrefilteringModeAdditionalLight: 4 + m_PrefilteringModeAdditionalLightShadows: 1 + m_PrefilterXRKeywords: 0 + m_PrefilteringModeForwardPlus: 1 + m_PrefilteringModeDeferredRendering: 1 + m_PrefilteringModeScreenSpaceOcclusion: 1 + m_PrefilterDebugKeywords: 0 + m_PrefilterWriteRenderingLayers: 0 + m_PrefilterHDROutput: 0 + m_PrefilterAlphaOutput: 0 + m_PrefilterSSAODepthNormals: 0 + m_PrefilterSSAOSourceDepthLow: 0 + m_PrefilterSSAOSourceDepthMedium: 0 + m_PrefilterSSAOSourceDepthHigh: 0 + m_PrefilterSSAOInterleaved: 0 + m_PrefilterSSAOBlueNoise: 0 + m_PrefilterSSAOSampleCountLow: 0 + m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOSampleCountHigh: 0 + m_PrefilterDBufferMRT1: 0 + m_PrefilterDBufferMRT2: 0 + m_PrefilterDBufferMRT3: 0 + m_PrefilterSoftShadowsQualityLow: 0 + m_PrefilterSoftShadowsQualityMedium: 0 + m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterSoftShadows: 0 + m_PrefilterScreenCoord: 0 + m_PrefilterNativeRenderPass: 0 + m_PrefilterUseLegacyLightmaps: 0 + m_ShaderVariantLogLevel: 0 + m_ShadowCascades: 1 + m_Textures: + blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} diff --git a/Assets/Settings/URP-HighFidelity.asset.meta b/Assets/Settings/URP-HighFidelity.asset.meta new file mode 100644 index 0000000..7416e17 --- /dev/null +++ b/Assets/Settings/URP-HighFidelity.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b7fd9122c28c4d15b667c7040e3b3fd +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/URP-Performant-Renderer.asset b/Assets/Settings/URP-Performant-Renderer.asset new file mode 100644 index 0000000..56c53f0 --- /dev/null +++ b/Assets/Settings/URP-Performant-Renderer.asset @@ -0,0 +1,52 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: URP-Performant-Renderer + m_EditorClassIdentifier: + debugShaders: + debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, + type: 3} + m_RendererFeatures: [] + m_RendererFeatureMap: + m_UseNativeRenderPass: 0 + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + shaders: + blitPS: {fileID: 4800000, guid: c17132b1f77d20942aa75f8429c0f8bc, type: 3} + copyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + screenSpaceShadowPS: {fileID: 0} + samplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + stencilDeferredPS: {fileID: 4800000, guid: e9155b26e1bc55942a41e518703fe304, type: 3} + fallbackErrorPS: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} + materialErrorPS: {fileID: 4800000, guid: 5fd9a8feb75a4b5894c241777f519d4e, type: 3} + coreBlitPS: {fileID: 0} + coreBlitColorAndDepthPS: {fileID: 0} + cameraMotionVector: {fileID: 0} + objectMotionVector: {fileID: 0} + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 2 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 1 + m_RenderingMode: 0 + m_DepthPrimingMode: 0 + m_AccurateGbufferNormals: 0 + m_ClusteredRendering: 0 + m_TileSize: 32 diff --git a/Assets/Settings/URP-Performant-Renderer.asset.meta b/Assets/Settings/URP-Performant-Renderer.asset.meta new file mode 100644 index 0000000..912ff60 --- /dev/null +++ b/Assets/Settings/URP-Performant-Renderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 707360a9c581a4bd7aa53bfeb1429f71 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/URP-Performant.asset b/Assets/Settings/URP-Performant.asset new file mode 100644 index 0000000..736d63b --- /dev/null +++ b/Assets/Settings/URP-Performant.asset @@ -0,0 +1,136 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: URP-Performant + m_EditorClassIdentifier: + k_AssetVersion: 12 + k_AssetPreviousVersion: 12 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: 707360a9c581a4bd7aa53bfeb1429f71, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsTerrainHoles: 1 + m_SupportsHDR: 0 + m_HDRColorBufferPrecision: 0 + m_MSAA: 1 + m_RenderScale: 1 + m_UpscalingFilter: 0 + m_FsrOverrideSharpness: 0 + m_FsrSharpness: 0.92 + m_EnableLODCrossFade: 1 + m_LODCrossFadeDitheringType: 1 + m_ShEvalMode: 0 + m_LightProbeSystem: 0 + m_ProbeVolumeMemoryBudget: 1024 + m_ProbeVolumeBlendingMemoryBudget: 256 + m_SupportProbeVolumeGPUStreaming: 0 + m_SupportProbeVolumeDiskStreaming: 0 + m_SupportProbeVolumeScenarios: 0 + m_SupportProbeVolumeScenarioBlending: 0 + m_ProbeVolumeSHBands: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 0 + m_MainLightShadowmapResolution: 1024 + m_AdditionalLightsRenderingMode: 0 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 512 + m_AdditionalLightsShadowResolutionTierLow: 128 + m_AdditionalLightsShadowResolutionTierMedium: 256 + m_AdditionalLightsShadowResolutionTierHigh: 512 + m_ReflectionProbeBlending: 0 + m_ReflectionProbeBoxProjection: 0 + m_ShadowDistance: 50 + m_ShadowCascadeCount: 1 + m_Cascade2Split: 0.25 + m_Cascade3Split: {x: 0.1, y: 0.3} + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_CascadeBorder: 0.1 + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_AnyShadowsSupported: 1 + m_SoftShadowsSupported: 0 + m_ConservativeEnclosingSphere: 0 + m_NumIterationsEnclosingSphere: 64 + m_SoftShadowQuality: 2 + m_AdditionalLightsCookieResolution: 2048 + m_AdditionalLightsCookieFormat: 3 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_SupportsLightCookies: 1 + m_SupportsLightLayers: 0 + m_DebugLevel: 0 + m_StoreActionsOptimization: 0 + m_UseAdaptivePerformance: 1 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 16 + m_AllowPostProcessAlphaOutput: 0 + m_UseFastSRGBLinearConversion: 0 + m_SupportDataDrivenLensFlare: 1 + m_SupportScreenSpaceLensFlare: 1 + m_GPUResidentDrawerMode: 0 + m_SmallMeshScreenPercentage: 0 + m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_VolumeFrameworkUpdateMode: 0 + m_VolumeProfile: {fileID: 0} + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + m_PrefilteringModeMainLightShadows: 1 + m_PrefilteringModeAdditionalLight: 4 + m_PrefilteringModeAdditionalLightShadows: 1 + m_PrefilterXRKeywords: 0 + m_PrefilteringModeForwardPlus: 1 + m_PrefilteringModeDeferredRendering: 1 + m_PrefilteringModeScreenSpaceOcclusion: 1 + m_PrefilterDebugKeywords: 0 + m_PrefilterWriteRenderingLayers: 0 + m_PrefilterHDROutput: 0 + m_PrefilterAlphaOutput: 0 + m_PrefilterSSAODepthNormals: 0 + m_PrefilterSSAOSourceDepthLow: 0 + m_PrefilterSSAOSourceDepthMedium: 0 + m_PrefilterSSAOSourceDepthHigh: 0 + m_PrefilterSSAOInterleaved: 0 + m_PrefilterSSAOBlueNoise: 0 + m_PrefilterSSAOSampleCountLow: 0 + m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOSampleCountHigh: 0 + m_PrefilterDBufferMRT1: 0 + m_PrefilterDBufferMRT2: 0 + m_PrefilterDBufferMRT3: 0 + m_PrefilterSoftShadowsQualityLow: 0 + m_PrefilterSoftShadowsQualityMedium: 0 + m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterSoftShadows: 0 + m_PrefilterScreenCoord: 0 + m_PrefilterNativeRenderPass: 0 + m_PrefilterUseLegacyLightmaps: 0 + m_ShaderVariantLogLevel: 0 + m_ShadowCascades: 0 + m_Textures: + blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} diff --git a/Assets/Settings/URP-Performant.asset.meta b/Assets/Settings/URP-Performant.asset.meta new file mode 100644 index 0000000..264c9c5 --- /dev/null +++ b/Assets/Settings/URP-Performant.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0e2fc18fe036412f8223b3b3d9ad574 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro.meta b/Assets/TextMesh Pro.meta new file mode 100644 index 0000000..f9da8b5 --- /dev/null +++ b/Assets/TextMesh Pro.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f54d1bd14bd3ca042bd867b519fee8cc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Documentation.meta b/Assets/TextMesh Pro/Documentation.meta new file mode 100644 index 0000000..afa527a --- /dev/null +++ b/Assets/TextMesh Pro/Documentation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8e7e8f5a82a3a134e91c54efd2274ea9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Documentation/TextMesh Pro User Guide 2016.pdf b/Assets/TextMesh Pro/Documentation/TextMesh Pro User Guide 2016.pdf new file mode 100644 index 0000000..c2ea2d2 Binary files /dev/null and b/Assets/TextMesh Pro/Documentation/TextMesh Pro User Guide 2016.pdf differ diff --git a/Assets/TextMesh Pro/Documentation/TextMesh Pro User Guide 2016.pdf.meta b/Assets/TextMesh Pro/Documentation/TextMesh Pro User Guide 2016.pdf.meta new file mode 100644 index 0000000..e4afeef --- /dev/null +++ b/Assets/TextMesh Pro/Documentation/TextMesh Pro User Guide 2016.pdf.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1b8d251f9af63b746bf2f7ffe00ebb9b +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras.meta b/Assets/TextMesh Pro/Examples & Extras.meta new file mode 100644 index 0000000..d94c9b5 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce51c8e33b734b4db6086586558c53a3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts.meta new file mode 100644 index 0000000..37020f0 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b63e0053080646b9819789bf3bf9fa17 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton OFL.txt b/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton OFL.txt new file mode 100644 index 0000000..0ad6de5 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton OFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2011, Vernon Adams (vern@newtypography.co.uk), +with Reserved Font Name Anton. +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton OFL.txt.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton OFL.txt.meta new file mode 100644 index 0000000..7963e08 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton OFL.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 73a79399807f4e8388c2cbb5494681ca +timeCreated: 1484172033 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton.ttf b/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton.ttf new file mode 100644 index 0000000..4ef73dc Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton.ttf differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton.ttf.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton.ttf.meta new file mode 100644 index 0000000..1375b4a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Anton.ttf.meta @@ -0,0 +1,19 @@ +fileFormatVersion: 2 +guid: 997a43b767814dd0a7642ec9b78cba41 +timeCreated: 1484172033 +licenseType: Pro +TrueTypeFontImporter: + serializedVersion: 2 + fontSize: 16 + forceTextureCase: -2 + characterSpacing: 1 + characterPadding: 0 + includeFontData: 1 + use2xBehaviour: 0 + fontNames: [] + fallbackFontReferences: [] + customCharacters: + fontRenderingMode: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers - OFL.txt b/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers - OFL.txt new file mode 100644 index 0000000..13e7fbe --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers - OFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2010 by vernon adams (vern@newtypography.co.uk), +with Reserved Font Name Bangers. +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers - OFL.txt.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers - OFL.txt.meta new file mode 100644 index 0000000..c1a298c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers - OFL.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: efe0bf4ac872451e91612d1ae593f480 +timeCreated: 1484171296 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers.ttf b/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers.ttf new file mode 100644 index 0000000..477dfc3 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers.ttf differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers.ttf.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers.ttf.meta new file mode 100644 index 0000000..cd243dc --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Bangers.ttf.meta @@ -0,0 +1,19 @@ +fileFormatVersion: 2 +guid: 5dd49b3eacc540408c98eee0de38e0f1 +timeCreated: 1484171297 +licenseType: Pro +TrueTypeFontImporter: + serializedVersion: 2 + fontSize: 16 + forceTextureCase: -2 + characterSpacing: 1 + characterPadding: 0 + includeFontData: 1 + use2xBehaviour: 0 + fontNames: [] + fallbackFontReferences: [] + customCharacters: + fontRenderingMode: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Electronic Highway Sign.TTF b/Assets/TextMesh Pro/Examples & Extras/Fonts/Electronic Highway Sign.TTF new file mode 100644 index 0000000..16c1059 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Fonts/Electronic Highway Sign.TTF differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Electronic Highway Sign.TTF.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Electronic Highway Sign.TTF.meta new file mode 100644 index 0000000..0668b8d --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Electronic Highway Sign.TTF.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 8a2b9e2a607dd2143b58c44bc32410b4 +TrueTypeFontImporter: + externalObjects: {} + serializedVersion: 4 + fontSize: 16 + forceTextureCase: -2 + characterSpacing: 0 + characterPadding: 1 + includeFontData: 1 + fontName: Electronic Highway Sign + fontNames: + - Electronic Highway Sign + fallbackFontReferences: [] + customCharacters: + fontRenderingMode: 0 + ascentCalculationMode: 1 + useLegacyBoundsCalculation: 0 + shouldRoundAdvanceValue: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold - OFL.txt b/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold - OFL.txt new file mode 100644 index 0000000..22bdace --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold - OFL.txt @@ -0,0 +1,92 @@ +Copyright (c) 2011-2012, Vernon Adams (vern@newtypography.co.uk), with Reserved Font Names 'Oswald' +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold - OFL.txt.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold - OFL.txt.meta new file mode 100644 index 0000000..99b230f --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold - OFL.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d2cf87a8a7a94aa8b80dff1c807c1178 +timeCreated: 1484171296 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold.ttf b/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold.ttf new file mode 100644 index 0000000..a77a3d0 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold.ttf differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold.ttf.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold.ttf.meta new file mode 100644 index 0000000..f14340b --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Oswald-Bold.ttf.meta @@ -0,0 +1,19 @@ +fileFormatVersion: 2 +guid: c9f6d0e7bc8541498c9a4799ba184ede +timeCreated: 1484171297 +licenseType: Pro +TrueTypeFontImporter: + serializedVersion: 2 + fontSize: 16 + forceTextureCase: -2 + characterSpacing: 1 + characterPadding: 0 + includeFontData: 1 + use2xBehaviour: 0 + fontNames: [] + fallbackFontReferences: [] + customCharacters: + fontRenderingMode: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - AFL.txt b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - AFL.txt new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - AFL.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - AFL.txt.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - AFL.txt.meta new file mode 100644 index 0000000..be89a11 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - AFL.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f28c334d44214474d9702d3ad79ecb0a +timeCreated: 1484171296 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - License.txt b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - License.txt new file mode 100644 index 0000000..4b1096f --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - License.txt @@ -0,0 +1,3 @@ +This font is licensed under the Apache License, Version 2.0. + +See the following link for full licensing terms https://www.apache.org/licenses/LICENSE-2.0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - License.txt.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - License.txt.meta new file mode 100644 index 0000000..42f2c8c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold - License.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f0303f887b8fa7243a51432c478ff2f3 +timeCreated: 1484171296 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold.ttf b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold.ttf new file mode 100644 index 0000000..d3f01ad Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold.ttf differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold.ttf.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold.ttf.meta new file mode 100644 index 0000000..4f36d75 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Roboto-Bold.ttf.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 4beb055f07aaff244873dec698d0363e +TrueTypeFontImporter: + externalObjects: {} + serializedVersion: 4 + fontSize: 16 + forceTextureCase: -2 + characterSpacing: 0 + characterPadding: 1 + includeFontData: 1 + fontName: Roboto + fontNames: + - Roboto + fallbackFontReferences: [] + customCharacters: + fontRenderingMode: 0 + ascentCalculationMode: 1 + useLegacyBoundsCalculation: 0 + shouldRoundAdvanceValue: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity - OFL.txt b/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity - OFL.txt new file mode 100644 index 0000000..f131937 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity - OFL.txt @@ -0,0 +1,92 @@ +Copyright (c) 2020-2021, Unity, with Reserved Font Names 'Unity' +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity - OFL.txt.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity - OFL.txt.meta new file mode 100644 index 0000000..f1df76f --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity - OFL.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0251f66ebc602a944b35bccd13be2738 +timeCreated: 1484171296 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity.ttf b/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity.ttf new file mode 100644 index 0000000..82f106a Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity.ttf differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity.ttf.meta b/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity.ttf.meta new file mode 100644 index 0000000..e7fa283 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Fonts/Unity.ttf.meta @@ -0,0 +1,21 @@ +fileFormatVersion: 2 +guid: f4eec857a4fdf2f43be0e9f3d1a984e7 +TrueTypeFontImporter: + externalObjects: {} + serializedVersion: 4 + fontSize: 16 + forceTextureCase: -2 + characterSpacing: 0 + characterPadding: 1 + includeFontData: 1 + fontNames: + - Unity + fallbackFontReferences: [] + customCharacters: + fontRenderingMode: 0 + ascentCalculationMode: 1 + useLegacyBoundsCalculation: 0 + shouldRoundAdvanceValue: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials.meta b/Assets/TextMesh Pro/Examples & Extras/Materials.meta new file mode 100644 index 0000000..dbedf7c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5808953df7a24274a851aa6dee52d30e +folderAsset: yes +timeCreated: 1436068007 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - Surface Shader Scene.mat b/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - Surface Shader Scene.mat new file mode 100644 index 0000000..330b9fb --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - Surface Shader Scene.mat @@ -0,0 +1,84 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Crate - Surface Shader Scene + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _EMISSION _NORMALMAP _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 8878a782f4334ecbbcf683b3ac780966, type: 3} + 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: 602cb87b6a29443b8636370ea0751574, 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} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 0.5 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _EmissionScaleUI: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.233 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 1 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 0.712} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColorUI: {r: 1, g: 1, b: 1, a: 1} + - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - Surface Shader Scene.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - Surface Shader Scene.mat.meta new file mode 100644 index 0000000..5b4e12d --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - Surface Shader Scene.mat.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: e6b9b44320f4448d9d5e0ee634259966 +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - URP.mat b/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - URP.mat new file mode 100644 index 0000000..3194d55 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - URP.mat @@ -0,0 +1,138 @@ +%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: Crate - URP + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _EMISSION + - _NORMALMAP + m_InvalidKeywords: [] + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 2800000, guid: 602cb87b6a29443b8636370ea0751574, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 8878a782f4334ecbbcf683b3ac780966, type: 3} + 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: 602cb87b6a29443b8636370ea0751574, 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} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 0.5 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 1 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 1, g: 1, b: 1, a: 0.7137255} + - _Color: {r: 1, g: 1, b: 1, a: 0.7137255} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &7626160506639672020 +MonoBehaviour: + m_ObjectHideFlags: 11 + 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: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 9 diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - URP.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - URP.mat.meta new file mode 100644 index 0000000..dbdaff3 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Crate - URP.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3b5cc91c3bf8cf74391252247f52fb59 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Logo Scene.mat b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Logo Scene.mat new file mode 100644 index 0000000..8315530 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Logo Scene.mat @@ -0,0 +1,207 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Ground - Logo Scene + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _NORMALMAP + m_LightmapFlags: 5 + m_CustomRenderQueue: -1 + stringTagMap: {} + m_SavedProperties: + serializedVersion: 2 + m_TexEnvs: + data: + first: + name: _MainTex + second: + m_Texture: {fileID: 2800000, guid: 1cdc5b506b1a4a33a53c30669ced1f51, type: 3} + m_Scale: {x: 20, y: 20} + m_Offset: {x: 0, y: 0} + data: + first: + name: _BumpMap + second: + m_Texture: {fileID: 2800000, guid: 8b8c8a10edf94ddc8cc4cc4fcd5696a9, type: 3} + m_Scale: {x: 30, y: 50} + m_Offset: {x: 0, y: 0} + data: + first: + name: _DetailNormalMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _ParallaxMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _OcclusionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _EmissionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _DetailMask + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _DetailAlbedoMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _MetallicGlossMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _BorderTex + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _FillTex + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + data: + first: + name: _EdgeTex + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + data: + first: + name: _SrcBlend + second: 1 + data: + first: + name: _DstBlend + second: 0 + data: + first: + name: _Radius + second: 0 + data: + first: + name: _Cutoff + second: .5 + data: + first: + name: _Shininess + second: .220354751 + data: + first: + name: _Parallax + second: .0199999996 + data: + first: + name: _ZWrite + second: 1 + data: + first: + name: _Glossiness + second: .344000012 + data: + first: + name: _BumpScale + second: 1 + data: + first: + name: _OcclusionStrength + second: 1 + data: + first: + name: _DetailNormalMapScale + second: 1 + data: + first: + name: _UVSec + second: 0 + data: + first: + name: _Mode + second: 0 + data: + first: + name: _Metallic + second: 0 + data: + first: + name: _EmissionScaleUI + second: 0 + data: + first: + name: _EdgeSoftness + second: 0 + data: + first: + name: _DiffusePower + second: 1 + data: + first: + name: _Border + second: .0214285739 + data: + first: + name: _Size + second: .100000001 + data: + first: + name: _EdgeWidth + second: 0 + m_Colors: + data: + first: + name: _EmissionColor + second: {r: 0, g: 0, b: 0, a: 0} + data: + first: + name: _Color + second: {r: 1, g: 1, b: 1, a: 1} + data: + first: + name: _SpecColor + second: {r: .5, g: .5, b: .5, a: 1} + data: + first: + name: _EmissionColorUI + second: {r: 1, g: 1, b: 1, a: 1} + data: + first: + name: _FaceColor + second: {r: 1, g: 1, b: 1, a: 1} + data: + first: + name: _BorderColor + second: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Logo Scene.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Logo Scene.mat.meta new file mode 100644 index 0000000..c8a274c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Logo Scene.mat.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: c719e38f25a9480abd2480ab621a2949 +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Surface Shader Scene.mat b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Surface Shader Scene.mat new file mode 100644 index 0000000..79fceba --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Surface Shader Scene.mat @@ -0,0 +1,112 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Ground - Surface Shader Scene + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _EMISSION + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BorderTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 2800000, guid: c45cd05946364f32aba704f0853a975b, type: 3} + m_Scale: {x: 10, y: 10} + 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} + - _DetailTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EdgeTex: + 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} + - _FillTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 85ac55597b97403c82fc6601a93cf241, type: 3} + m_Scale: {x: 5, y: 5} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Border: 0.021428574 + - _BumpScale: 0.25 + - _ColorMask: 15 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DiffusePower: 1 + - _DstBlend: 0 + - _EdgeSoftness: 0 + - _EdgeWidth: 0 + - _EmissionScaleUI: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.348 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _Radius: 0 + - _Shininess: 0.24302611 + - _Size: 0.1 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _Strength: 0.2 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _BorderColor: {r: 0, g: 0, b: 0, a: 1} + - _Color: {r: 1, g: 1, b: 1, a: 0.8784314} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColorUI: {r: 1, g: 1, b: 1, a: 1} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _SpecColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Surface Shader Scene.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Surface Shader Scene.mat.meta new file mode 100644 index 0000000..73ed8ec --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Surface Shader Scene.mat.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: aadd5a709a48466c887296bb5b1b8110 +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - URP.mat b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - URP.mat new file mode 100644 index 0000000..a2ee26e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - URP.mat @@ -0,0 +1,173 @@ +%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: Ground - URP + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _EMISSION + m_InvalidKeywords: [] + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 2800000, guid: 85ac55597b97403c82fc6601a93cf241, type: 3} + m_Scale: {x: 5, y: 5} + m_Offset: {x: 0, y: 0} + - _BorderTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 2800000, guid: c45cd05946364f32aba704f0853a975b, type: 3} + m_Scale: {x: 10, y: 10} + 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} + - _DetailTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EdgeTex: + 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} + - _FillTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 85ac55597b97403c82fc6601a93cf241, type: 3} + m_Scale: {x: 5, y: 5} + 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} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _Border: 0.021428574 + - _BumpScale: 0.25 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _ColorMask: 15 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DiffusePower: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EdgeSoftness: 0 + - _EdgeWidth: 0 + - _EmissionScaleUI: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 1 + - _Glossiness: 0.348 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _QueueOffset: 0 + - _Radius: 0 + - _ReceiveShadows: 1 + - _Shininess: 0.24302611 + - _Size: 0.1 + - _Smoothness: 0.348 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _Strength: 0.2 + - _Surface: 0 + - _UVSec: 0 + - _WorkflowMode: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} + - _BorderColor: {r: 0, g: 0, b: 0, a: 1} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColorUI: {r: 1, g: 1, b: 1, a: 1} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _SpecColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &8510939975645199906 +MonoBehaviour: + m_ObjectHideFlags: 11 + 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: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 9 diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - URP.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - URP.mat.meta new file mode 100644 index 0000000..97fc3d6 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - URP.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 71529b88994c1a341b22bc57c038674a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Small Crate_diffuse.mat b/Assets/TextMesh Pro/Examples & Extras/Materials/Small Crate_diffuse.mat new file mode 100644 index 0000000..e9fafdd --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Small Crate_diffuse.mat @@ -0,0 +1,127 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Small Crate_diffuse + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _EMISSION _NORMALMAP + m_LightmapFlags: 1 + m_CustomRenderQueue: -1 + stringTagMap: {} + m_SavedProperties: + serializedVersion: 2 + m_TexEnvs: + - first: + name: _BumpMap + second: + m_Texture: {fileID: 2800000, guid: 8878a782f4334ecbbcf683b3ac780966, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailAlbedoMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailMask + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailNormalMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _EmissionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MainTex + second: + m_Texture: {fileID: 2800000, guid: 602cb87b6a29443b8636370ea0751574, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MetallicGlossMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _OcclusionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _ParallaxMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - first: + name: _BumpScale + second: 1 + - first: + name: _Cutoff + second: 0.5 + - first: + name: _DetailNormalMapScale + second: 1 + - first: + name: _DstBlend + second: 0 + - first: + name: _GlossMapScale + second: 1 + - first: + name: _Glossiness + second: 0.5 + - first: + name: _GlossyReflections + second: 1 + - first: + name: _Metallic + second: 0 + - first: + name: _Mode + second: 0 + - first: + name: _OcclusionStrength + second: 1 + - first: + name: _Parallax + second: 0.02 + - first: + name: _SmoothnessTextureChannel + second: 0 + - first: + name: _SpecularHighlights + second: 1 + - first: + name: _SrcBlend + second: 1 + - first: + name: _UVSec + second: 0 + - first: + name: _ZWrite + second: 1 + m_Colors: + - first: + name: _Color + second: {r: 1, g: 1, b: 1, a: 1} + - first: + name: _EmissionColor + second: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Materials/Small Crate_diffuse.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Materials/Small Crate_diffuse.mat.meta new file mode 100644 index 0000000..a85f800 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Small Crate_diffuse.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 22262639920f43d6be32430e4e58350d +timeCreated: 1473643741 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Prefabs.meta b/Assets/TextMesh Pro/Examples & Extras/Prefabs.meta new file mode 100644 index 0000000..4881085 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Prefabs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5bff2544887143f5807c7d5059d07f79 +folderAsset: yes +timeCreated: 1436068007 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Prefabs/Text Popup.prefab b/Assets/TextMesh Pro/Examples & Extras/Prefabs/Text Popup.prefab new file mode 100644 index 0000000..873b789 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Prefabs/Text Popup.prefab @@ -0,0 +1,280 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &121924 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 4 + m_Component: + - 224: {fileID: 22414422} + - 222: {fileID: 22260028} + - 114: {fileID: 11487728} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &188050 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 4 + m_Component: + - 224: {fileID: 22450954} + - 222: {fileID: 22204918} + - 114: {fileID: 11486278} + - 114: {fileID: 11427010} + - 114: {fileID: 11405862} + - 225: {fileID: 22524478} + m_Layer: 0 + m_Name: Text Popup + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &11405862 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 188050} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 2 + m_VerticalFit: 2 +--- !u!114 &11427010 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 188050} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 10 + m_Bottom: 10 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 +--- !u!114 &11486278 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 188050} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.10542818, g: 0.21589755, b: 0.47794116, a: 0.9411765} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!114 &11487728 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 121924} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Sample + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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_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_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 6 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &22204918 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 188050} +--- !u!222 &22260028 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 121924} +--- !u!224 &22414422 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 121924} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 22450954} + m_RootOrder: 0 + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &22450954 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 188050} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 22414422} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!225 &22524478 +CanvasGroup: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 188050} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 0 + m_BlocksRaycasts: 0 + m_IgnoreParentGroups: 0 +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 188050} + m_IsPrefabParent: 1 diff --git a/Assets/TextMesh Pro/Examples & Extras/Prefabs/Text Popup.prefab.meta b/Assets/TextMesh Pro/Examples & Extras/Prefabs/Text Popup.prefab.meta new file mode 100644 index 0000000..5c11316 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Prefabs/Text Popup.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b06f0e6c1dfa4356ac918da1bb32c603 +timeCreated: 1435130987 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 1.prefab b/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 1.prefab new file mode 100644 index 0000000..0f01d97 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 1.prefab @@ -0,0 +1,219 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &100000 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 22495902} + - component: {fileID: 3300000} + - component: {fileID: 2300000} + - component: {fileID: 11400000} + - component: {fileID: 22227760} + m_Layer: 0 + m_Name: TextMeshPro - Prefab 1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &2300000 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &3300000 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_Mesh: {fileID: 0} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + 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_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Seems to be ok! + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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_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_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 0 + m_isAlignmentEnumConverted: 0 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 0 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 11400000} + characterCount: 15 + spriteCount: 0 + spaceCount: 3 + wordCount: 4 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 2300000} + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_maskType: 0 +--- !u!222 &22227760 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} +--- !u!224 &22495902 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -4.87} + m_SizeDelta: {x: 28.005241, y: 4.035484} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 100000} + m_IsPrefabParent: 1 diff --git a/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 1.prefab.meta b/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 1.prefab.meta new file mode 100644 index 0000000..91fe0ae --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 1.prefab.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: a6e39ced0ea046bcb636c3f0b2e2a745 +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 2.prefab b/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 2.prefab new file mode 100644 index 0000000..54a5247 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 2.prefab @@ -0,0 +1,219 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &100000 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 22478072} + - component: {fileID: 3300000} + - component: {fileID: 2300000} + - component: {fileID: 11400000} + - component: {fileID: 22224556} + m_Layer: 0 + m_Name: TextMeshPro - Prefab 2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &2300000 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &3300000 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_Mesh: {fileID: 0} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + 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_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Hello World! + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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_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_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 0 + m_isAlignmentEnumConverted: 0 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 0 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 11400000} + characterCount: 12 + spriteCount: 0 + spaceCount: 1 + wordCount: 2 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 2300000} + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_maskType: 0 +--- !u!222 &22224556 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} +--- !u!224 &22478072 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100000} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 4.48} + m_SizeDelta: {x: 19.604034, y: 4.035484} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 100000} + m_IsPrefabParent: 1 diff --git a/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 2.prefab.meta b/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 2.prefab.meta new file mode 100644 index 0000000..1d941f5 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Prefabs/TextMeshPro - Prefab 2.prefab.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: fdad9d952ae84cafb74c63f2e694d042 +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources.meta b/Assets/TextMesh Pro/Examples & Extras/Resources.meta new file mode 100644 index 0000000..8ba2a4c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d6d3a169ad794942a21da6a552d62f6f +folderAsset: yes +timeCreated: 1436068007 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets.meta new file mode 100644 index 0000000..69552ee --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7f422cd1388b01047a58cd07c7a23d9d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Blue to Purple - Vertical.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Blue to Purple - Vertical.asset new file mode 100644 index 0000000..9758a19 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Blue to Purple - Vertical.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 54d21f6ece3b46479f0c328f8c6007e0, type: 3} + m_Name: Blue to Purple - Vertical + m_EditorClassIdentifier: + topLeft: {r: 0, g: 0.83448267, b: 1, a: 1} + topRight: {r: 0.1544118, g: 0.5801215, b: 1, a: 1} + bottomLeft: {r: 0.49168324, g: 0, b: 0.7058823, a: 1} + bottomRight: {r: 0.4901961, g: 0, b: 0.7019608, a: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Blue to Purple - Vertical.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Blue to Purple - Vertical.asset.meta new file mode 100644 index 0000000..9d49b87 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Blue to Purple - Vertical.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 479a66fa4b094512a62b0a8e553ad95a +timeCreated: 1468189245 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Dark to Light Green - Vertical.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Dark to Light Green - Vertical.asset new file mode 100644 index 0000000..21ada73 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Dark to Light Green - Vertical.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 54d21f6ece3b46479f0c328f8c6007e0, type: 3} + m_Name: Dark to Light Green - Vertical + m_EditorClassIdentifier: + topLeft: {r: 0, g: .661764741, b: 0, a: 1} + topRight: {r: 0, g: .573529422, b: .00224910071, a: 1} + bottomLeft: {r: .525490224, g: 1, b: .490196109, a: 1} + bottomRight: {r: .421999991, g: .992156923, b: .374000013, a: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Dark to Light Green - Vertical.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Dark to Light Green - Vertical.asset.meta new file mode 100644 index 0000000..228a49e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Dark to Light Green - Vertical.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4c86a3366cd840348ebe8dc438570ee4 +timeCreated: 1468443381 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Light to Dark Green - Vertical.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Light to Dark Green - Vertical.asset new file mode 100644 index 0000000..8c4ab99 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Light to Dark Green - Vertical.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 54d21f6ece3b46479f0c328f8c6007e0, type: 3} + m_Name: Light to Dark Green - Vertical + m_EditorClassIdentifier: + topLeft: {r: 0.5147059, g: 1, b: 0.5147059, a: 1} + topRight: {r: 0.5137255, g: 1, b: 0.5137255, a: 1} + bottomLeft: {r: 0, g: 0.46323532, b: 0, a: 1} + bottomRight: {r: 0, g: 0.46274513, b: 0, a: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Light to Dark Green - Vertical.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Light to Dark Green - Vertical.asset.meta new file mode 100644 index 0000000..d521412 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Light to Dark Green - Vertical.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5cf8ae092ca54931b443bec5148f3c59 +timeCreated: 1468443381 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Yellow to Orange - Vertical.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Yellow to Orange - Vertical.asset new file mode 100644 index 0000000..e99de77 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Yellow to Orange - Vertical.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 54d21f6ece3b46479f0c328f8c6007e0, type: 3} + m_Name: Yellow to Orange - Vertical + m_EditorClassIdentifier: + topLeft: {r: 1, g: 1, b: 0.5661765, a: 1} + topRight: {r: 1, g: 1, b: 0.252, a: 1} + bottomLeft: {r: 1, g: 0, b: 0, a: 1} + bottomRight: {r: 1, g: 0, b: 0, a: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Yellow to Orange - Vertical.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Yellow to Orange - Vertical.asset.meta new file mode 100644 index 0000000..b09bb84 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Color Gradient Presets/Yellow to Orange - Vertical.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 69a525efa7e6472eab268f6ea605f06e +timeCreated: 1468213165 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials.meta new file mode 100644 index 0000000..846e80b --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4f1e85c79acf49968737939ce8b445c7 +folderAsset: yes +timeCreated: 1436068007 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Drop Shadow.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Drop Shadow.mat new file mode 100644 index 0000000..0f87ce3 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Drop Shadow.mat @@ -0,0 +1,104 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Anton SDF - Drop Shadow + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28933816116536082, guid: 8a89fa14b10d46a99122fd4f73fca9a2, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0.1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.6770833 + - _ScaleRatioC: 0.64125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.5 + - _UnderlayOffsetY: -0.5 + - _UnderlaySoftness: 0.05 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Drop Shadow.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Drop Shadow.mat.meta new file mode 100644 index 0000000..fd5bcfa --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Drop Shadow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 749b9069dc4742c5bfa5c74644049926 +timeCreated: 1484173523 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Outline.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Outline.mat new file mode 100644 index 0000000..b4b58ea --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Outline.mat @@ -0,0 +1,104 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Anton SDF - Outline + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28933816116536082, guid: 8a89fa14b10d46a99122fd4f73fca9a2, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0.1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.8333333 + - _ScaleRatioB: 0.6770833 + - _ScaleRatioC: 0.59375 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Outline.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Outline.mat.meta new file mode 100644 index 0000000..b3b0386 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Outline.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a00013af81304728b2be1f4309ee2433 +timeCreated: 1484173536 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Sunny Days.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Sunny Days.mat new file mode 100644 index 0000000..3fb2b9a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Sunny Days.mat @@ -0,0 +1,104 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Anton SDF - Sunny Days + m_Shader: {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3} + m_ShaderKeywords: BEVEL_ON UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 2800000, guid: 17c350171f7a3ca479f830547c66d187, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: -0.15} + - _MainTex: + m_Texture: {fileID: 28933816116536082, guid: 8a89fa14b10d46a99122fd4f73fca9a2, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 2800000, guid: 1cdc5b506b1a4a33a53c30669ced1f51, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.25 + - _BevelClamp: 0.345 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0.1 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.15 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.7875 + - _ScaleRatioC: 0.7875 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 1 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.75 + - _UnderlayOffsetY: -0.75 + - _UnderlaySoftness: 0.1 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.5 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0.5882353, g: 0.5882353, b: 0.5882353, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 0.9921569, g: 0.90196085, b: 0.40000004, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Sunny Days.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Sunny Days.mat.meta new file mode 100644 index 0000000..d5b9684 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF - Sunny Days.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6522f30e342599e4e9dd4cc2cc03c830 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF.asset new file mode 100644 index 0000000..868c4bb --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF.asset @@ -0,0 +1,318 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2140474 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Anton SDF Material + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28933816116536082} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.6770833 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: Anton SDF + m_EditorClassIdentifier: + m_Version: 1.1.0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: Anton + m_StyleName: Regular + m_PointSize: 90 + m_Scale: 1 + m_UnitsPerEM: 2048 + m_LineHeight: 132.05566 + m_AscentLine: 102.43652 + m_CapLine: 70 + m_MeanLine: 66 + m_Baseline: 0 + m_DescentLine: -29.61914 + m_SuperscriptOffset: 102.43652 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -29.61914 + m_SubscriptSize: 0.5 + m_UnderlineOffset: -13.491211 + m_UnderlineThickness: 4.482422 + m_StrikethroughOffset: 26.4 + m_StrikethroughThickness: 4.482422 + m_TabWidth: 21 + m_Material: {fileID: 2140474} + m_SourceFontFileGUID: 997a43b767814dd0a7642ec9b78cba41 + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: 997a43b767814dd0a7642ec9b78cba41 + faceIndex: 0 + pointSizeSamplingMode: 1 + pointSize: 90 + padding: 9 + paddingMode: 0 + packingMode: 4 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 6 + characterSequence: + referencedFontAssetGUID: 8a89fa14b10d46a99122fd4f73fca9a2 + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4165 + includeFontFeatures: 0 + m_SourceFontFile: {fileID: 12800000, guid: 997a43b767814dd0a7642ec9b78cba41, type: 3} + m_SourceFontFilePath: + m_AtlasPopulationMode: 1 + InternalDynamicOS: 0 + m_GlyphTable: [] + m_CharacterTable: [] + m_AtlasTextures: + - {fileID: 28933816116536082} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_GetFontFeatures: 1 + m_ClearDynamicDataOnBuild: 1 + m_AtlasWidth: 1024 + m_AtlasHeight: 1024 + m_AtlasPadding: 9 + m_AtlasRenderMode: 4165 + m_UsedGlyphRects: [] + m_FreeGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 1023 + m_Height: 1023 + m_FontFeatureTable: + m_MultipleSubstitutionRecords: [] + m_LigatureSubstitutionRecords: [] + m_GlyphPairAdjustmentRecords: [] + m_MarkToBaseAdjustmentRecords: [] + m_MarkToMarkAdjustmentRecords: [] + m_ShouldReimportFontFeatures: 0 + m_FallbackFontAssetTable: [] + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 + m_fontInfo: + Name: Anton + PointSize: 73 + Scale: 1 + CharacterCount: 97 + LineHeight: 107.125 + Baseline: 0 + Ascender: 83.09375 + CapHeight: 56.8125 + Descender: -24.03125 + CenterLine: 0 + SuperscriptOffset: 83.09375 + SubscriptOffset: -10.942871 + SubSize: 0.5 + Underline: -10.942871 + UnderlineThickness: 3.6357422 + strikethrough: 22.725 + strikethroughThickness: 0 + TabWidth: 171.25 + Padding: 5 + AtlasWidth: 512 + AtlasHeight: 512 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + fallbackFontAssets: [] + atlas: {fileID: 0} +--- !u!28 &28933816116536082 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Anton SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_IsAlphaChannelOptional: 0 + serializedVersion: 3 + m_Width: 1 + m_Height: 1 + m_CompleteImageSize: 1 + m_MipsStripped: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 1 + m_IsPreProcessed: 0 + m_IgnoreMipmapLimit: 0 + m_MipmapLimitGroupName: + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_VTOnly: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + m_PlatformBlob: + image data: 1 + _typelessdata: 00 + m_StreamData: + serializedVersion: 2 + offset: 0 + size: 0 + path: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF.asset.meta new file mode 100644 index 0000000..c5163c0 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8a89fa14b10d46a99122fd4f73fca9a2 +timeCreated: 1484172732 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow - 2 Pass.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow - 2 Pass.mat new file mode 100644 index 0000000..f4d4d49 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow - 2 Pass.mat @@ -0,0 +1,112 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Bangers SDF - Drop Shadow - 2 Pass + m_Shader: {fileID: 4800000, guid: 0178fcb869bafef4690d177d31d17db8, type: 3} + m_ShaderKeywords: OUTLINE_ON UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28584486757587946, guid: 125cb55b44b24c4393181402bc6200e6, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 11 + - _LightAngle: 3.1416 + - _MaskID: 0 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.4 + - _PerspectiveFilter: 0 + - _Reflectivity: 10 + - _ScaleRatioA: 0.90909094 + - _ScaleRatioB: 1 + - _ScaleRatioC: 0.60843194 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.789 + - _UnderlayOffsetY: -0.777 + - _UnderlaySoftness: 0.425 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -10000, g: -10000, b: 10000, a: 10000} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 100000, a: 100000} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.7529412} + m_BuildTextureStacks: [] diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow - 2 Pass.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow - 2 Pass.mat.meta new file mode 100644 index 0000000..b8cb642 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow - 2 Pass.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 947a44964e53bf0448ff698b2a2219c0 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow.mat new file mode 100644 index 0000000..2c5a35d --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow.mat @@ -0,0 +1,110 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Bangers SDF - Drop Shadow + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28584486757587946, guid: 125cb55b44b24c4393181402bc6200e6, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 11 + - _LightAngle: 3.1416 + - _MaskID: 0 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.15 + - _PerspectiveFilter: 0 + - _Reflectivity: 10 + - _ScaleRatioA: 0.90909094 + - _ScaleRatioB: 1 + - _ScaleRatioC: 0.7386364 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.289 + - _UnderlayOffsetY: -0.478 + - _UnderlaySoftness: 0.068 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -10000, g: -10000, b: 10000, a: 10000} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 100000, a: 100000} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.7529412} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow.mat.meta new file mode 100644 index 0000000..6506858 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Drop Shadow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f2dcf029949142e28b974630369c8b4e +timeCreated: 1444812175 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Outline.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Outline.mat new file mode 100644 index 0000000..096979b --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Outline.mat @@ -0,0 +1,110 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Bangers SDF - Outline + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28584486757587946, guid: 125cb55b44b24c4393181402bc6200e6, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 11 + - _LightAngle: 3.1416 + - _MaskID: 0 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.15 + - _PerspectiveFilter: 0 + - _Reflectivity: 10 + - _ScaleRatioA: 0.90909094 + - _ScaleRatioB: 1 + - _ScaleRatioC: 0.79545456 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -10000, g: -10000, b: 10000, a: 10000} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 100000, a: 100000} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5019608} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Outline.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Outline.mat.meta new file mode 100644 index 0000000..c046bb7 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF - Outline.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f629c6e43dba4bf38cb74d8860150664 +timeCreated: 1455497618 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Glow.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Glow.mat new file mode 100644 index 0000000..1055340 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Glow.mat @@ -0,0 +1,113 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Bangers SDF Glow + m_Shader: {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3} + m_ShaderKeywords: GLOW_ON UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 2800000, guid: 2ce5c55e85304b819a1826ecbc839aa5, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28584486757587946, guid: 125cb55b44b24c4393181402bc6200e6, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0.1 + - _FaceShininess: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.148 + - _GlowOffset: 0.433 + - _GlowOuter: 0.158 + - _GlowPower: 0.908 + - _GradientScale: 11 + - _LightAngle: 3.1416 + - _MaskID: 0 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineShininess: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.21 + - _PerspectiveFilter: 0 + - _Reflectivity: 10 + - _ScaleRatioA: 0.90909094 + - _ScaleRatioB: 0.64772725 + - _ScaleRatioC: 0.64772725 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.869 + - _UnderlayOffsetY: -1 + - _UnderlaySoftness: 0 + - _UseClipRect: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -10000, g: -10000, b: 10000, a: 10000} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 1} + - _MaskCoord: {r: 0, g: 0, b: 100000, a: 100000} + - _OutlineColor: {r: 0, g: 0.25517216, b: 1, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 1, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Glow.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Glow.mat.meta new file mode 100644 index 0000000..80d1050 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Glow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d75b8f41e959450c84ac6e967084d3e1 +timeCreated: 1426033972 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo - URP.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo - URP.mat new file mode 100644 index 0000000..5f8002f --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo - URP.mat @@ -0,0 +1,151 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-5083544279399351042 +MonoBehaviour: + m_ObjectHideFlags: 11 + 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: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 9 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Bangers SDF Logo - URP + m_Shader: {fileID: -6465566751694194690, guid: a3d800b099a06e0478fb790c5e79057a, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: + - GLOW_ON + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 8b8c8a10edf94ddc8cc4cc4fcd5696a9, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 8900000, guid: f8caea216d5e7af42872b30cd96a235f, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 2800000, guid: 283f897e4925411ebbaa758b4cb13fc2, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28584486757587946, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 2800000, guid: 1cdc5b506b1a4a33a53c30669ced1f51, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Ambient: 0.094 + - _Bevel: 0.461 + - _BevelAmount: 0.385 + - _BevelClamp: 0 + - _BevelOffset: -0.271 + - _BevelRoundness: 0.825 + - _BevelType: 0 + - _BevelWidth: 0.287 + - _BumpFace: 0 + - _BumpOutline: 0 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0.2 + - _FaceShininess: 1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.076 + - _GlowOffset: 0.354 + - _GlowOuter: 0.336 + - _GlowPower: 0.75 + - _GradientScale: 11 + - _LightAngle: 2.83 + - _MaskID: 0 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineMode: 0 + - _OutlineShininess: 1 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.4 + - _PerspectiveFilter: 0.875 + - _QueueControl: -1 + - _QueueOffset: 0 + - _Reflectivity: 6.94 + - _ScaleRatioA: 0.90909094 + - _ScaleRatioB: 0.5568182 + - _ScaleRatioC: 0.90909094 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _FaceUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _GlowColor: {r: 1, g: 0.6344826, b: 0, a: 0.5019608} + - _IsoPerimeter: {r: -0.6, g: 0, b: 0.428, a: 0} + - _MaskCoord: {r: 0, g: 0, b: 0, a: 0} + - _OutlineColor: {r: 1, g: 1, b: 1, a: 1} + - _OutlineColor1: {r: 1, g: 1, b: 1, a: 1} + - _OutlineColor2: {r: 0.95979345, g: 1, b: 0.007843137, a: 1} + - _OutlineColor3: {r: 0, g: 0, b: 0, a: 1} + - _OutlineOffset1: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset2: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset3: {r: 0, g: 0, b: 0, a: 0} + - _OutlineUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _Softness: {r: 0, g: 0, b: 0, a: 0} + - _SpecColor: {r: 1, g: 1, b: 1, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + - _UnderlayOffset: {r: 0, g: 0, b: 0, a: 0} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo - URP.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo - URP.mat.meta new file mode 100644 index 0000000..bd96db4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo - URP.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6751ce1a4611b3940812c13a6847d94f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo.mat new file mode 100644 index 0000000..35e68ac --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo.mat @@ -0,0 +1,101 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Bangers SDF Logo + m_Shader: {fileID: 4800000, guid: f7ada0af4f174f0694ca6a487b8f543d, type: 3} + m_ShaderKeywords: GLOW_ON + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 8b8c8a10edf94ddc8cc4cc4fcd5696a9, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 8900000, guid: f8caea216d5e7af42872b30cd96a235f, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 2800000, guid: 283f897e4925411ebbaa758b4cb13fc2, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28584486757587946, guid: 125cb55b44b24c4393181402bc6200e6, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 2800000, guid: 1cdc5b506b1a4a33a53c30669ced1f51, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.461 + - _BevelClamp: 0 + - _BevelOffset: -0.09 + - _BevelRoundness: 0.615 + - _BevelWidth: 0.001 + - _BumpFace: 0 + - _BumpOutline: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0.2 + - _FaceShininess: 1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.076 + - _GlowOffset: 0.354 + - _GlowOuter: 0.336 + - _GlowPower: 0.75 + - _GradientScale: 11 + - _LightAngle: 3.142 + - _MaskID: 0 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineShininess: 1 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.4 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.90909094 + - _ScaleRatioB: 0.5568182 + - _ScaleRatioC: 0.90909094 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 1, g: 0.6344826, b: 0, a: 0.5019608} + - _MaskCoord: {r: 0, g: 0, b: 0, a: 0} + - _OutlineColor: {r: 1, g: 1, b: 1, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 1, g: 1, b: 1, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo.mat.meta new file mode 100644 index 0000000..7bf03ca --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF Logo.mat.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: f4e195ac1e204eff960149d1cb34e18c +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF.asset new file mode 100644 index 0000000..91a29e1 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF.asset @@ -0,0 +1,302 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Bangers SDF Material + m_Shader: {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28584486757587946} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 11 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.90909094 + - _ScaleRatioB: 0.79545456 + - _ScaleRatioC: 0.79545456 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.5 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: Bangers SDF + m_EditorClassIdentifier: + m_Version: 1.1.0 + m_Material: {fileID: 2100000} + m_SourceFontFileGUID: 5dd49b3eacc540408c98eee0de38e0f1 + m_SourceFontFile: {fileID: 12800000, guid: 5dd49b3eacc540408c98eee0de38e0f1, type: 3} + m_AtlasPopulationMode: 1 + InternalDynamicOS: 0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: Bangers + m_StyleName: Regular + m_PointSize: 144 + m_Scale: 1 + m_UnitsPerEM: 2048 + m_LineHeight: 153.14062 + m_AscentLine: 127.125 + m_CapLine: 107 + m_MeanLine: 106 + m_Baseline: 0 + m_DescentLine: -26.015625 + m_SuperscriptOffset: 127.125 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -26.015625 + m_SubscriptSize: 0.5 + m_UnderlineOffset: 0 + m_UnderlineThickness: 0 + m_StrikethroughOffset: 42.4 + m_StrikethroughThickness: 0 + m_TabWidth: 28 + m_GlyphTable: [] + m_CharacterTable: [] + m_AtlasTextures: + - {fileID: 28584486757587946} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_ClearDynamicDataOnBuild: 1 + m_UsedGlyphRects: [] + m_FreeGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 1023 + m_Height: 1023 + m_fontInfo: + Name: Bangers + PointSize: 137 + Scale: 1 + CharacterCount: 95 + LineHeight: 145.6875 + Baseline: 0 + Ascender: 120.9375 + CapHeight: 101.5625 + Descender: -24.75 + CenterLine: 0 + SuperscriptOffset: 120.9375 + SubscriptOffset: 0 + SubSize: 0.5 + Underline: -12.22 + UnderlineThickness: 5 + strikethrough: 40.625 + strikethroughThickness: 0 + TabWidth: 342.5 + Padding: 10 + AtlasWidth: 1024 + AtlasHeight: 1024 + atlas: {fileID: 0} + m_AtlasWidth: 1024 + m_AtlasHeight: 1024 + m_AtlasPadding: 10 + m_AtlasRenderMode: 4165 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_MultipleSubstitutionRecords: [] + m_LigatureSubstitutionRecords: [] + m_GlyphPairAdjustmentRecords: [] + m_MarkToBaseAdjustmentRecords: [] + m_MarkToMarkAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: 5dd49b3eacc540408c98eee0de38e0f1 + faceIndex: 0 + pointSizeSamplingMode: 1 + pointSize: 144 + padding: 10 + paddingMode: 0 + packingMode: 4 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 6 + characterSequence: + referencedFontAssetGUID: 125cb55b44b24c4393181402bc6200e6 + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4165 + includeFontFeatures: 0 + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 +--- !u!28 &28584486757587946 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Bangers SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + serializedVersion: 2 + m_Width: 0 + m_Height: 0 + m_CompleteImageSize: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 1 + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + image data: 0 + _typelessdata: + m_StreamData: + offset: 0 + size: 0 + path: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF.asset.meta new file mode 100644 index 0000000..321c943 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF.asset.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: 125cb55b44b24c4393181402bc6200e6 +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Electronic Highway Sign SDF.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Electronic Highway Sign SDF.asset new file mode 100644 index 0000000..e1c585a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Electronic Highway Sign SDF.asset @@ -0,0 +1,302 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2140032 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Electronic Highway Sign SDF Material + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28981121099961358} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 11 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.90909094 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.7386364 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: Electronic Highway Sign SDF + m_EditorClassIdentifier: + m_Version: 1.1.0 + m_Material: {fileID: 2140032} + m_SourceFontFileGUID: 8a2b9e2a607dd2143b58c44bc32410b4 + m_SourceFontFile: {fileID: 12800000, guid: 8a2b9e2a607dd2143b58c44bc32410b4, type: 3} + m_AtlasPopulationMode: 1 + InternalDynamicOS: 0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: Electronic Highway Sign + m_StyleName: Regular + m_PointSize: 144 + m_Scale: 1 + m_UnitsPerEM: 2048 + m_LineHeight: 146.57143 + m_AscentLine: 123.42857 + m_CapLine: 115 + m_MeanLine: 115 + m_Baseline: 0 + m_DescentLine: -23.142857 + m_SuperscriptOffset: 123.42857 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -23.142857 + m_SubscriptSize: 0.5 + m_UnderlineOffset: -14.708571 + m_UnderlineThickness: 2.0571427 + m_StrikethroughOffset: 46 + m_StrikethroughThickness: 2.0571427 + m_TabWidth: 88 + m_GlyphTable: [] + m_CharacterTable: [] + m_AtlasTextures: + - {fileID: 28981121099961358} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_ClearDynamicDataOnBuild: 1 + m_UsedGlyphRects: [] + m_FreeGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 1023 + m_Height: 1023 + m_fontInfo: + Name: Electronic Highway Sign + PointSize: 144 + Scale: 1 + CharacterCount: 95 + LineHeight: 168 + Baseline: 0 + Ascender: 123.4375 + CapHeight: 115.1875 + Descender: -23.15625 + CenterLine: 0 + SuperscriptOffset: 123.4375 + SubscriptOffset: -14.708571 + SubSize: 0.5 + Underline: -14.708571 + UnderlineThickness: 2.057143 + strikethrough: 36.465908 + strikethroughThickness: 2.057143 + TabWidth: 881.5625 + Padding: 9 + AtlasWidth: 1024 + AtlasHeight: 1024 + atlas: {fileID: 0} + m_AtlasWidth: 1024 + m_AtlasHeight: 1024 + m_AtlasPadding: 10 + m_AtlasRenderMode: 4165 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_MultipleSubstitutionRecords: [] + m_LigatureSubstitutionRecords: [] + m_GlyphPairAdjustmentRecords: [] + m_MarkToBaseAdjustmentRecords: [] + m_MarkToMarkAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: 8a2b9e2a607dd2143b58c44bc32410b4 + faceIndex: 0 + pointSizeSamplingMode: 1 + pointSize: 144 + padding: 10 + paddingMode: 0 + packingMode: 4 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 6 + characterSequence: + referencedFontAssetGUID: 8f586378b4e144a9851e7b34d9b748ee + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4165 + includeFontFeatures: 1 + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 +--- !u!28 &28981121099961358 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Electronic Highway Sign SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + serializedVersion: 2 + m_Width: 0 + m_Height: 0 + m_CompleteImageSize: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 1 + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + image data: 0 + _typelessdata: + m_StreamData: + offset: 0 + size: 0 + path: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Electronic Highway Sign SDF.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Electronic Highway Sign SDF.asset.meta new file mode 100644 index 0000000..fab93db --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Electronic Highway Sign SDF.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc36b3fdc14f47ebb36fd484a67e268a +timeCreated: 1487729771 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Metalic Green.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Metalic Green.mat new file mode 100644 index 0000000..28601cd --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Metalic Green.mat @@ -0,0 +1,104 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF - Metalic Green + m_Shader: {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3} + m_ShaderKeywords: BEVEL_ON GLOW_ON OUTLINE_ON UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 2800000, guid: 283f897e4925411ebbaa758b4cb13fc2, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 2800000, guid: f88677df267a41d6be1e7a6133e7d227, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0 + - _Bevel: 1 + - _BevelClamp: 0.617 + - _BevelOffset: -0.01 + - _BevelRoundness: 1 + - _BevelWidth: 0.071 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0 + - _FaceDilate: 0.15 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.136 + - _GlowOffset: 0.427 + - _GlowOuter: 0.062 + - _GlowPower: 0.941 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.219 + - _PerspectiveFilter: 0 + - _Reflectivity: 12.76 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.6525 + - _ScaleRatioC: 0.6525 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.5 + - _UnderlayOffsetY: -0.5 + - _UnderlaySoftness: 0.2 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -10000, g: -10000, b: 10000, a: 10000} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 0, g: 0.75735635, b: 0, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 100000, a: 100000} + - _OutlineColor: {r: 1, g: 1, b: 1, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 0.7689687, g: 1, b: 0.75000346, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Metalic Green.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Metalic Green.mat.meta new file mode 100644 index 0000000..44020ae --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Metalic Green.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8b29aaa3eec7468097ff07adfcf29ac9 +timeCreated: 1484213182 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Overlay.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Overlay.mat new file mode 100644 index 0000000..fc5c217 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Overlay.mat @@ -0,0 +1,62 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF - Overlay + m_Shader: {fileID: 4800000, guid: a02a7d8c237544f1962732b55a9aebf1, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _ColorMask: 15 + - _FaceDilate: 0 + - _GradientScale: 10 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 1 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Overlay.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Overlay.mat.meta new file mode 100644 index 0000000..6a07ee9 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Overlay.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9ad269c99dcf42b7aedefd83dd5a7b9d +timeCreated: 1484174016 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Soft Mask.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Soft Mask.mat new file mode 100644 index 0000000..f08b09e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Soft Mask.mat @@ -0,0 +1,112 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF - Soft Mask + m_Shader: {fileID: 4800000, guid: bc1ede39bf3643ee8e493720e4259791, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MaskTex: + m_Texture: {fileID: 2800000, guid: 10c49fcd9c64421db7c0133e61e55f97, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskEdgeSoftness: 0.044 + - _MaskInverse: 1 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _MaskWipeControl: 0.321 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _MaskEdgeColor: {r: 0.18382353, g: 0.39208913, b: 1, a: 1} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Soft Mask.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Soft Mask.mat.meta new file mode 100644 index 0000000..c907d8a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/LiberationSans SDF - Soft Mask.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 42df1c7856584b6b8db9a509b6b10074 +timeCreated: 1484173785 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Oswald Bold SDF.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Oswald Bold SDF.asset new file mode 100644 index 0000000..f295819 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Oswald Bold SDF.asset @@ -0,0 +1,302 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2147374 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Oswald Bold SDF Material + m_Shader: {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28256370963634744} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: Oswald Bold SDF + m_EditorClassIdentifier: + m_Version: 1.1.0 + m_Material: {fileID: 2147374} + m_SourceFontFileGUID: c9f6d0e7bc8541498c9a4799ba184ede + m_SourceFontFile: {fileID: 12800000, guid: c9f6d0e7bc8541498c9a4799ba184ede, type: 3} + m_AtlasPopulationMode: 1 + InternalDynamicOS: 0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: Oswald + m_StyleName: Bold + m_PointSize: 90 + m_Scale: 1 + m_UnitsPerEM: 2048 + m_LineHeight: 133.37402 + m_AscentLine: 107.40234 + m_CapLine: 80 + m_MeanLine: 58 + m_Baseline: 0 + m_DescentLine: -25.97168 + m_SuperscriptOffset: 107.40234 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -25.97168 + m_SubscriptSize: 0.5 + m_UnderlineOffset: -13.491211 + m_UnderlineThickness: 4.482422 + m_StrikethroughOffset: 23.2 + m_StrikethroughThickness: 4.482422 + m_TabWidth: 18 + m_GlyphTable: [] + m_CharacterTable: [] + m_AtlasTextures: + - {fileID: 28256370963634744} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_ClearDynamicDataOnBuild: 1 + m_UsedGlyphRects: [] + m_FreeGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 1023 + m_Height: 1023 + m_fontInfo: + Name: Oswald + PointSize: 71 + Scale: 1 + CharacterCount: 97 + LineHeight: 105.21875 + Baseline: 0 + Ascender: 84.71875 + CapHeight: 62.40625 + Descender: -20.5 + CenterLine: 0 + SuperscriptOffset: 84.71875 + SubscriptOffset: -10.643066 + SubSize: 0.5 + Underline: -10.643066 + UnderlineThickness: 3.5361328 + strikethrough: 24.9625 + strikethroughThickness: 0 + TabWidth: 142.1875 + Padding: 5 + AtlasWidth: 512 + AtlasHeight: 512 + atlas: {fileID: 0} + m_AtlasWidth: 1024 + m_AtlasHeight: 1024 + m_AtlasPadding: 9 + m_AtlasRenderMode: 4165 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_MultipleSubstitutionRecords: [] + m_LigatureSubstitutionRecords: [] + m_GlyphPairAdjustmentRecords: [] + m_MarkToBaseAdjustmentRecords: [] + m_MarkToMarkAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: c9f6d0e7bc8541498c9a4799ba184ede + faceIndex: 0 + pointSizeSamplingMode: 1 + pointSize: 90 + padding: 9 + paddingMode: 0 + packingMode: 4 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 6 + characterSequence: 20-7E,A0,2026 + referencedFontAssetGUID: 0161d805a3764c089bef00bfe00793f5 + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4165 + includeFontFeatures: 0 + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 +--- !u!28 &28256370963634744 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Oswald Bold SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + serializedVersion: 2 + m_Width: 0 + m_Height: 0 + m_CompleteImageSize: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 1 + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + image data: 0 + _typelessdata: + m_StreamData: + offset: 0 + size: 0 + path: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Oswald Bold SDF.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Oswald Bold SDF.asset.meta new file mode 100644 index 0000000..d2d5e66 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Oswald Bold SDF.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0161d805a3764c089bef00bfe00793f5 +timeCreated: 1484171878 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Drop Shadow.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Drop Shadow.mat new file mode 100644 index 0000000..fa14395 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Drop Shadow.mat @@ -0,0 +1,104 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Roboto-Bold SDF - Drop Shadow + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28204114720316640, guid: 5302535af1044152a457ed104f1f4b91, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0.1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.64125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.5 + - _UnderlayOffsetY: -0.5 + - _UnderlaySoftness: 0.1 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Drop Shadow.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Drop Shadow.mat.meta new file mode 100644 index 0000000..15402ea --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Drop Shadow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b246c4190f4e46ec9352fe15a7b09ce0 +timeCreated: 1487723245 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - HDRP Unlit.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - HDRP Unlit.mat new file mode 100644 index 0000000..27a2fd0 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - HDRP Unlit.mat @@ -0,0 +1,191 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Roboto-Bold SDF - HDRP Unlit + m_Shader: {fileID: -6465566751694194690, guid: f63d574838ccfb44f84acc05fed0af48, type: 3} + m_ShaderKeywords: _ALPHATEST_ON _ENABLE_FOG_ON_TRANSPARENT _SURFACE_TYPE_TRANSPARENT + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 2750 + stringTagMap: + MotionVector: User + RenderType: Transparent + disabledShaderPasses: + - TransparentDepthPrepass + - TransparentDepthPostpass + - TransparentBackface + - MOTIONVECTORS + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 2800000, guid: 6eb184de103d4b3f812b38561065192f, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28204114720316640, guid: 5302535af1044152a457ed104f1f4b91, type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaCutoffEnable: 1 + - _AlphaDstBlend: 10 + - _AlphaSrcBlend: 1 + - _AlphaToMask: 0 + - _AlphaToMaskInspectorValue: 0 + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelAmount: 0.25 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelType: 0 + - _BevelWidth: 0 + - _BlendMode: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 2 + - _CullModeForward: 2 + - _DepthOffsetEnable: 0 + - _Diffuse: 0.5 + - _DoubleSidedEnable: 0 + - _DoubleSidedNormalMode: 2 + - _DstBlend: 10 + - _EnableBlendModePreserveSpecularLighting: 0 + - _EnableFogOnTransparent: 1 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OpaqueCullMode: 2 + - _OutlineMode: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _RenderQueueType: 3 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _SrcBlend: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilRef: 0 + - _StencilRefDepth: 0 + - _StencilRefDistortionVec: 4 + - _StencilRefGBuffer: 2 + - _StencilRefMV: 32 + - _StencilWriteMask: 6 + - _StencilWriteMaskDepth: 8 + - _StencilWriteMaskDistortionVec: 4 + - _StencilWriteMaskGBuffer: 14 + - _StencilWriteMaskMV: 40 + - _SurfaceType: 1 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _TransparentBackfaceEnable: 0 + - _TransparentCullMode: 2 + - _TransparentDepthPostpassEnable: 0 + - _TransparentDepthPrepassEnable: 0 + - _TransparentSortPriority: 0 + - _TransparentWritingMotionVec: 0 + - _TransparentZWrite: 1 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _UseShadowThreshold: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + - _ZTestDepthEqualForOpaque: 4 + - _ZTestGBuffer: 3 + - _ZTestTransparent: 4 + - _ZWrite: 1 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0} + - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _FaceUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _IsoPerimeter: {r: 0, g: 0.1, b: 0.3, a: 0} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _OutlineColor1: {r: 0, g: 1, b: 1, a: 1} + - _OutlineColor2: {r: 0, g: 0, b: 0, a: 1} + - _OutlineColor3: {r: 0, g: 0, b: 0, a: 1} + - _OutlineOffset1: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset2: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset3: {r: 0, g: 0, b: 0, a: 0} + - _OutlineUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _Softness: {r: 0, g: 0, b: 0, a: 0} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + - _UnderlayOffset: {r: 0, g: 0, b: 0, a: 0} + m_BuildTextureStacks: [] +--- !u!114 &8695414737614723888 +MonoBehaviour: + m_ObjectHideFlags: 11 + 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: da692e001514ec24dbc4cca1949ff7e8, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 11 diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - HDRP Unlit.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - HDRP Unlit.mat.meta new file mode 100644 index 0000000..29c918d --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - HDRP Unlit.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2ddca8f46aa0838419d568affb0ca6b4 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Surface.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Surface.mat new file mode 100644 index 0000000..e159990 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Surface.mat @@ -0,0 +1,107 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Roboto-Bold SDF - Surface + m_Shader: {fileID: 4800000, guid: 85187c2149c549c5b33f0cdb02836b17, type: 3} + m_ShaderKeywords: UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28204114720316640, guid: 5302535af1044152a457ed104f1f4b91, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0.1 + - _FaceShininess: 0.8 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0.19 + - _GlowOuter: 0.905 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineShininess: 0 + - _OutlineSoftness: 0.017 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.5856164 + - _ScaleRatioC: 0.83076924 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.5 + - _UnderlayOffsetY: -0.5 + - _UnderlaySoftness: 0.1 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 0.3793165, b: 1, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Surface.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Surface.mat.meta new file mode 100644 index 0000000..80e1f1a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - Surface.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e6b276ec991f467aa14ef1f3cc665993 +timeCreated: 1487723313 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - URP.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - URP.mat new file mode 100644 index 0000000..8c77694 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - URP.mat @@ -0,0 +1,157 @@ +%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: Roboto-Bold SDF - URP + m_Shader: {fileID: -6465566751694194690, guid: a3d800b099a06e0478fb790c5e79057a, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: + - UNDERLAY_ON + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28204114720316640, guid: 5302535af1044152a457ed104f1f4b91, type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelAmount: 0 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelType: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0.1 + - _FaceShininess: 0.8 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0.19 + - _GlowOuter: 0.905 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineMode: 0 + - _OutlineShininess: 0 + - _OutlineSoftness: 0.017 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _QueueControl: -1 + - _QueueOffset: 0 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.5856164 + - _ScaleRatioC: 0.83076924 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.5 + - _UnderlayOffsetY: -0.5 + - _UnderlaySoftness: 0.1 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _FaceUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _GlowColor: {r: 0, g: 0.3793165, b: 1, a: 0.5} + - _IsoPerimeter: {r: 0, g: 0, b: 0, a: 0} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _OutlineColor1: {r: 0, g: 0, b: 0, a: 1} + - _OutlineColor2: {r: 0, g: 0, b: 0, a: 0} + - _OutlineColor3: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset1: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset2: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset3: {r: 0, g: 0, b: 0, a: 0} + - _OutlineUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _Softness: {r: 0, g: 0, b: 0, a: 0} + - _SpecColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + - _UnderlayOffset: {r: 0, g: 0, b: 0, a: 0} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &8442970692996052813 +MonoBehaviour: + m_ObjectHideFlags: 11 + 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: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 9 diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - URP.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - URP.mat.meta new file mode 100644 index 0000000..b246600 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF - URP.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 90722b8bd74d9aa49958562aff7bdf76 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF.asset new file mode 100644 index 0000000..75ba721 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF.asset @@ -0,0 +1,302 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2164040 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Roboto-Bold SDF Material + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28204114720316640} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _Diffuse: 0.5 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: Roboto-Bold SDF + m_EditorClassIdentifier: + m_Version: 1.1.0 + m_Material: {fileID: 2164040} + m_SourceFontFileGUID: 4beb055f07aaff244873dec698d0363e + m_SourceFontFile: {fileID: 12800000, guid: 4beb055f07aaff244873dec698d0363e, type: 3} + m_AtlasPopulationMode: 1 + InternalDynamicOS: 0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: Roboto + m_StyleName: Bold + m_PointSize: 90 + m_Scale: 1 + m_UnitsPerEM: 2048 + m_LineHeight: 105.46875 + m_AscentLine: 83.49609 + m_CapLine: 64 + m_MeanLine: 48 + m_Baseline: 0 + m_DescentLine: -21.972656 + m_SuperscriptOffset: 83.49609 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -21.972656 + m_SubscriptSize: 0.5 + m_UnderlineOffset: -8.7890625 + m_UnderlineThickness: 4.3945312 + m_StrikethroughOffset: 19.2 + m_StrikethroughThickness: 4.3945312 + m_TabWidth: 22 + m_GlyphTable: [] + m_CharacterTable: [] + m_AtlasTextures: + - {fileID: 28204114720316640} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_ClearDynamicDataOnBuild: 1 + m_UsedGlyphRects: [] + m_FreeGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 1023 + m_Height: 1023 + m_fontInfo: + Name: Roboto + PointSize: 146 + Scale: 1 + CharacterCount: 98 + LineHeight: 192.5625 + Baseline: 0 + Ascender: 153 + CapHeight: 103.8125 + Descender: -39.5625 + CenterLine: 0 + SuperscriptOffset: 153 + SubscriptOffset: -14.2578125 + SubSize: 0.5 + Underline: -14.2578125 + UnderlineThickness: 7.1289062 + strikethrough: 41.25 + strikethroughThickness: 7.1289062 + TabWidth: 363.4375 + Padding: 9 + AtlasWidth: 1024 + AtlasHeight: 1024 + atlas: {fileID: 0} + m_AtlasWidth: 1024 + m_AtlasHeight: 1024 + m_AtlasPadding: 9 + m_AtlasRenderMode: 4165 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_MultipleSubstitutionRecords: [] + m_LigatureSubstitutionRecords: [] + m_GlyphPairAdjustmentRecords: [] + m_MarkToBaseAdjustmentRecords: [] + m_MarkToMarkAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: 4beb055f07aaff244873dec698d0363e + faceIndex: 0 + pointSizeSamplingMode: 1 + pointSize: 90 + padding: 9 + paddingMode: 0 + packingMode: 4 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 6 + characterSequence: 20-7E,A0,200B,2026 + referencedFontAssetGUID: 5302535af1044152a457ed104f1f4b91 + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4165 + includeFontFeatures: 0 + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 +--- !u!28 &28204114720316640 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Roboto-Bold SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + serializedVersion: 2 + m_Width: 0 + m_Height: 0 + m_CompleteImageSize: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 1 + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + image data: 0 + _typelessdata: + m_StreamData: + offset: 0 + size: 0 + path: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF.asset.meta new file mode 100644 index 0000000..f7fe8be --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5302535af1044152a457ed104f1f4b91 +timeCreated: 1487723159 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Bloom.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Bloom.mat new file mode 100644 index 0000000..893115a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Bloom.mat @@ -0,0 +1,223 @@ +%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: Unity SDF - HDRP LIT - Bloom + m_Shader: {fileID: -6465566751694194690, guid: ca2ed216f98028c4dae6c5224a952b3c, + type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _ALPHATEST_ON + - _DISABLE_SSR_TRANSPARENT + - _DOUBLESIDED_ON + - _ENABLE_FOG_ON_TRANSPARENT + - _SURFACE_TYPE_TRANSPARENT + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 1 + m_CustomRenderQueue: 3000 + stringTagMap: + MotionVector: User + RenderType: Transparent + disabledShaderPasses: + - TransparentDepthPrepass + - TransparentDepthPostpass + - TransparentBackface + - RayTracingPrepass + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 5445961698780662350, guid: c9adb1f542a93ae489bacfeae21e8394, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaCutoffEnable: 1 + - _AlphaDstBlend: 10 + - _AlphaSrcBlend: 1 + - _AlphaToMask: 0 + - _AlphaToMaskInspectorValue: 0 + - _Ambient: 0.393 + - _Bevel: 0.5 + - _BevelAmount: 0 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelType: 1 + - _BevelWidth: 0 + - _BlendMode: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _ConservativeDepthOffsetEnable: 0 + - _CullMode: 0 + - _CullModeForward: 0 + - _DepthOffsetEnable: 0 + - _Diffuse: 0 + - _DoubleSidedEnable: 1 + - _DoubleSidedGIMode: 0 + - _DoubleSidedNormalMode: 0 + - _DstBlend: 10 + - _DstBlend2: 10 + - _EnableBlendModePreserveSpecularLighting: 1 + - _EnableFogOnTransparent: 1 + - _ExcludeFromTUAndAA: 0 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _MaterialID: 1 + - _MaterialTypeMask: 2 + - _OpaqueCullMode: 2 + - _OutlineMode: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerPixelSorting: 0 + - _PerspectiveFilter: 0.875 + - _RayTracing: 0 + - _ReceivesSSR: 1 + - _ReceivesSSRTransparent: 0 + - _Reflectivity: 5 + - _RefractionModel: 0 + - _RenderQueueType: 4 + - _RequireSplitLighting: 0 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 0 + - _SrcBlend: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilRef: 0 + - _StencilRefDepth: 0 + - _StencilRefDistortionVec: 4 + - _StencilRefGBuffer: 2 + - _StencilRefMV: 32 + - _StencilWriteMask: 6 + - _StencilWriteMaskDepth: 9 + - _StencilWriteMaskDistortionVec: 4 + - _StencilWriteMaskGBuffer: 15 + - _StencilWriteMaskMV: 41 + - _SupportDecals: 1 + - _SurfaceType: 1 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _TransmissionEnable: 1 + - _TransparentBackfaceEnable: 0 + - _TransparentCullMode: 2 + - _TransparentDepthPostpassEnable: 0 + - _TransparentDepthPrepassEnable: 0 + - _TransparentSortPriority: 0 + - _TransparentWritingMotionVec: 0 + - _TransparentZWrite: 0 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _UseShadowThreshold: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + - _ZTestDepthEqualForOpaque: 4 + - _ZTestGBuffer: 3 + - _ZTestTransparent: 4 + - _ZWrite: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _DoubleSidedConstants: {r: -1, g: -1, b: -1, a: 0} + - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _FaceText_ST: {r: 1, g: 1, b: 0, a: 0} + - _FaceUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _IsoPerimeter: {r: 0, g: 0.3, b: 0.4, a: 0} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _OutlineColor1: {r: 0, g: 0, b: 0, a: 0} + - _OutlineColor2: {r: 0, g: 28.109804, b: 95.87451, a: 1} + - _OutlineColor3: {r: 0, g: 0, b: 0, a: 1} + - _OutlineOffset1: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset2: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset3: {r: 0, g: 0, b: 0, a: 0} + - _OutlineUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _Softness: {r: 0, g: 0, b: 0, a: 0} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + - _UnderlayOffset: {r: 0, g: 0, b: 0, a: 0} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &5076635838026210647 +MonoBehaviour: + m_ObjectHideFlags: 11 + 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: da692e001514ec24dbc4cca1949ff7e8, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 13 + hdPluginSubTargetMaterialVersions: + m_Keys: [] + m_Values: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Bloom.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Bloom.mat.meta new file mode 100644 index 0000000..a112160 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Bloom.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8d176c01131de8f46ad61094e29d79b2 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Outline.mat b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Outline.mat new file mode 100644 index 0000000..cd8be48 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Outline.mat @@ -0,0 +1,173 @@ +%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: Unity SDF - HDRP LIT - Outline + m_Shader: {fileID: -6465566751694194690, guid: ca2ed216f98028c4dae6c5224a952b3c, + type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _ALPHATEST_ON + - _DISABLE_DECALS + - _DISABLE_SSR_TRANSPARENT + - _DOUBLESIDED_ON + - _ENABLE_FOG_ON_TRANSPARENT + - _SURFACE_TYPE_TRANSPARENT + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 1 + m_CustomRenderQueue: 3000 + stringTagMap: + MotionVector: User + RenderType: Transparent + disabledShaderPasses: + - TransparentDepthPrepass + - TransparentDepthPostpass + - TransparentBackface + - RayTracingPrepass + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 5445961698780662350, guid: c9adb1f542a93ae489bacfeae21e8394, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaCutoffEnable: 1 + - _AlphaDstBlend: 10 + - _AlphaSrcBlend: 1 + - _AlphaToMask: 0 + - _AlphaToMaskInspectorValue: 0 + - _Ambient: 0 + - _BevelAmount: 0 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelType: 0 + - _BevelWidth: 0.5 + - _BlendMode: 0 + - _ConservativeDepthOffsetEnable: 0 + - _CullMode: 0 + - _CullModeForward: 0 + - _DepthOffsetEnable: 0 + - _Diffuse: 0 + - _DoubleSidedEnable: 1 + - _DoubleSidedGIMode: 0 + - _DoubleSidedNormalMode: 0 + - _DstBlend: 10 + - _DstBlend2: 10 + - _EnableBlendModePreserveSpecularLighting: 1 + - _EnableFogOnTransparent: 1 + - _ExcludeFromTUAndAA: 0 + - _GradientScale: 10 + - _LightAngle: 0 + - _MaterialID: 1 + - _MaterialTypeMask: 2 + - _OpaqueCullMode: 2 + - _OutlineMode: 0 + - _PerPixelSorting: 0 + - _RayTracing: 0 + - _ReceivesSSR: 1 + - _ReceivesSSRTransparent: 0 + - _Reflectivity: 5 + - _RefractionModel: 0 + - _RenderQueueType: 4 + - _RequireSplitLighting: 0 + - _ScaleRatioA: 0 + - _SpecularPower: 0 + - _SrcBlend: 1 + - _StencilRef: 0 + - _StencilRefDepth: 0 + - _StencilRefDistortionVec: 4 + - _StencilRefGBuffer: 2 + - _StencilRefMV: 32 + - _StencilWriteMask: 6 + - _StencilWriteMaskDepth: 9 + - _StencilWriteMaskDistortionVec: 4 + - _StencilWriteMaskGBuffer: 15 + - _StencilWriteMaskMV: 41 + - _SupportDecals: 0 + - _SurfaceType: 1 + - _TransmissionEnable: 1 + - _TransparentBackfaceEnable: 0 + - _TransparentCullMode: 2 + - _TransparentDepthPostpassEnable: 0 + - _TransparentDepthPrepassEnable: 0 + - _TransparentSortPriority: 0 + - _TransparentWritingMotionVec: 0 + - _TransparentZWrite: 0 + - _UnderlayDilate: 0 + - _UnderlaySoftness: 0 + - _UseShadowThreshold: 0 + - _ZTestDepthEqualForOpaque: 4 + - _ZTestGBuffer: 3 + - _ZTestTransparent: 4 + - _ZWrite: 0 + m_Colors: + - _DoubleSidedConstants: {r: -1, g: -1, b: -1, a: 0} + - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _FaceText_ST: {r: 1, g: 1, b: 0, a: 0} + - _FaceUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _IsoPerimeter: {r: 0, g: 0.188, b: 0, a: 0} + - _OutlineColor1: {r: 0, g: 0, b: 0, a: 1} + - _OutlineColor2: {r: 0.009433985, g: 0.02534519, b: 1, a: 1} + - _OutlineColor3: {r: 0, g: 0, b: 0, a: 1} + - _OutlineOffset1: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset2: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset3: {r: 0, g: 0, b: 0, a: 0} + - _OutlineUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _Softness: {r: 0, g: 0, b: 0, a: 0} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 1} + - _UnderlayOffset: {r: 0, g: 0, b: 0, a: 0} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &3286349241373283790 +MonoBehaviour: + m_ObjectHideFlags: 11 + 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: da692e001514ec24dbc4cca1949ff7e8, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 13 + hdPluginSubTargetMaterialVersions: + m_Keys: [] + m_Values: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Outline.mat.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Outline.mat.meta new file mode 100644 index 0000000..2f7f36e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF - HDRP LIT - Outline.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 967f61bb1e3e28645a39e0cb647cc79e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF.asset new file mode 100644 index 0000000..395f4c3 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF.asset @@ -0,0 +1,389 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &-8643439910342830561 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Unity Atlas Material + m_Shader: {fileID: -6465566751694194690, guid: f63d574838ccfb44f84acc05fed0af48, type: 3} + m_ShaderKeywords: _ALPHATEST_ON _DOUBLESIDED_ON _ENABLE_FOG_ON_TRANSPARENT _SURFACE_TYPE_TRANSPARENT + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 1 + m_CustomRenderQueue: 3000 + stringTagMap: + MotionVector: User + RenderType: Transparent + disabledShaderPasses: + - TransparentDepthPrepass + - TransparentDepthPostpass + - TransparentBackface + - MOTIONVECTORS + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 5445961698780662350} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaCutoffEnable: 1 + - _AlphaDstBlend: 10 + - _AlphaSrcBlend: 1 + - _AlphaToMask: 0 + - _AlphaToMaskInspectorValue: 0 + - _Ambient: 0.31 + - _Bevel: 0.5 + - _BevelAmount: 1 + - _BevelClamp: 0 + - _BevelOffset: 0.047 + - _BevelRoundness: 0.84 + - _BevelType: 0 + - _BevelWidth: 0.286 + - _BlendMode: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _CullMode: 0 + - _CullModeForward: 0 + - _DepthOffsetEnable: 0 + - _Diffuse: 0.922 + - _DoubleSidedEnable: 1 + - _DoubleSidedNormalMode: 2 + - _DstBlend: 10 + - _EnableBlendModePreserveSpecularLighting: 0 + - _EnableFogOnTransparent: 1 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 4.51 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OpaqueCullMode: 2 + - _OutlineMode: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 8.39 + - _RenderQueueType: 4 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2.4 + - _SrcBlend: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilRef: 0 + - _StencilRefDepth: 0 + - _StencilRefDistortionVec: 4 + - _StencilRefGBuffer: 2 + - _StencilRefMV: 32 + - _StencilWriteMask: 6 + - _StencilWriteMaskDepth: 8 + - _StencilWriteMaskDistortionVec: 4 + - _StencilWriteMaskGBuffer: 14 + - _StencilWriteMaskMV: 40 + - _SurfaceType: 1 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _TransparentBackfaceEnable: 0 + - _TransparentCullMode: 2 + - _TransparentDepthPostpassEnable: 0 + - _TransparentDepthPrepassEnable: 0 + - _TransparentSortPriority: 0 + - _TransparentWritingMotionVec: 0 + - _TransparentZWrite: 0 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _UseShadowThreshold: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + - _ZTestDepthEqualForOpaque: 4 + - _ZTestGBuffer: 3 + - _ZTestTransparent: 4 + - _ZWrite: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0} + - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _FaceUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _IsoPerimeter: {r: 0, g: 0.1, b: 0.2, a: 0.3} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _OutlineColor1: {r: 0, g: 1, b: 1, a: 1} + - _OutlineColor2: {r: 0.009433985, g: 0.02534519, b: 1, a: 1} + - _OutlineColor3: {r: 0, g: 0, b: 0, a: 1} + - _OutlineOffset1: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset2: {r: 0, g: 0, b: 0, a: 0} + - _OutlineOffset3: {r: 0, g: 0, b: 0, a: 0} + - _OutlineUVSpeed: {r: 0, g: 0, b: 0, a: 0} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _Softness: {r: 0, g: 0, b: 0, a: 0} + - _SpecularColor: {r: 0, g: 0.9563775, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + - _UnderlayOffset: {r: 0, g: 0, b: 0, a: 0} + m_BuildTextureStacks: [] +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: Unity SDF + m_EditorClassIdentifier: + m_Version: 1.1.0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: Unity + m_StyleName: Regular + m_PointSize: 90 + m_Scale: 1 + m_UnitsPerEM: 2048 + m_LineHeight: 90 + m_AscentLine: 84.375 + m_CapLine: 0 + m_MeanLine: 0 + m_Baseline: 0 + m_DescentLine: -5.625 + m_SuperscriptOffset: 84.375 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -5.625 + m_SubscriptSize: 0.5 + m_UnderlineOffset: 0 + m_UnderlineThickness: 0.087890625 + m_StrikethroughOffset: 0 + m_StrikethroughThickness: 0.087890625 + m_TabWidth: 0 + m_Material: {fileID: -8643439910342830561} + m_SourceFontFileGUID: f4eec857a4fdf2f43be0e9f3d1a984e7 + m_SourceFontFile: {fileID: 0} + m_AtlasPopulationMode: 0 + InternalDynamicOS: 0 + m_GlyphTable: + - m_Index: 2 + m_Metrics: + m_Width: 245.30273 + m_Height: 88.85742 + m_HorizontalBearingX: 0.703125 + m_HorizontalBearingY: 83.583984 + m_HorizontalAdvance: 246.44531 + m_GlyphRect: + m_X: 10 + m_Y: 10 + m_Width: 246 + m_Height: 89 + m_Scale: 1 + m_AtlasIndex: 0 + m_CharacterTable: + - m_ElementType: 1 + m_Unicode: 58183 + m_GlyphIndex: 2 + m_Scale: 1 + m_AtlasTextures: + - {fileID: 5445961698780662350} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_ClearDynamicDataOnBuild: 0 + m_AtlasWidth: 1024 + m_AtlasHeight: 1024 + m_AtlasPadding: 9 + m_AtlasRenderMode: 16422 + m_UsedGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 265 + m_Height: 108 + m_FreeGlyphRects: + - m_X: 0 + m_Y: 108 + m_Width: 1023 + m_Height: 915 + - m_X: 265 + m_Y: 0 + m_Width: 758 + m_Height: 1023 + m_FontFeatureTable: + m_MultipleSubstitutionRecords: [] + m_LigatureSubstitutionRecords: [] + m_GlyphPairAdjustmentRecords: [] + m_MarkToBaseAdjustmentRecords: [] + m_MarkToMarkAdjustmentRecords: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: f4eec857a4fdf2f43be0e9f3d1a984e7 + faceIndex: 0 + pointSizeSamplingMode: 0 + pointSize: 90 + padding: 9 + paddingMode: 0 + packingMode: 0 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 7 + characterSequence: + referencedFontAssetGUID: + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 16422 + includeFontFeatures: 0 + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: [] + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 + m_fontInfo: + Name: + PointSize: 0 + Scale: 0 + CharacterCount: 0 + LineHeight: 0 + Baseline: 0 + Ascender: 0 + CapHeight: 0 + Descender: 0 + CenterLine: 0 + SuperscriptOffset: 0 + SubscriptOffset: 0 + SubSize: 0 + Underline: 0 + UnderlineThickness: 0 + strikethrough: 0 + strikethroughThickness: 0 + TabWidth: 0 + Padding: 0 + AtlasWidth: 0 + AtlasHeight: 0 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + fallbackFontAssets: [] + atlas: {fileID: 0} +--- !u!28 &5445961698780662350 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Unity Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + m_IsAlphaChannelOptional: 0 + serializedVersion: 2 + m_Width: 1024 + m_Height: 1024 + m_CompleteImageSize: 1048576 + m_MipsStripped: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 0 + m_IsPreProcessed: 0 + m_IgnoreMasterTextureLimit: 0 + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_VTOnly: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + m_PlatformBlob: + image data: 1048576 + _typelessdata: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090c0f10100f0c0803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205080c0f1215181b1d1d1b18140e0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104080b0e1115181b1e2125282a2a28251f1912090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104070a0e1114171b1e2124272b2e3134363634302b231b1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070a0d1014171a1d2024272a2d3134373a3d414343413c352d241a10050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306090d101316191d2023262a2d3033363a3d4043474a4d50504d473f362c21160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205090c0f1216191c1f2226292c2f3336393c404346494c505356595c5c5851483d32271b0f030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205080b0f1215181b1f2225282c2f3235383c3f4245494c4f5255595c5f62666969635a4f43372b1f130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104080b0e1115181b1e2125282b2e3235383b3e4245484b4f5255585b5f6265686b6f7275756b6054473b2f22160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070a0d1114171a1e2124272b2e3134373b3e4144484b4e5154585b5e6165686b6e7175787b7e827c7063574b3e32261a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0f13171a1d2023272a2d3034373a3d4044474a4d5154575a5e6164676a6e7174777a7d8285888b8c8073675a4e4236291d110400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e151b1f2326292d303336393d4043464a4d5053565a5d6063676a6d7074777a7d8184878a8e9194978f83766a5e5145392d201408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f181f262c2f3236393c3f4346494c4f5356595c5f6366696c707376797d8083878a8d9093979a9da09f93867a6d6155493c3024170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d17212a31373c3f4245484c4f5255595c5f6266696c6f7275797c808386898c909396999da0a3a6a9ada2968a7d7165584c4033271b0f020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f29333b43484b4e5255585b5e6265686b6f7275787b7e8285898c8f9295999c9fa2a6a9acafb2b6b2a6998d8174685c4f43372b1e12060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206080a0a0a0a0a0a0a0a0a09070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b26313b454d54575b5e6164686b6e7174787b7e8285888b8f9295989b9fa2a5a8abafb2b5b8bcbfc2b5a99d9084786b5f53473a2e2215090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e12151717171717171717161514110f0c080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212c37424d575f64676a6d7174777a7d8184888b8e9194989b9ea1a5a8abaeb1b5b8bbbec2c5c8cbc5b9aca094887b6f62564a3d3125190c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c13191e2223232323232323232322201e1b18140f0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c27323d48535f697073767a7d8184878a8d9194979a9da1a4a7aaaeb1b4b7bbbec1c4c7cbced1d4d5c8bcb0a4978b7e72665a4d4135281c100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161e252a2e3030303030303030302f2d2a2724201b150f08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206080808080808080d18232e39444f5a65707b8083868a8d9093969a9da0a3a7aaadb0b3b7babcb8b5b3b2b5bbc3ccd6dde1d8ccbfb3a79a8e8275695d5144382c201307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b161f2830363a3d3d3d3d3d3d3d3d3d3b393734302b26201a130b0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214151515151515151e29343f4a55606b76828c8f9396999ca0a3a6a9acb0b3b6b9bcb8b5b2afaca9a6a6aab1bac4cfdadcdbcfc3b7aa9e9285796d6054483b2f23170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d27313a4147494a4a4a4a4a4a4a49484643403c37322b241d150c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e151a1e212222222222222224303b46515c67727d88939c9fa2a5a9acafb2b6b9bcb8b5b2afaca9a6a3a09d99999fa8b2becad1d0d0d2c6baaea195897c7064574b3f33261a0e0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18232f39434c525656565656565656565552504c48433d362f271e150c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101820262b2e2f2f2f2f2f2f2f2e36414c57626d78838e99a4abafb2b5b8bbb8b5b2afaca9a6a3a09d999693908d8d96a1adbac6c5c3c3c6cabdb1a5988c8073675b4f42362a1d11050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c2834404b555e636363636363636362615f5c58534e48413930271e140a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071019222a31373a3b3b3b3b3b3b3b3b3c47525d68737e8a95a0abb6bbb8b5b2afaca9a6a3a09d999693908d8a87848185929facb8beb9b6b7bac0c1b4a89c9083776b5e5246392d2114080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2c3844515c676f707070707070706f6e6b68645f59524b423930261c12080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071019222b343c42474848484848484847474e59646f7a85909ba6b1b2afaca9a6a3a09d999693908d8a8784817d7a77808b96a1adbab3adaaaaaeb5beb8ab9f93877a6e6255493d3124180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d797d7d7d7d7d7d7d7c7a7874706b645d544b42382e24190f0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008101a232b343d464e53555555555555555454545f6a75818b96a2aca9a6a3a09d999693908d8a8784817d7a777471707b86919ca7b2b3a9a19d9ea3acb6bbafa3968a7d7165594c4034281b0f030000000000000000000000000000000000000000000000010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a878a8a8a8a8a8a898785817c766f665d544a40362b20150a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a232c353d464f585f6262626262626261616166717c87929da3a09d999693908d8a8784817d7a7774716e6b686c77828d98a3aeb7aca19790929aa5b1bdb2a69a8e8275685c5044372b1f12060000000000000000000000000000000000000407090b0d0e0e0e0e0d0b090703000001010101010101010101010000010101010101010101010100000000000000000000000001010101010101010101010000010101010101010101010100000000000000000000000000010203030714202d3a4753606d7a879497979797979694918d8781786f665c52473d32271c100500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a232c353e474f58616a6e6e6e6e6e6e6e6e6e6e6e77828d98999693908d8a8784817d7a7774716e6b6865625f67727d89939ea9b4b1a69b90858995a1adb9b6a99d9185786c5f53473b2e22160a00000000000000000000000000000004080d10131618191a1b1b1a19181613100c0c0d0e0e0e0e0e0e0e0e0e0d0b0c0e0e0e0e0e0e0e0e0e0e0e0c090500000000000005090c0e0e0e0e0e0e0e0e0e0e0d0c0c0e0e0e0e0e0e0e0e0e0e0e0c090500000000000003070a0c0e0f10101014202d3a4753606d7a8794a1a4a4a4a4a2a09d98928b82786e64594e43382d21160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009111a232c353e475059616a737b7b7b7b7b7b7b7a7a7a7a7d8993908d8a8784817d7a7774716e6b6865625f5b5858636e79848f9aa5b0b5aa9f94897e85919daab6b9ada194887b6f63574a3e3225190d01000000000000000000000000040a0f14191d20232526272727272624221f1c18181a1b1b1b1b1b1b1b1b1b1a18181a1b1b1b1b1b1b1b1b1b1a1915110b040000040b1116191a1b1b1b1b1b1b1b1b1b1a18181a1b1b1b1b1b1b1b1b1b1a1915110b040001070b0f1316181a1b1c1c1c1c202d3a4753606d7a8794a1adafb0b0afada9a49c948a80756a6055493e32271c100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b232c353e475059626b737c8689898989898888888888888a8784817d7a7774716e6b6865625f5b5855524f535e6974808a95a0abb6afa4998e8378828e9aa6b2bcb0a4988b7e73665a4e4135291d10040000000000000000000001080f151b2025292c2f31333434343433312f2c28242427272727272727272727272425272727272727272727272725211c160e06060f161d222527272727272727272727272425272727272727272727272725211c160e070d12171b1f2225272829292928282d3a4753606d7a8794a1a1a2a4a7acb2b5aea69c92877c71665a4f43382c211509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d353e475059626b747d868f9595959595959595958f867d7a7774716e6b6865625f5b5855524f4c49464f5a65707b86919ca7b2b3a89d92887c717d8a96a3afbbb4a79b8f83766a5d5145382c201407000000000000000000030b121920262c3135383c3e3f404141403f3e3b38342f31333434343434343434343330313434343434343434343434322d2720180f0f1821282e32343434343434343434343331313434343434343434343434322d27201812181e23282b2f3134353636363535343a4753606d7a8794959595989ba0a7afb8aea3998e83776b6055493d31261a0e0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d363f475059626b747d868f98a1a2a2a2a2a1a1988f867d746e6b6865625f5b5855524f4c49464340404b56606b76828d97a2adb8ada2978c81766e7a87939fabb8b7ab9f9286796d6154483c3023170b0000000000000000040c151d242b32373d4145484a4c4d4e4e4d4c4a4844403b3d40414141414141414141403c3d40414141414141414141403e39322a211717212a32393e41414141414141414141403d3d40414141414141414141403e39322a211d24292f33383b3e4042424343424241404753606d7a87888888898b8f959da6b0b5aa9f94887c71655a4e42362a1e1206000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000109121b242d363f485159626b747d868f98a1aaafafafaaa1988f867d746b625f5b5855524f4c494643403d39363b46515c67727d88939ea9b4b1a69b90857a6f6a77838f9ca8b4baaea295897d7064584c3f33271b0e02000000000000030d161e272f363d43484d515457595a5a5a5a595754504c47484d4e4e4e4e4e4e4e4e4e4c48494d4e4e4e4e4e4e4e4e4e4d4a443c33291e1e29333c444a4d4e4e4e4e4e4e4e4e4e4d48494d4e4e4e4e4e4e4e4e4e4d4a443c3329282f353a3f44484b4d4e4f4f4f4e4e4e4c4953606c787a7a7a7a7c7e848b949ea9b4b0a5998e82766a5e53473b2f23170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131b242d363f48515a636b747d878f98a1aab3bcb3aaa1988f867d746b6259524f4c494643403d393633302d37424d58626d79848f99a4afb6aba0958a7e74696773808c98a4b1bdb1a5998d8174685b4f43362a1e12050000000000020c151f28303940474e54595d616466666767666563605c585254595a5a5a5a5a5a5a5a5a595354595a5a5a5a5a5a5a5a5a5a554e453a2f2424303b454e565a5a5a5a5a5a5a5a5a5a595454595a5a5a5a5a5a5a5a5a5a554e453a2f333a40464b505457595b5c5c5c5b5b5a5955505b666d6e6e6e6e6f7379828d98a3afb6aa9e93877b6f63574b3f33271b0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252d363f48515a636c757d879099a1aab3bcb3aaa1988f867c736b6259504743403d393633302d2a2727323d48535e6974808a95a0abb6afa4998e83786d6263707c8895a1adb9b5a99c9084776b5f52463a2e211509000000000009141e27313a424b52595f65696d70727374747372706c68635d5e65676767676767676767655d5e656767676767676767676660564c4034282935414c576066676767676767676767655e5e656767676767676767676660564c40343d444b51575c60636668696969686867655f56545c60616161616367707b86929eabb7afa3978c8073675b4f43372b1f1307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e373f48515a636c757e879099a2abb3bcb3aaa1988f867c736a615950473e3633302d2a2724211e232e39444f5a656f7a86919ca7b2b4a99e93887d72675c606c7885919daab6b8aca093877a6e6256493d3125180c0000000006111b263039434c545c646a7075797c7e818282817e7c79746e6865707474747474747474746f65667074747474747474747472685c5044372b2b3845515d69727474747474747474747065667074747474747474747472685c50443d464e565c62686c70727475767675757471685c50505454545455565e6a76838f9ba8b5b4a89c9084776b5f53473b2f23170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e374049515a636c757e879099a2abb4bcb3aaa1988f867c736a61584f473e352c2724211e1b17141e29343f4a55606b76818c97a2adb8ada2978d82766b60555c6975828e9aa6b2bcafa3978b7e7266594d4134281c0f030000010c17222d37414b555e666e757c8286898c8d8e8e8d8b89858079726b7582828282828282828274676976828282828282828282786b5e5245382b2c3946525f6c7982828282828282828275686976828282828282828282786b5e5245454f5860686e73787c8082828383828281786b5e524547474747484e5a6774818d9aa7b4b8aca094887c7064574b3f33271b0f03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b131c252e374049525b636c757e879099a2abb4bbb3aaa1988f867c736a61584f463d352c231b1714110e0f1a25303b46515c67717c88939ea9b4b2a79c91867b70655a4f5965717d8a96a3afbbb3a69a8e8275695d5044382b1f1307000007121e29343f49535d67707881878d9295989a9b9a9a9895918b847c7475828e8e8e8e8e8e8e8274676976838e8e8e8e8e8e8e85786b5e5245382b2c3946525f6c79868e8e8e8e8e8e8e8275686976838e8e8e8e8e8e8e85786b5e52454d57616a72797e84888c8e8f908f8f8f85786b5e52453a3b3b3b414e5a6774818d9aa7b4bcb0a4988c8074685c5044372b1f13070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d252e374049525b646d757e889199a2abb4bbb2a9a1988f867c736a61584f463d342b231a100b08050b15202b36414c57626d78838e99a4afb6aba0958a8074695e534955626e7a87939fabb7b6aa9e9185786c6054473b2f22160a00010c18232f3a45505b656f79828a92999ea2a5a6a7a7a6a4a19c968f877e75828f9b9b9b9b9b8e827467697683909b9b9b9b9b9285786b5e5245382b2c3946525f6c7986939b9b9b9b9b8f827568697683909b9b9b9b9b9285786b5e5248545f69737c848a9095989b9c9d9c9c9285786b5e5245382e2e3743505c6975828f9ba8b5c1b4a89c9084786c6054483b3024170b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d262f374049525b646d767e88919aa3abb4bbb2a9a0978f867c736a61584f463d342b22191007000006111c27323d48535e69747e8a95a0abb6b0a59a8f84796e63584d46525e6a76838f9ba8b4baada195897c7063574b3e32261a0d0105111d2934404b57626d77828b949ca4a9aeb1b3b4b4b2b1ada7a09890877d828f9ca8a8a89b8e827467697683909da8a8a89f9285786b5e5245382b2c3946525f6c798693a0a8a8a89c8f827568697683909da8a8a89f9285786b5e524e5965707b858e969ba1a5a7a9a9a99f9285786b5e5245382b2e3a47535f6b7885919daab7c3b8aca094887c7064584c4034281b0f030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d262f384149525b646d768089919aa3acb5bbb2a9a0978e857c736a61584f463d342b221910070303030d17222d38434e59646f7a85909ba6b1b4a99e93897d72675c5146424e5a6773808c98a4b0bdb1a4988c8073675a4e4236291d11040915222e3945515c68737e89939da6aeb5bab4aeaaa7a5a5a5a6a8a2999086828f9ca9b4a89b8e827467697683909da9b4ac9f9285786b5e5245382b2c3946525f6c798693a0adb4a99c8f827568697683909da9b4ac9f9285786b5e52525e6a76828d97a0a7acb1b1aba7a49f9285786b5e5245382b323e4a56636f7b8894a0adb9c5bdb1a5988c8174685c5044382c20140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b141d262f38414a535b646d768089929ba3acb5bbb2a9a0978e857c736a61584f463d342b2219101010101010131e29343f4a55606b76818c97a2adb8aea3988d82776c61564b403e4b57636f7c8894a1adb9b4a89b8f83766a5e5245392d2014080d1926323e4a56626d7985909ba5afb8b7b0a9a39e9b999898999ca0a2988f8d949fabb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e5255616e7a86929ea9b2b7aea6a09b98979285786b5e5245382b36424e5a66737e8b97a4b0bcc8c1b5a99d9185786c6054483c3024180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151d262f38414a535c656d768089929ba4adb5bbb2a9a0978e857c736a61584f463d342b221c1c1c1c1c1c1c1c1c242f3a45505b66717c87929da8b3b2a79c91867b70655a4f44393b4753606c7885919da9b6b7ab9f93867a6e6155493c3024180b101c2935424e5a66727e8a96a1acb7b7aea59e97928e8c8b8b8d90949aa19b9a9ea6b0b4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e525764707d8a96a2afbbb0a59c948f8b8a8a85786b5e5245382e3a46525e6a76838f9ba7b3c0c8c5b9ada195897c7064584c4034281c100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151e272f38424b535c656e768089929ba4adb6bbb2a9a0978e857c736a61574f463d342b29292929292929292929292b36414c57626d78838e99a4afb7aca1968b80756a5f54493e333744505c6875828d9aa6b2bbafa2968a7d7165584c4033271b0e131f2c3845515d6a76838f9ba7b2baafa59c948c8682807d7e8184898f97a0a6a9afb8b4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e525865727e8c98a5b1b5a99e948a837e7d7d7d776b5e524538323e4a56636f7a87939fabb7bdbbbcbdb1a5998d8174685c5044382c201408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d151e273039424b545d656e778189929ba4adb6bbb2a9a0978e857c736a61574e453d3636363636363636363636363636363c47525d68737e89949faab5b0a59a8f84796e63584d42372c34404c5965717d8a96a2afbbb2a6998d8174685c4f43362a1d1115212e3b4754606d7986929fabb7b3a89d938a827a7572717273777d858e97a1abb6c1b4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b2b1a5998d8278727070706e665b4f433737434f5b67737e8b97a3afb6b0aeafb3b5a99d9185786c6054483c3024180c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161f273039424b545d666f77818a939ba4adb6bbb2a9a0978e857c736a61574e454343434343434343434343434343434343434e59646f7a85909ba6b1b5aa9f94897d72685d52473c3126303d4955616e7a86939fabb7afa4998f84776a5e5144372b1e1116232f3c4956626f7b8895a1aebaaea2978c8178706a666565676c737b858f9aa5b1bcb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3afa296897c7066636363625d544a3e333b47535f6b77838f9ba7b3aba4a1a3a8b0ada195897d7165584c4034281c1004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161f283139424b545d666f78818a939ca5adb6bbb2a9a0978e857c736a61574f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f545f6a75818b96a1acb7aea3988d83776c61564b40352a212d3945525e6a76838f9ba8b4a99e93887d72675b4f43362a1d101724313d4a5763707d8a96a3b0b6a99d91867a6f665e5a58585b6169737d89949fabb7b4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6157565656524b423834404c57636f7b8893a0acada29995979ea8b1a5998d8175695d5145382c2014080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161f28313a434b545d666f78818a939ca5aeb7bcb2a9a0978e857c736a615c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c66717c87929da8b3b3a89d92877c71665b50453a2f241d2936424e5a6773808c98a4ada2978c82766b60564b3f33271b0e1824313e4b5764717d8b98a4b1b3a69a8e8275695e544d4b4c4f57616c77838f9ba7b3b4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e61544a4a49464039303844505c6874808c98a4b0a89c90888c97a3afa99d9185796d6155493d3125180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d161f28313a434c555d666f78818a939ca5aeb7c0b5aaa0978e857b726a69696969696969696969696969696969696969696969696969696c77838e98a3aeb7aca1968b81756a5f54493e33281d1a26323e4b57636f7b8894a1a69b91867a70655a4f44392e23170b1824313e4b5764717d8b98a5b1b1a5988b7e7265594d423e3f454f5b66727e8b97a4b0b4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473d3d3a352f313d4955606c7885909ca8b1a5988c808794a0acaea295897d7165594d4135291c11050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151f28313a434c555e676f78828b939ca5aeb7c0beb1a5998e857b7676767676767676767676767676767676767676767676767676767676767e89949faab5b1a69b90857a6f64594e43382d221716222f3b47535f6c7885919da0958a7e74695e53483d33281d120b1824313e4b5764717d8b98a5b1b1a4978a7d7064574a3e32333e4a56636f7b8995a2aeb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b302e2a2a35414d5965717d8995a1adada195897c84909da9b2a6998d8275695d5145392d211509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121d27313a434c555e677078828b949da5aeb7c0c9bdb1a4978b838383838383838383838383838383838383838383838383838383838383838385909aa5b0b5aa9f94897e73685d52473c31261b10131f2b3744505c6875818d99998e83786d62584d42372c21160b0b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302e3b4754616d7a8794a1adb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e21222e3a46525e6a75828e99a5b1aa9e918579818d9aa6b2aa9e9286796d6155493d3125190d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e39434c555e677079828b949da6aeb7c0c9ccbfb3a79c9390909090909090909090909090909090909090909090909090909090909090909097a1acb7afa4998e83786d62574c41362b20150a0f1b2834404c5865717d8a9693887c72675c51463b30251a10050b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e2127333e4a56626e7a86929eaab2a69a8e82757d8a97a3afaea2968a7d7165594d4135291d1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1b27333f4a555e677079828b949da6afb8c0c9d2cfc4b8aea59f9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9da1a9b3b3a89d92877c71665b50453a2f24190e030c1824303c4955616d7a86928c81766b60554a3f342a1f1409000b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e212b37434f5b67737e8b97a3aeafa3968a7d727a8793a0acb2a69a8e8275695d5145392d21150900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2a3743505c677079838b949da6afb8c1cad2dbd5cac0b7afaba9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9aaadb3baaea2978c81766b60554a3f34291e1308000814202d3945515e6a76838f857a6f64594f44392e23180d02000b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e24303c48535f6b77838f9ba7b3ab9f93877a6e7784909ca8b4aa9e92867a6e6255493d3125190d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2b3845525e6b78838c949da6afb8c1cad3dce4dcd2c9c1bbb7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b9beb8ac9f92867a6f64594e43382d22170c010004111d2935424e5a6673808b7e74695e53483d32271c110700000b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e2834404c5864707c8894a0acb3a79b8f83766a73808c98a5b1aea2968a7d7266594e4235291d1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2b3744505d69737c858e97a0a9b1bac3ccd5ded6cbc2b9b2adacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacafb5b9ada1958a7e74695e53483d32271c1106000713202c3844515d6975828e84786d63584d42372c21160b01000b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e2d3945515c6874818c98a4b0afa3978b7e7367707c8894a1adb2a69a8e82766a5e5246392d2115090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2834404c57616a737c858e97a0a8b1bac3ccd5d0c5bab0a7a19f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa3abb4b2a79b90867a6f64594f44392e23180d020b17232f3c4854606d7985918a8074695e53493e33281d1207000b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ac9f9285786b5e5245382b2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e313d4955616d7985919da9b5ab9f93877b6f636c7884909da9b5aa9e92867a6e62564a3e3226190d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18242f3b454e57616a727b858e969fa8b1bac3ccccc0b4a89e9592929292929292929292929292929292929292929292929292929292929292929399a2adb8ada2978c81766b60554a3f34291e13080e1a27333f4b5864707c899591867b70655a4f44392e24190e030b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ac9f9285796c5f5246392d2c3946525f6c798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e36424e5a66717d8a95a1adb2a79a8f83766a5e6874818d99a5b1afa3968a7e72665a4e42362a1e1206000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007131e29333c454e576069727b848d969fa8b1bac3cabeb1a4988c858585858585858585858585858585858585858585858585858585858585858587919ca7b2b3a99d93887c71665c51463b30251a0f121e2a36434f5b6774808c99978d82766b61564b40352a1f14090b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ada094877a6e6155493d33313a4653606d798693a0adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e3a46525e6a76828e9aa6b2aea2968a7e72665a64707c8995a1adb3a79a8f83766a5e52463a2e22160a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d17212a333c454e576069717a848d959ea8b1b9c2beb1a4988c8379787878787878787878787878787878787878787878787878787878787878808a95a0abb6afa4998e83786d62574c41362b201515212e3a46525f6b7784909c9e93887d72675c51473c31261b100b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6afa3968a7d71655a4f453e3e414a55626e7a8894a1adb5a99c8f827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473b333f4b57636f7a87939faab6aa9e92867a6e6256606c7885919da9b5ab9f93877a6e62564a3e32261a0e020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f18212a333c454e576068717a838c959ea7b0b9c0b4a99e958c8379706b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6d79848f9aa5b0b6ab9f958a7e74695e53483d32271c1925313d4a56626e7b8793a0a59a8f84796e63584d42372c21150b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6b2a69a8e82766b60574f4b4b4d535b66727d8a96a3afb5a89b8e827568697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e6154473e3d434f5b6773808b97a3afb1a5998d8275695d515c6874818d99a5b1afa3978b7e72665a4e42362a1e1206000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a333c454e565f68717a838c959ea7b0b8bab0a79e958c837970675e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e67727d88939ea9b4b1a69b90857a6f64594e43382d221c2935414d5966727e8b97a3aba0958a8074695f54493d32261a0d1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6b6aa9e93887d7269615b5857595e656d77838e9aa6b2b3a79a8d817467697683909da9b6ac9f9285786b5e52596672808d99a6b3aea195887a6e61544b4b494854606c7884909ca8b3ada195897d7165594d5864707c8995a1adb3a79b8f83766a5e52463a2e22160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a333c444d565f68717a838c959ea6afb8b9b0a79e958c837970685f5652525252525252525252525252525252525252525256616c76828d98a3aeb8ada2978c81756b60554a3f3429202c3845515d6975828e9aa7b2a79c91867b70655a4e4236291d101824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6bbafa4998f857b736c67646466696f768089949fabb6b1a5988c7e7266697683909da9b6ac9f9285786b5e57596672808d99a6b3aea195887a6e6157575756515864707c8894a0acb5a99d9185786d60554954606d7985919da9b5ab9f93877b6f63564a3e32261a0e0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18212a323b444d565f687179838c949da6afb8b9b0a79e958c837a71685f564d454545454545454545454545454545454545454f5a65707b86919ca7b2b3a89d92877c71665b50453a2f24303c4854606d7986929eaab6ada3988d82766a5d5144372b1e111824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6bcb5aba0978e857d7773717172757a8189929ba6b1b9ada195897c7063697683909da9b6ac9f9285786b6464646672808d99a6b3aea195887a6e64646464625b5d6975818d99a5b1b0a4988c8174685c5044505c6975818d99a6b2afa3978b7e73675b4f43362a1e12060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f182029323b444d565f677079838b949da6afb8b9b0a79e958c837a71685f564d443b3838383838383838383838383838383e49545f6a75808b96a1acb7afa4998e83776d62574c41362b333f4c5864707c8995a2aebab3a79a8e8275695d5044372a1e111824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6b4aaa3a0a0978f8983807d7d7e82868c939ba4adb7b4a99d9185796d60697683909da9b6ac9f9285786b7171717172808d99a6b3aea195887a71717171716d64626d7985919da9b5aca094887c7064584c404c5865717d8995a2aeb3a79b8f83776b5f53473a2f23160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e172029323b444d555e677079828b949da6afb7b9b0a79e958c837a71685f564d443b322b2b2b2b2b2b2b2b2b2b2b2b2c37424d58636e79848f9aa5b0b5aa9f94897e73685d52473c3137434f5b6874818d99a5b1bcb0a3978b7e7266594d4134281c0f1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6ada29893949c9a948f8c8b8b8c8e92979da5adb6b8aea3988c8175695c697683909da9b6ac9f928578717d7d7d7d7d808d99a6b3aea195887d7d7d7d7d7d756866727d8a96a2aeb4a89c9084776c5f54483c4955616d7985919eaab6aba093877b6f63574b3f33271a0e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e172029323b434c555e677079828b949da5aeb7b9b0a89e958c837a71685f564d443b3229201f1f1f1f1f1f1f1f1f26313c47525d68727d89949faab5b1a69b90857a6f64594e43383a46535f6b7784909ca9b5b8aca094877b6e62564a3d3125180c1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b6a99d90878a949fa09b999898989a9ea3a8afb6b9b0a79c92867b70645c697683909da9b6ac9f928578717d8b8b8b8b8b919ca8b4b0a3988e8b8b8b8b8b8275686b76838e9aa6b2afa3978b8073675b4f433845515d6975828e9aa6b2b0a4978b8073675b4f43372b1f130700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e172029313a434c555e677078828b949ca5aeb7bab1a89e958c837a71685f564d443b32292017121212121212141f2a35404b56616c77828d98a3aeb7aca1968b81756a5f54493e3e4a56626f7b8794a0acb8b5a99c9084776b5f53463a2e21150b1824313e4b5764717d8b98a5b1b1a4978a7d7063564a3d302d3a4753606d7a8794a1adb4a89b8e827467697683909da9b5a99c8f82838d97a1a8a5a5a5a5a7aaaeb3bab7b0a89e958a80756a5f5c697683909da9b6ac9f928578717d8b989898989ba3adb8b4a9a099989898988f8275686f7b87939fabb7ab9f93877b6f63574b3f34414d5965717d8a96a2aeb4a89c9084776b5f53473b2f23170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e171f28313a434c555e666f78828a939ca5aeb7bab1a89e958c837a71685f564d443b322920170e050000030e19242f3a45505b66717b87929da8b3b3a89d92877c71665b5045414e5a66727e8b97a3b0bcb1a5998d8174685b4f43372a1e120b1824313e4b5764717d8b98a5ababa4978a7d7063564a3d302d3a4753606d7a8794a1ababa89b8e827467697683909da9aba99c8f827b858f98a0a7adb1b1b3b6b6b4b1aca59e958c83786e63585c697683909da9abab9f928578717d8b98a5a5a5a7adb5bfbbb2aaa5a5a5a59c8f82756874808c97a3ababa79b8f83766b5e52473a313d4955616d7986929eaaababa094887b6f63574b3f33271b0f030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d161f28313a434c545d666f78818a939ca5aeb6bab1a89e958c837a71685f564d443b322920170e05000007121d28333e49545f6a75818b96a1acb7aea3988d83776c61564b45515d6a76828f9ba7b3baaea296897d7064584c3f33271b0e0b1824313e4b5764717d8b989e9e9e9e978a7d7063564a3d302d3a4753606d7a87949e9e9e9e9b8e827467697683909d9e9e9e9c8f82757c868e969da2a6a8aaaaa9a8a5a09a948c837a70675c525c697683909d9e9e9e9e928578717d8b989e9e9ea1a8b1bbb7ada59f9e9e9e9c8f82756c7884909c9e9e9e9e968a7e72665a4e42362d3945515d6975828e9a9e9e9e9e988c8073675b4f43372b1f1306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161f28313a424b545d666f78818a939ca5adb6bab1a89e958c837a71685f564d443b322920170e0804010c17222d38434e58646f7985909ba6b1b5aa9f94897d73685d524854616d7986929eabb7b7ab9f9286796d6154483c3023170b0b1824313e4b5764717d8b9191919191918a7d7063564a3d302d3a4753606d7a879191919191918e8274676976839091919191918f8275737c848b9196999c9d9d9d9b98948f89827971685f554f5c697683909191919191918578717d8b91919191969faab6b1a69b93919191918f8275717c8991919191919191867a6e62564a3e322935414d5965717d8a9191919191919084776c5f53473b2f22150900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161f283039424b545d666f77818a939ba4adb6bab1a89e958c837a71685f564d443b3229201714110e0b101b26313c47525d68737e89949faab5b0a59a8f85796e63584d5864707d8995a2aebab4a79b8f83766a5d5145392c2014070b1824313e4b5764717d85858585858585857d7063564a3d302d3a4753606d7a85858585858585858274676976838585858585858582756a727980858a8d8f9091908f8c88847e7770685f564d4f5c697683858585858585858578717d85858585858e9aa6b3aea2958985858585858275758285858585858585858275695d5146392e25313d4955616e7a8585858585858585857c7063564a3d3023170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161e273039424b545d656e778189929ba4adb6bab1a89e958c837a71685f564d443b322923201d1a171415202b36414c57626c77838e99a4afb7aca1968b80756a5f545c6874818d99a5b1bdb0a4988b7e73665a4e4135291d10040a1724313d4a56636f777777777777777777776e6256493c302d3946525f6b75777777777777777777716667727777777777777777777267686e74797d818284848482807c78726c655e564d444f5b6772777777777777777777746f7777777777808d99a6b3aea195887a77777777777272777777777777777777777165594d413529212d3945515d6a74777777777777777777776e6256493c3023160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c151e273038424b535c656e768089929ba4adb6bab1a89e958c837a71685f564d443b33302d2a2623201d1a242f3a45505b66717c87929da8b3b2a79c92867b70655a5f6b7884909da9b5b9ada194887b6f63574a3e3226190d010915222e3a46525d666a6a6a6a6a6a6a6a6a6a655c51463a2d2a37434e5a636a6a6a6a6a6a6a6a6a6a675f60686a6a6a6a6a6a6a6a6a68605d63696d7174767676767573706c67615b544c443f4b5660686a6a6a6a6a6a6a6a6a69666a6a6a6a72808d99a6b3aea195887a6e6a6a6a6a68686a6a6a6a6a6a6a6a6a6a675f54493d31251d2935414d5862696a6a6a6a6a6a6a6a6a6a655c51463a2d21150800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151e262f38414a535c656d768089929ba4acb5bab1a89e958c837a71685f564d443f3c393633302d2a262329343f4a55606b75818c97a2adb8aea3988d82776c61636f7b8894a0acb9b6a99d9185786c5f53473b2e22160a0006121e2a36414b545b5e5e5e5e5e5e5e5e5e5e5a534a40352926323d4851595d5e5e5e5e5e5e5e5e5e5c56575c5e5e5e5e5e5e5e5e5e5c5652585d616567696a6a6a696664605b565049423a404c58636c6e6e6e6e6e6e6e6e6e6d655e5e5e6672808d99a6b3aea195887a6e615e5e5e5c5c5e5e5e5e5e5e5e5e5e5e5b554d43382c201925313c4750585d5e5e5e5e5e5e5e5e5e5e5a534a4035291d11050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c141d262f38414a535b646d768089929aa3acb5bab1a89e958c837a71685f564f4c4845423f3c393633302d2d38434e59646f7a85909ba6b1b4a99e94897d726766727e8b97a4b0bcb2a69a8e8275685c5044372b1f120600020e19242f3942494f515151515151515151514e4941382e24212c363f474d515151515151515151514f4b4c50515151515151515151504b474c5155585a5c5d5d5d5c5a5754504b453e3836424f5c68757b7b7b7b7b7b7b7b7b776b5e51596672808d99a6b3aea195887a6e615451515050515151515151515151514f4b433b31261b141f2a353e464d50515151515151515151514e4941382e24180d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d262f384149525b646d768088919aa3abb1b1b1a89e958c837a71685f5b5855524f4c4845423f3c3936333d48535e69737e8a959fabb6b0a59a8f84796e6a76838f9ba7b3bbafa3968a7d7165594c4034281b0f03000008131d2730383e4244444444444444444444423e372f261c1a242d353c4144444444444444444444433f404344444444444444444443403b4145494c4e4f5050504f4d4b48443f39342d36434f5c6976838989898989898985786b5e52596672808d99a6b3aea195887a6e61544744434344444444444444444444433f3931291f150e19232c353c414444444444444444444444423e372f261c12070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d262f374049525b646d767e889199a2a5a5a5a5a59e958c837a716b6764615e5b5855524f4c4845423f3c414c57626d78838e99a4afb6aca0968b80756d7986929fabb7b8ab9f93877a6e6255493d3124180c000000010b151e262d32363737373737373737373736322d261d14121b242b3135373737373737373737373633343737373737373737373737343035393c3f414343434342413e3b38332e282936434f5c6976839095959595959285786b5e52596672808d99a6b3aea195887a6e6154473b37373737373737373737373736332e2720170d07111a232a3035373737373737373737373736322d261d140b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d252e374049525b646c757e87909898989898989898958c847a7774716e6b6764615e5b5855524f4c484546515c66717c88939ea9b3b2a79c91867b717d8a96a2aebab4a89c9083776b5e5246392d21140800000000030c141b2226292b2b2b2b2b2b2b2b2b2b2926211b140b0912192025292a2b2b2b2b2b2b2b2b2b2a27282a2b2b2b2b2b2b2b2b2b2a2724292d303335363737373634322f2c27221d2936434f5c697683909da2a2a29f9285786b5e52596672808d99a6b3aea195887a6e6154473b2e2a2b2b2b2b2b2b2b2b2b2b2a27231d160e05000811181f24282a2b2b2b2b2b2b2b2b2b2b2926211b140b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b131c252e374049525a636c757e878b8b8b8b8b8b8b8b8b8b8b8784817d7a7774716e6b6764615e5b5855524f4c55606b76818c97a2adb8aea3988d8276818d99a6b2bdb1a5988c8073675b4f42362a1d11050000000000020a10161a1d1e1e1e1e1e1e1e1e1e1e1d1a1610090200080e14191c1e1e1e1e1e1e1e1e1e1e1d1b1b1d1e1e1e1e1e1e1e1e1e1d1b181c20242628292a2a2a292825231f1b171c2936434f5c697683909da9acac9f9285786b5e52596672808d99a6acaca195887a6e6154473b2e211e1e1e1e1e1e1e1e1e1e1d1b17120b04000000070e14181c1e1e1e1e1e1e1e1e1e1e1e1d1a1610090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e374048515a636c757d7d7d7d7d7d7d7d7d7d7d808a908d8a8784817d7a7774716e6b6764615e5b585559656f7a86919ca7b2b4a99e93887d84919da9b5baaea195897c7064574b3f33261a0e0100000000000000050a0e1011111111111111111111100e0a050000000003090d1011111111111111111111110e0f11111111111111111111110f0c1014171a1b1d1d1d1d1c1b1916130f101c2936434f5c697683909d9f9f9f9f9285786b5e52596672808d999f9f9f9f95887a6e6154473b2e2114111111111111111111100e0b0600000000000003080c0f1111111111111111111111100e0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e363f48515a636c717171717171717171717179848f999693908d8a8784817d7a7774716e6b6764615e5e6974808a95a0abb6b0a59a8f848894a0adb9b7aa9e9285796d6054483b2f23170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080b0d0f10101010100e0c0a0703101c2936434f5c6976839092929292929285786b5e52596672808d929292929292887a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c242d363f48515a616464646464646464646467727d89949e9f9c999693908d8a8784817d7a7774716e6b67646d78848f99a5afb6aba0968e9099a4b0bcb3a79a8e8275695d5144382c201307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976838585858585858585786b5e525966728085858585858585857a6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a121b242d363f48505557575757575757575757616c77828d98a3a9a5a29f9c999693908d8a8784817d7a7774716e727d88939ea9b4b2a89f9b9ba2abb5bcb0a3978b7e72665a4d4135281c10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424f5b6873787878787878787878756a5e51586570787878787878787878766c6053473a2d21140700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d363e45494b4b4b4b4b4b4b4b4b4f5a65707b86929da8b2afaca9a5a29f9c999693908d8a8784817d7a7776828d98a3aebab1aba7a8acb3bdb9aca094887b6f62564a3d3125190c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a27333f4b5761696b6b6b6b6b6b6b6b6b6a63594d545f676b6b6b6b6b6b6b6b6b6b645b5044382b1f12060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242c33393c3e3e3e3e3e3e3e3e3e49545f6a75808b96a1acb7b8b5b2afaca9a5a29f9c999693908d8a8784817d86929facb9bcb6b4b4b8bec2b5a99d9084776b5f53463a2e211509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232f3a454f575d5e5e5e5e5e5e5e5e5e5e5951474d555c5e5e5e5e5e5e5e5e5e5e5a52493e33271b0f03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121a22282d30313131313131313137424d58636e7985909ba6aeb1b4b7bbb8b5b2afaca9a5a29f9c999693908d8a8a94a0adb9c6c3c1c1c4c9beb2a5998d8174685c4f43372b1e12060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121e29333d464c51525252525252525252514d473f444b50525252525252525252514e4840372d22170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810171c21232424242424242426313c47525d68737e89949ea1a5a8abaeb1b5b8bbb8b5b2afaca9a5a29f9c9996969ca6b1bdc9cfcdced0c7bbaea2968a7d7165584c4033271b0e0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c17212b343b414445454545454545454544423c35393f4345454545454545454545423d372e251b10050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b11141718181818181818202b36414c57626c77838e9295989b9fa2a5a8abafb2b5b8bbb8b5b2afaca9a5a3a3a7aeb8c2cdd9dadad0c4b7ab9f92867a6d6155483c3024170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f1922293035373838383838383838383835312b2e34373838383838383838383836322c251c1309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005080a0b0b0b0b0b0b0e19242f3a45505b66717c8285898c8f9295999c9fa2a6a9acafb3b6b9bbb8b5b2afafb2b8c0cad4dfe3d9ccc0b4a89b8f83766a5e5145392d201408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000710181f24282b2b2b2b2b2b2b2b2b2b2b29252023282a2b2b2b2b2b2b2b2b2b2b2a26211a130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131e29343f4a55606a7275797c808386898c909396999da0a3a6a9adb0b3b6babcbcbfc3cacdd0d3d7d5c9bdb0a4988c8073675a4e4235291d11040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d13181c1e1f1f1f1f1f1f1f1f1f1e1d1914171b1e1f1f1f1f1f1f1f1f1f1f1d1a15100901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c17222d38434e586166696c707376797d8083878a8d9093979a9da0a4a7aaadb0b4b7babdc1c4c7cacdc6b9ada194887c6f63574b3e3226190d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080c101112121212121212121212100d090b0f1112121212121212121212100e0a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c27323c464f565a5d6063676a6d7074777a7d8184878a8e9194979a9ea1a4a7abaeb1b4b7bbbec1c2b6aa9d9185786c6054473b2f22160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15202b343d454a4d5154575a5e6164676a6e7174777a7d8285888b8e9194989b9ea1a5a8abaeb2b5b8b3a69a8e8275695c5044382b1f130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e19222b33393e4144484b4e5154585b5e6165686b6e7175787b7e8285888b8f9295989c9fa2a5a8acafa3978a7d7165594d4034281b0f03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101921282e3235383b3e4245484b4f5255585b5f6265686b6f7275787c808286898c8f9396999c9fa3a093877a6e6256493d3124180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000710171d2225282c2f3235383c3f4245494c4f5256595c5f6266696c6f7376797c808386898d909396999084776b5e52463a2d2115080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050c1116191c1f2226292c2f3336393c404346494c505356595d6063666a6d7073767a7d8184878a8d8c8074675b4f42362a1e11050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005090d101316191d2023262a2d3033363a3d4043474a4d5054575a5d6064676a6d7074777a7d81847c7064584b3f33261a0e020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070a0d1014171a1d2124272a2d3134373a3d4144474a4e5154575a5e6164676b6e717477776c6054483c2f23170b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104070a0e1114171b1e2124272b2e3134383b3e4144484b4e5155585b5e6165686b6b655b5044382c2013070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104080b0e1115181b1e2225282b2e3235383b3f4245484b4f5255585c5f5f5b53493f33281c1004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205080c0f1215181c1f2225292c2f3236393c3f4246494c4f52524f4941382d22170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206090c0f1316191c202326292c303336393d40434545433e372f261b11060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060a0d1013161a1d2023262a2d303337393937332d251d140a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070a0d1014171a1d2124272a2c2c2a27221b130b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104070b0e1114171b1e1f1f1e1b1610090100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205080b0e111313110e0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + m_StreamData: + serializedVersion: 2 + offset: 0 + size: 0 + path: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF.asset.meta new file mode 100644 index 0000000..eb77f19 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Unity SDF.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c9adb1f542a93ae489bacfeae21e8394 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets.meta new file mode 100644 index 0000000..294a767 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3ac6db30e75b49b282a3564110579f27 +folderAsset: yes +timeCreated: 1480573362 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/Default Sprite Asset.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/Default Sprite Asset.asset new file mode 100644 index 0000000..46602c0 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/Default Sprite Asset.asset @@ -0,0 +1,351 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2102322 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TMPro/Sprite + m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 2800000, guid: a0fc465d6cf04254a2938578735e2383, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _ColorMask: 15 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _UseUIAlphaClip: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 84a92b25f83d49b9bc132d206b370281, type: 3} + m_Name: Default Sprite Asset + m_EditorClassIdentifier: + hashCode: 826640882 + material: {fileID: 2102322} + materialHashCode: 0 + m_Version: 1.1.0 + spriteSheet: {fileID: 2800000, guid: a0fc465d6cf04254a2938578735e2383, type: 3} + m_SpriteCharacterTable: + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 0 + m_Scale: 1.25 + m_Name: Smiley + m_HashCode: -992563897 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 1 + m_Scale: 1.25 + m_Name: Default Sprite Asset_1 + m_HashCode: -1731209668 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 2 + m_Scale: 1.25 + m_Name: Wink + m_HashCode: 3171611 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 3 + m_Scale: 1.25 + m_Name: Default Sprite Asset_3 + m_HashCode: -1731209666 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 4 + m_Scale: 1.25 + m_Name: Whaaat! + m_HashCode: -2000778261 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 5 + m_Scale: 1.25 + m_Name: Default Sprite Asset_5 + m_HashCode: -1731209672 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 6 + m_Scale: 1.25 + m_Name: Default Sprite Asset_6 + m_HashCode: -1731209669 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 7 + m_Scale: 1.25 + m_Name: Default Sprite Asset_7 + m_HashCode: -1731209670 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 8 + m_Scale: 1.25 + m_Name: Default Sprite Asset_8 + m_HashCode: -1731209675 + - m_ElementType: 2 + m_Unicode: 59801 + m_GlyphIndex: 9 + m_Scale: 1.25 + m_Name: Unity Logo + m_HashCode: -1711635116 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 10 + m_Scale: 1.25 + m_Name: Default Sprite Asset_12 + m_HashCode: -1295344242 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 11 + m_Scale: 1.25 + m_Name: Default Sprite Asset_13 + m_HashCode: -1295344241 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 12 + m_Scale: 1.25 + m_Name: Default Sprite Asset_14 + m_HashCode: -1295344248 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 13 + m_Scale: 1.25 + m_Name: Default Sprite Asset_15 + m_HashCode: -1295344247 + m_SpriteGlyphTable: + - m_Index: 0 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 1 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 2 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 3 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 4 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 5 + m_Metrics: + m_Width: 127 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 256 + m_Width: 127 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 6 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 7 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 8 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 128 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 9 + m_Metrics: + m_Width: 384 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 384 + m_GlyphRect: + m_X: 128 + m_Y: 128 + m_Width: 384 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 10 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 11 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 0 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 12 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 0 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 13 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 106.14 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 0 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + spriteInfoList: [] + fallbackSpriteAssets: [] diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/Default Sprite Asset.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/Default Sprite Asset.asset.meta new file mode 100644 index 0000000..372a414 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/Default Sprite Asset.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fbef3c704dce48f08a44612d6c856c8d +timeCreated: 1454544381 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/DropCap Numbers.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/DropCap Numbers.asset new file mode 100644 index 0000000..78b4994 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/DropCap Numbers.asset @@ -0,0 +1,406 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2155154 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TextMeshPro/Sprite + m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _ColorMask: 15 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _UseUIAlphaClip: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} +--- !u!21 &2168720 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TextMeshPro/Sprite + m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 2800000, guid: fd09957580ac4326916010f1f260975b, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _ColorMask: 15 + - _CullMode: 0 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _UseUIAlphaClip: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 84a92b25f83d49b9bc132d206b370281, type: 3} + m_Name: DropCap Numbers + m_EditorClassIdentifier: + hashCode: 874831499 + material: {fileID: 2168720} + materialHashCode: 0 + m_Version: 1.1.0 + m_FaceInfo: + m_FamilyName: + m_StyleName: + m_PointSize: 0 + m_Scale: 0 + m_LineHeight: 0 + m_AscentLine: 0 + m_CapLine: 0 + m_MeanLine: 0 + m_Baseline: 0 + m_DescentLine: 0 + m_SuperscriptOffset: 0 + m_SuperscriptSize: 0 + m_SubscriptOffset: 0 + m_SubscriptSize: 0 + m_UnderlineOffset: 0 + m_UnderlineThickness: 0 + m_StrikethroughOffset: 0 + m_StrikethroughThickness: 0 + m_TabWidth: 0 + spriteSheet: {fileID: 2800000, guid: fd09957580ac4326916010f1f260975b, type: 3} + m_SpriteCharacterTable: + - m_ElementType: 2 + m_Unicode: 48 + m_GlyphIndex: 0 + m_Scale: 1 + m_Name: Zero + m_HashCode: 3342626 + - m_ElementType: 2 + m_Unicode: 49 + m_GlyphIndex: 1 + m_Scale: 1 + m_Name: One + m_HashCode: 86532 + - m_ElementType: 2 + m_Unicode: 50 + m_GlyphIndex: 2 + m_Scale: 1 + m_Name: Two + m_HashCode: 89964 + - m_ElementType: 2 + m_Unicode: 51 + m_GlyphIndex: 3 + m_Scale: 1 + m_Name: Three + m_HashCode: 98777518 + - m_ElementType: 2 + m_Unicode: 52 + m_GlyphIndex: 4 + m_Scale: 1 + m_Name: Four + m_HashCode: 2627086 + - m_ElementType: 2 + m_Unicode: 53 + m_GlyphIndex: 5 + m_Scale: 1 + m_Name: Five + m_HashCode: 2629180 + - m_ElementType: 2 + m_Unicode: 54 + m_GlyphIndex: 6 + m_Scale: 1 + m_Name: Six + m_HashCode: 91746 + - m_ElementType: 2 + m_Unicode: 55 + m_GlyphIndex: 7 + m_Scale: 1 + m_Name: Seven + m_HashCode: 99766859 + - m_ElementType: 2 + m_Unicode: 56 + m_GlyphIndex: 8 + m_Scale: 1 + m_Name: Eight + m_HashCode: 78732407 + - m_ElementType: 2 + m_Unicode: 57 + m_GlyphIndex: 9 + m_Scale: 1 + m_Name: Nine + m_HashCode: 2898988 + - m_ElementType: 2 + m_Unicode: 65534 + m_GlyphIndex: 10 + m_Scale: 2.2 + m_Name: 0-Large + m_HashCode: 1182309024 + - m_ElementType: 2 + m_Unicode: 65534 + m_GlyphIndex: 11 + m_Scale: 2.2 + m_Name: 1-Large + m_HashCode: 451176033 + - m_ElementType: 2 + m_Unicode: 65534 + m_GlyphIndex: 12 + m_Scale: 2.2 + m_Name: 2-Large + m_HashCode: -534322270 + - m_ElementType: 2 + m_Unicode: 65534 + m_GlyphIndex: 13 + m_Scale: 2.2 + m_Name: 3-Large + m_HashCode: -1265455261 + m_SpriteGlyphTable: + - m_Index: 0 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300000, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 1 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300002, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 2 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300004, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 3 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300006, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 4 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300008, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 5 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300010, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 6 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300012, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 7 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300014, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 8 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 128 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300016, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 9 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 128 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300018, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 10 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 112.25 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300000, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 11 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 47.5 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300002, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 12 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 47.5 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300004, guid: fd09957580ac4326916010f1f260975b, type: 3} + - m_Index: 13 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 2.9 + m_HorizontalBearingY: 47.5 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 21300006, guid: fd09957580ac4326916010f1f260975b, type: 3} + spriteInfoList: [] + fallbackSpriteAssets: [] diff --git a/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/DropCap Numbers.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/DropCap Numbers.asset.meta new file mode 100644 index 0000000..fd3f68f --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Sprite Assets/DropCap Numbers.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 14aa93acbb234d16aaef0e8b46814db6 +timeCreated: 1464163339 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes.meta new file mode 100644 index 0000000..8520f88 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: db1090641b3241f6995b587eb21637bc +folderAsset: yes +timeCreated: 1436068007 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/01- Single Line TextMesh Pro.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/01- Single Line TextMesh Pro.unity new file mode 100644 index 0000000..8bc62bf --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/01- Single Line TextMesh Pro.unity @@ -0,0 +1,380 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 5cb611ed8508d904ebba194afcee9c98, + type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &42794038 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 42794043} + - component: {fileID: 42794042} + - component: {fileID: 42794039} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &42794039 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 42794038} + m_Enabled: 1 +--- !u!20 &42794042 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 42794038} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 100 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &42794043 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 42794038} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -50} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1866137809 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1866137810} + - component: {fileID: 1866137813} + - component: {fileID: 1866137811} + m_Layer: 10 + m_Name: Simple Example + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1866137810 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1866137809} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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} + m_SizeDelta: {x: 100, y: 7.4} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1866137811 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1866137809} + 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: Simple example of text created with <#80ff80>TextMesh + <#8080ff>Pro! + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 36 + m_fontSizeBase: 36 + 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.3 + 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 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1866137813} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1866137813 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1866137809} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/01- Single Line TextMesh Pro.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/01- Single Line TextMesh Pro.unity.meta new file mode 100644 index 0000000..1667191 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/01- Single Line TextMesh Pro.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 2ac8cf212df6445e8aebbe3cb832e993 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/02 - Multi-line TextMesh Pro.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/02 - Multi-line TextMesh Pro.unity new file mode 100644 index 0000000..0e7e3e6 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/02 - Multi-line TextMesh Pro.unity @@ -0,0 +1,384 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 2bf015e748557a84c8fa6bfc44e4d685, + type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1079079952 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079079957} + - component: {fileID: 1079079956} + - component: {fileID: 1079079953} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1079079953 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 +--- !u!20 &1079079956 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 100 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1079079957 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -40} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1915181340 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1915181346} + - component: {fileID: 1915181343} + - component: {fileID: 1915181341} + m_Layer: 0 + m_Name: Multi Line TextMesh Pro + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1915181341 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1915181340} + 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: 'Example of <#ff8000>multiple + + <#00ff00>lines of text + created + + with <#80ff80>TextMesh <#8080ff>Pro!' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 36 + m_fontSizeBase: 36 + 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: 0 + 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.3 + 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 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1915181343} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1915181343 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1915181340} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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!224 &1915181346 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1915181340} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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} + m_SizeDelta: {x: 31.685612, y: 12.5} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/02 - Multi-line TextMesh Pro.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/02 - Multi-line TextMesh Pro.unity.meta new file mode 100644 index 0000000..6729ee6 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/02 - Multi-line TextMesh Pro.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 251716609f634449bfe8ce75c0ed78fe +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/03 - Line Justification.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/03 - Line Justification.unity new file mode 100644 index 0000000..2fa8553 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/03 - Line Justification.unity @@ -0,0 +1,896 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 56510bd4b3627c840a063bd270324c89, + type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &674168707 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 674168713} + - component: {fileID: 674168710} + - component: {fileID: 674168708} + m_Layer: 0 + m_Name: 1 - Left Justified + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &674168708 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 674168707} + 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: 'This block of text is + + <#8080ff>Left justified.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 36 + m_fontSizeBase: 36 + 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.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 674168710} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &674168710 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 674168707} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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!224 &674168713 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 674168707} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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: 10} + m_SizeDelta: {x: 35, y: 9.713184} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1079079952 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079079957} + - component: {fileID: 1079079956} + - component: {fileID: 1079079953} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1079079953 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 +--- !u!20 &1079079956 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 100 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1079079957 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -10, z: -60} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1191214184 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1191214190} + - component: {fileID: 1191214186} + - component: {fileID: 1191214185} + m_Layer: 0 + m_Name: 3 - Right Justified + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1191214185 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1191214184} + 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: 'This block of text is + + <#80ff80>Right justified.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 4 + 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.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1191214186} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1191214186 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1191214184} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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!224 &1191214190 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1191214184} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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} + m_AnchoredPosition: {x: 0, y: -10} + m_SizeDelta: {x: 35, y: 9.713184} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1369999148 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1369999154} + - component: {fileID: 1369999151} + - component: {fileID: 1369999149} + m_Layer: 0 + m_Name: 2 - Center Justified + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1369999149 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1369999148} + 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: 'This block of text is + + <#ff8000>Center justified.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 36 + m_fontSizeBase: 36 + 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: 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.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1369999151} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1369999151 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1369999148} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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!224 &1369999154 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1369999148} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + 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} + m_SizeDelta: {x: 35, y: 9.713184} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1915181340 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1915181346} + - component: {fileID: 1915181343} + - component: {fileID: 1915181341} + m_Layer: 0 + m_Name: 4 - Justified + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1915181341 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1915181340} + 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: This block of text is <#f0af80>Justified on the left and right + side. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 8 + 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.5 + 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.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1915181343} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1915181343 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1915181340} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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!224 &1915181346 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1915181340} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 4 + 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: -23.53233} + m_SizeDelta: {x: 35, y: 15.065462} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/03 - Line Justification.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/03 - Line Justification.unity.meta new file mode 100644 index 0000000..278bc55 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/03 - Line Justification.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 21a509e1d3cd49978623fa564adb6f02 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/04 - Word Wrapping.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/04 - Word Wrapping.unity new file mode 100644 index 0000000..173d5ed --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/04 - Word Wrapping.unity @@ -0,0 +1,379 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 088d960ecbf7a1d4a8f94993c066a0ff, + type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1079079952 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079079957} + - component: {fileID: 1079079956} + - component: {fileID: 1079079953} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1079079953 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 +--- !u!20 &1079079956 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 100 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1079079957 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -40} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1099104776 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1099104782} + - component: {fileID: 1099104779} + - component: {fileID: 1099104777} + m_Layer: 0 + m_Name: Word Wrapping + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1099104777 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1099104776} + 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: This is an example showing how TextMesh Pro! can handle <#ffff00>word wrapping. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 36 + m_fontSizeBase: 36 + 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.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1099104779} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1099104779 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1099104776} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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!224 &1099104782 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1099104776} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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} + m_SizeDelta: {x: 38.7609, y: 22.810886} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/04 - Word Wrapping.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/04 - Word Wrapping.unity.meta new file mode 100644 index 0000000..27f8627 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/04 - Word Wrapping.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 8f7137eacd7042d5b17ef0efe5e744f5 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/05 - Style Tags.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/05 - Style Tags.unity new file mode 100644 index 0000000..f4a68e8 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/05 - Style Tags.unity @@ -0,0 +1,1017 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &133236929 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 133236934} + - component: {fileID: 133236932} + - component: {fileID: 133236930} + - component: {fileID: 133236931} + - component: {fileID: 133236933} + m_Layer: 0 + m_Name: TextMesh Pro - Caption + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!114 &133236930 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 133236929} + 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_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: '*This is a partial list of all the Rich Text Tags available.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 28 + m_fontSizeBase: 28 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 24 + m_fontSizeMax: 96 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 257 + m_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 0 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 2 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 60 + spriteCount: 0 + spaceCount: 11 + wordCount: 12 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 133236933} + m_maskType: 0 +--- !u!222 &133236931 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 133236929} + m_CullTransparentMesh: 0 +--- !u!33 &133236932 +MeshFilter: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 133236929} + m_Mesh: {fileID: 0} +--- !u!23 &133236933 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 133236929} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!224 &133236934 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 133236929} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + 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: 3, y: -32.8} + m_SizeDelta: {x: 128, y: 10} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &347737868 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 347737873} + - component: {fileID: 347737870} + - component: {fileID: 347737869} + - component: {fileID: 347737872} + - component: {fileID: 347737871} + m_Layer: 0 + m_Name: TextMesh Pro - Styles + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!114 &347737869 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347737868} + 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_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: '<#a0ffa0>Basic Style Tags* available in TextMesh<#0080ff>Pro + + Normal + + Bold<<#ffff00>b> <<#ffff00>/b> + + Italics<<#ffff00>i> <<#ffff00>/i> + + Underline<<#ffff00>u> <<#ffff00>/u> + + Strikethrough<<#ffff00>s> <<#ffff00>/s> + + Superscript - X3 -<<#ffff00>sup> <<#ffff00>/sup> + + Subscript - H2O -<<#ffff00>sub> <<#ffff00>/sub> + + Text Highlighting<<#ffff00>mark=#ffff8000> + <<#ffff00>/mark> + +' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 48 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 24 + m_fontSizeMax: 96 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 257 + m_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 0 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 2 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 224 + spriteCount: 0 + spaceCount: 30 + wordCount: 36 + linkCount: 0 + lineCount: 9 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 347737871} + m_maskType: 0 +--- !u!33 &347737870 +MeshFilter: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347737868} + m_Mesh: {fileID: 0} +--- !u!23 &347737871 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347737868} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!222 &347737872 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347737868} + m_CullTransparentMesh: 0 +--- !u!224 &347737873 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347737868} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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} + m_AnchoredPosition: {x: 3, y: 0} + m_SizeDelta: {x: 128, y: 59.9} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &642642694 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 642642697} + - component: {fileID: 642642696} + - component: {fileID: 642642695} + m_Layer: 0 + m_Name: TextMeshPro - Styles + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &642642695 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 642642694} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: '<#a0ffa0>Basic Style Tags* available in TextMesh<#0080ff>Pro + + Normal + + Bold<<#ffff00>b> <<#ffff00>/b> + + Italics<<#ffff00>i> <<#ffff00>/i> + + Underline<<#ffff00>u> <<#ffff00>/u> + + Strikethrough<<#ffff00>s> <<#ffff00>/s> + + Superscript - X3 -<<#ffff00>sup> <<#ffff00>/sup> + + Subscript - H2O -<<#ffff00>sub> <<#ffff00>/sub> + + Text Highlighting<<#ffff00>mark=#ffff8000> + <<#ffff00>/mark> + +' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 48 + m_fontSizeBase: 48 + 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_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 642642695} + characterCount: 224 + spriteCount: 0 + spaceCount: 30 + wordCount: 36 + linkCount: 0 + lineCount: 9 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 6a9165d4abc743c469f4e1f2ee39605c, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &642642696 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 642642694} + m_CullTransparentMesh: 0 +--- !u!224 &642642697 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 642642694} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2144055438} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 15} + m_SizeDelta: {x: -40, y: -50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &718714744 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 718714747} + - component: {fileID: 718714746} + - component: {fileID: 718714745} + m_Layer: 0 + m_Name: TextMeshPro - Caption + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &718714745 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 718714744} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: '*Partial list of the Rich Text Tags available in TextMeshPro.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 28 + m_fontSizeBase: 28 + 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_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 718714745} + characterCount: 61 + spriteCount: 0 + spaceCount: 9 + wordCount: 10 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 6a9165d4abc743c469f4e1f2ee39605c, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &718714746 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 718714744} + m_CullTransparentMesh: 0 +--- !u!224 &718714747 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 718714744} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2144055438} + 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.000024437904, y: -300} + m_SizeDelta: {x: 1230, y: 40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1079079952 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079079957} + - component: {fileID: 1079079956} + - component: {fileID: 1079079953} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1079079953 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 +--- !u!20 &1079079956 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 36 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1079079957 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2144055437 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2144055438} + - component: {fileID: 2144055440} + - component: {fileID: 2144055439} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2144055438 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2144055437} + 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_Children: + - {fileID: 642642697} + - {fileID: 718714747} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &2144055439 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2144055437} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &2144055440 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2144055437} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/05 - Style Tags.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/05 - Style Tags.unity.meta new file mode 100644 index 0000000..4934c52 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/05 - Style Tags.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 70615243e2be4a81afaab9bf5d273d65 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/06 - Extra Rich Text Examples.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/06 - Extra Rich Text Examples.unity new file mode 100644 index 0000000..a1e7641 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/06 - Extra Rich Text Examples.unity @@ -0,0 +1,677 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &49570598 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 49570603} + - component: {fileID: 49570602} + - component: {fileID: 49570599} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &49570599 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 49570598} + m_Enabled: 1 +--- !u!20 &49570602 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 49570598} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &49570603 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 49570598} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &74526464 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 74526467} + - component: {fileID: 74526466} + - component: {fileID: 74526465} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &74526465 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 74526464} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &74526466 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 74526464} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &74526467 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 74526464} + 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_Children: + - {fileID: 1578794323} + - {fileID: 826978362} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &826978359 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 826978362} + - component: {fileID: 826978361} + - component: {fileID: 826978360} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &826978360 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826978359} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: The larger title line is done using the <<#a0ffa0>size=120%> tag. + Alignment of the tag examples is done using the <<#a0ffa0>pos=xx.x> tag. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 24 + m_fontSizeBase: 24 + 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_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 826978360} + characterCount: 120 + spriteCount: 0 + spaceCount: 20 + wordCount: 24 + linkCount: 0 + lineCount: 2 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 6a9165d4abc743c469f4e1f2ee39605c, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &826978361 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826978359} + m_CullTransparentMesh: 0 +--- !u!224 &826978362 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826978359} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 74526467} + 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: -264.95} + m_SizeDelta: {x: 1200, y: 70.1} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &956040813 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 956040817} + - component: {fileID: 956040816} + - component: {fileID: 956040815} + - component: {fileID: 956040814} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &956040814 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 956040813} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &956040815 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 956040813} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &956040816 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 956040813} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &956040817 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 956040813} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1578794322 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1578794323} + - component: {fileID: 1578794325} + - component: {fileID: 1578794324} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1578794323 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1578794322} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 74526467} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 15} + m_SizeDelta: {x: -40, y: -50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1578794324 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1578794322} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: 'Additional <#a0ffa0>Rich Text Tags in TextMesh<#0080ff>Pro! + + all caps<<#ffff00>allcaps> <<#ffff00>/allcaps> + + Example of small caps.<<#ffff00>smallcaps> + <<#ffff00>/smallcaps> + + Character spacing<<#ffff00>cspace=0.3em> + <<#ffff00>/cspace> + + Monospaced<<#ffff00>mspace=1em> <<#ffff00>/mspace> + + Line height<<#ffff00>line-height=75> <<#ffff00>/line-height> + + No Line-Break<<#ffff00>nobr> <<#ffff00>/nobr> + + Size Smaller / Bigger<<#ffff00>size=75%> + <<#ffff00>size=1.5em> <<#ffff00>/size>' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 42 + m_fontSizeBase: 42 + 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_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1578794324} + characterCount: 316 + spriteCount: 0 + spaceCount: 30 + wordCount: 44 + linkCount: 0 + lineCount: 8 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 6a9165d4abc743c469f4e1f2ee39605c, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1578794325 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1578794322} + m_CullTransparentMesh: 0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/06 - Extra Rich Text Examples.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/06 - Extra Rich Text Examples.unity.meta new file mode 100644 index 0000000..d4d5a2e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/06 - Extra Rich Text Examples.unity.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: 39a1fa96ad2a449b908fca29d4297a74 +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/07 - Superscript & Subscript Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/07 - Superscript & Subscript Example.unity new file mode 100644 index 0000000..8ad4bc2 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/07 - Superscript & Subscript Example.unity @@ -0,0 +1,383 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 955cc2a4737565a4293837beb489fb59, + type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &347737868 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 347737872} + - component: {fileID: 347737871} + - component: {fileID: 347737869} + m_Layer: 0 + m_Name: TextMesh Pro - Styles + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &347737869 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347737868} + 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: '9x<#00ff00>3 + 4x<#00ff00>2 + + 2x + 4 = 0 + + <#ffff00><#ff8000>Propane + = C<#ffff00>3H<#ffff00>8' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 48 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 24 + m_fontSizeMax: 96 + 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: 2 + 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 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 347737871} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &347737871 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347737868} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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!224 &347737872 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347737868} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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.37905407, y: 0} + m_SizeDelta: {x: 48, y: 14} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1079079952 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079079957} + - component: {fileID: 1079079956} + - component: {fileID: 1079079953} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1079079953 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 +--- !u!20 &1079079956 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 100 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1079079957 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -50} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/07 - Superscript & Subscript Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/07 - Superscript & Subscript Example.unity.meta new file mode 100644 index 0000000..3268424 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/07 - Superscript & Subscript Example.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 03ec435d4b7140e9b2d87f79136d8374 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/08 - Improved Text Alignment.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/08 - Improved Text Alignment.unity new file mode 100644 index 0000000..1f690f9 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/08 - Improved Text Alignment.unity @@ -0,0 +1,544 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &146169812 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 146169815} + - component: {fileID: 146169814} + - component: {fileID: 146169813} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &146169813 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 146169812} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &146169814 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 146169812} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 1848275637} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &146169815 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 146169812} + 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_Children: + - {fileID: 1063675290} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &1063675289 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1063675290} + - component: {fileID: 1063675292} + - component: {fileID: 1063675291} + - component: {fileID: 1063675293} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1063675290 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1063675289} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 146169815} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 24.999998, y: 10} + m_SizeDelta: {x: -50, y: -20} + m_Pivot: {x: 0.00000006123446, y: -9.313226e-10} +--- !u!114 &1063675291 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1063675289} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: "<#ffffff>Multiple<#80f0ff> Alignment + per text object\nThe + <<#ffffa0>align> tag in TextMesh<#40a0ff>Pro provides the ability + to control the alignment of lines and paragraphs which is essential when working + with text. \n\nYou may want some block of text to be <#80f0ff>left + aligned <<#ffffa0>align=<#80f0ff>left> which is sort of + the standard.\n\n<#ffffa0>\"Using <#80f0ff>Center Alignment + <<#ffffa0>align=<#80f0ff>center> for a title or displaying a quote + is another good example of text alignment.\"\n\n<#80f0ff>Right + Alignment <<#ffffa0>align=<#80f0ff>right> can be useful + to create contrast between lines and paragraphs of text.\n\n<#80f0ff>Justified + Alignment <<#ffffa0>align=<#80f0ff>justified> results + in text that is flush on both the left and right margins. Used well, justified + type can look clean and classy.\n\n<#ffffa0>\"Text formatting + and alignment has a huge impact on how people will read and perceive your text.\"\n- + Stephan Bouchard" + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 32 + m_fontSizeBase: 32 + 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_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: -18 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1063675291} + characterCount: 773 + spriteCount: 0 + spaceCount: 129 + wordCount: 128 + linkCount: 0 + lineCount: 19 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 6a9165d4abc743c469f4e1f2ee39605c, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1063675292 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1063675289} + m_CullTransparentMesh: 0 +--- !u!114 &1063675293 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1063675289} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 21256c5b62f346f18640dad779911e20, type: 3} + m_Name: + m_EditorClassIdentifier: + ShowCharacters: 0 + ShowWords: 0 + ShowLinks: 0 + ShowLines: 0 + ShowMeshBounds: 0 + ShowTextBounds: 0 + ObjectStats: 'Characters: 773 Words: 128 Spaces: 129 Sprites: 0 Links: 0 + + Lines: 19 Pages: 1' + m_TextComponent: {fileID: 1063675291} + m_Transform: {fileID: 1063675290} +--- !u!1 &1728718679 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1728718683} + - component: {fileID: 1728718682} + - component: {fileID: 1728718681} + - component: {fileID: 1728718680} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1728718680 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1728718679} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &1728718681 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1728718679} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1728718682 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1728718679} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1728718683 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1728718679} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1848275633 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1848275638} + - component: {fileID: 1848275637} + - component: {fileID: 1848275634} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1848275634 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1848275633} + m_Enabled: 1 +--- !u!20 &1848275637 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1848275633} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1848275638 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1848275633} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -48.4, y: 1, z: -75.97} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/08 - Improved Text Alignment.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/08 - Improved Text Alignment.unity.meta new file mode 100644 index 0000000..b8e0fef --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/08 - Improved Text Alignment.unity.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: 5fe2257128d9401fad0790f581dc8a6f +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/09 - Margin Tag Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/09 - Margin Tag Example.unity new file mode 100644 index 0000000..a0f71dc --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/09 - Margin Tag Example.unity @@ -0,0 +1,945 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &4849554 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4849557} + - component: {fileID: 4849556} + - component: {fileID: 4849555} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &4849555 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4849554} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &4849556 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4849554} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 1 + m_Camera: {fileID: 703237851} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &4849557 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4849554} + 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_Children: + - {fileID: 1080092504} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &268121704 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 268121708} + - component: {fileID: 268121707} + - component: {fileID: 268121706} + - component: {fileID: 268121705} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &268121705 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 268121704} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &268121706 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 268121704} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &268121707 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 268121704} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &268121708 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 268121704} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &454260780 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 454260781} + - component: {fileID: 454260783} + - component: {fileID: 454260782} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &454260781 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 454260780} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1080092504} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: -0.000000046100467, y: 1} +--- !u!114 &454260782 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 454260780} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: '<#80ff80>The TextMesh<#40A0FF>Pro<#80ff80> + Margin Tag + + Example of using the <<#FFFF00>margin=5%> tag + which defines the left and right margin of a line or paragraph of text. + + + You can also use the <<#FFFF00>margin left=15%> tag to + independently control the left margin. + + + Or use the <<#FFFF00>margin right=15%> tag to control + the right margin.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 48 + m_fontSizeBase: 48 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 8 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_isAlignmentEnumConverted: 0 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: -5 + m_lineSpacingMax: 0 + m_paragraphSpacing: -10 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 454260782} + characterCount: 285 + spriteCount: 0 + spaceCount: 50 + wordCount: 52 + linkCount: 0 + lineCount: 9 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 6a9165d4abc743c469f4e1f2ee39605c, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &454260783 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 454260780} + m_CullTransparentMesh: 0 +--- !u!1 &703237847 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 703237852} + - component: {fileID: 703237851} + - component: {fileID: 703237848} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &703237848 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 703237847} + m_Enabled: 1 +--- !u!20 &703237851 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 703237847} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 36 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &703237852 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 703237847} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1080092503 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1080092504} + - component: {fileID: 1080092505} + m_Layer: 0 + m_Name: Frame + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1080092504 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1080092503} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 454260781} + - {fileID: 1205717531} + m_Father: {fileID: 4849557} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1080092505 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1080092503} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 20 + m_Right: 20 + m_Top: 10 + m_Bottom: 10 + m_ChildAlignment: 0 + m_Spacing: 25 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!1 &1205717530 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1205717531} + - component: {fileID: 1205717533} + - component: {fileID: 1205717532} + m_Layer: 0 + m_Name: TextMeshPro Text (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1205717531 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1205717530} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1080092504} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1205717532 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1205717530} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: The margin tag can be defined in <#80ff80>pixel units (px), <#80ff80>font + units (em) and as <#80ff80>percentage (%) of the width of the + text container. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 24 + m_fontSizeBase: 24 + 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_isAlignmentEnumConverted: 0 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.5 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1205717532} + characterCount: 124 + spriteCount: 0 + spaceCount: 23 + wordCount: 23 + linkCount: 0 + lineCount: 2 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 6a9165d4abc743c469f4e1f2ee39605c, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1205717533 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1205717530} + m_CullTransparentMesh: 0 +--- !u!1 &1562965274 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1562965280} + - component: {fileID: 1562965278} + - component: {fileID: 1562965277} + - component: {fileID: 1562965275} + - component: {fileID: 1562965279} + m_Layer: 0 + m_Name: TextMeshPro + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!114 &1562965275 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562965274} + 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_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: '<#80ff80>The TextMesh<#40A0FF>Pro<#80ff80> + Margin Tag + + Example of using the <<#FFFF00>margin=5%> tag + which defines the left and right margin of a line or paragraph of text. + + + You can also use the <<#FFFF00>margin-left=15%> tag to + independently control the left margin. + + + Or use the <<#FFFF00>margin-right=15%> tag to control + the right margin.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 48 + m_fontSizeBase: 48 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 3 + m_isAlignmentEnumConverted: 0 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: -5 + m_lineSpacingMax: 0 + m_paragraphSpacing: -10 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 2, y: 1, z: 2, w: 1} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 285 + spriteCount: 0 + spaceCount: 48 + wordCount: 50 + linkCount: 0 + lineCount: 10 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1562965278} + m_maskType: 0 +--- !u!33 &1562965277 +MeshFilter: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562965274} + m_Mesh: {fileID: 0} +--- !u!23 &1562965278 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562965274} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!222 &1562965279 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562965274} + m_CullTransparentMesh: 0 +--- !u!224 &1562965280 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562965274} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + 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} + m_SizeDelta: {x: 128, y: 72} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/09 - Margin Tag Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/09 - Margin Tag Example.unity.meta new file mode 100644 index 0000000..db68797 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/09 - Margin Tag Example.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 349f38d3606449708c7340d26740e1e2 +timeCreated: 1434495347 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/10 - Bullets & Numbered List Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/10 - Bullets & Numbered List Example.unity new file mode 100644 index 0000000..0aa93b1 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/10 - Bullets & Numbered List Example.unity @@ -0,0 +1,665 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1143834369 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1143834374} + - component: {fileID: 1143834373} + - component: {fileID: 1143834370} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1143834370 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1143834369} + m_Enabled: 1 +--- !u!20 &1143834373 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1143834369} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1143834374 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1143834369} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1303869253 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1303869254} + - component: {fileID: 1303869256} + - component: {fileID: 1303869255} + m_Layer: 0 + m_Name: TMP SubMeshUI [TextMeshPro/Sprite] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1303869254 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1303869253} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1723377477} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: -0.000000013038516, y: 1} +--- !u!114 &1303869255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1303869253} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2168720, guid: 14aa93acbb234d16aaef0e8b46814db6, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 0} + m_spriteAsset: {fileID: 11400000, guid: 14aa93acbb234d16aaef0e8b46814db6, type: 2} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2168720, guid: 14aa93acbb234d16aaef0e8b46814db6, type: 2} + m_isDefaultMaterial: 1 + m_padding: 0 + m_canvasRenderer: {fileID: 1303869256} + m_TextComponent: {fileID: 1723377478} + m_materialReferenceIndex: 2 +--- !u!222 &1303869256 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1303869253} + m_CullTransparentMesh: 0 +--- !u!1 &1487880985 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1487880988} + - component: {fileID: 1487880987} + - component: {fileID: 1487880986} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1487880986 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1487880985} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1487880987 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1487880985} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1487880988 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1487880985} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1527684999 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1527685000} + - component: {fileID: 1527685002} + - component: {fileID: 1527685001} + m_Layer: 0 + m_Name: TMP SubMeshUI [TextMeshPro/Sprite] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1527685000 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1527684999} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1723377477} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: -0.000000013038516, y: 1} +--- !u!114 &1527685001 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1527684999} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2168720, guid: 14aa93acbb234d16aaef0e8b46814db6, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 0} + m_spriteAsset: {fileID: 11400000, guid: 14aa93acbb234d16aaef0e8b46814db6, type: 2} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2168720, guid: 14aa93acbb234d16aaef0e8b46814db6, type: 2} + m_isDefaultMaterial: 1 + m_padding: 0 + m_canvasRenderer: {fileID: 1527685002} + m_TextComponent: {fileID: 1723377478} + m_materialReferenceIndex: 1 +--- !u!222 &1527685002 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1527684999} + m_CullTransparentMesh: 0 +--- !u!1 &1723377476 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1723377477} + - component: {fileID: 1723377479} + - component: {fileID: 1723377478} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1723377477 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1723377476} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1527685000} + - {fileID: 1303869254} + m_Father: {fileID: 1920483573} + 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: -633.5, y: 350} + m_SizeDelta: {x: 1258, y: 700} + m_Pivot: {x: -0.000000013038516, y: 1} +--- !u!114 &1723377478 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1723377476} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: 'This is an example of using the <#ffff80> tag in TextMesh<#40a0ff>Pro + to create bullets and numbered lists. + + + For these bullets, I am making + creative use of the <#ffff80> tag to use sprites instead of plain + bullets or numbers. + + + By using the <#ffff80> + tag, we can indent the text to make room for the sprites. + + + \u2022Multiple levels of indentation is also possible. + + + \u2022This is placeholder text for another sub item in our list. + + + Using the <#ffff80> + tag, we can go back to the previous level of indentation. + + + Despite the sophisticated layout of this text, the use of sprites and indentation, + this is still a single text object.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 35.9 + m_fontSizeBase: 35.9 + 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_isAlignmentEnumConverted: 0 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: -27.4 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 1 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 0 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1723377478} + characterCount: 609 + spriteCount: 0 + spaceCount: 111 + wordCount: 106 + linkCount: 0 + lineCount: 18 + pageCount: 1 + materialCount: 2 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1723377479 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1723377476} + m_CullTransparentMesh: 0 +--- !u!1 &1920483570 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1920483573} + - component: {fileID: 1920483572} + - component: {fileID: 1920483571} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1920483571 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1920483570} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &1920483572 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1920483570} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &1920483573 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1920483570} + 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_Children: + - {fileID: 1723377477} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/10 - Bullets & Numbered List Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/10 - Bullets & Numbered List Example.unity.meta new file mode 100644 index 0000000..8efb961 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/10 - Bullets & Numbered List Example.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3f814e1d12c45568daf3dd9a86a0e61 +timeCreated: 1464165314 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/11 - The Style Tag.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/11 - The Style Tag.unity new file mode 100644 index 0000000..e201900 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/11 - The Style Tag.unity @@ -0,0 +1,554 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &149728873 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 149728878} + - component: {fileID: 149728877} + - component: {fileID: 149728874} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &149728874 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 149728873} + m_Enabled: 1 +--- !u!20 &149728877 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 149728873} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &149728878 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 149728873} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &471852954 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 471852957} + - component: {fileID: 471852956} + - component: {fileID: 471852955} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &471852955 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 471852954} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &471852956 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 471852954} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &471852957 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 471852954} + 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_Children: + - {fileID: 753419227} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &753419226 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 753419227} + m_Layer: 0 + m_Name: Frame + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &753419227 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 753419226} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 840213848} + m_Father: {fileID: 471852957} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &840213847 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 840213848} + - component: {fileID: 840213850} + - component: {fileID: 840213849} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &840213848 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 840213847} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 753419227} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -40, y: -40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &840213849 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 840213847} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: 'The<#80ff80> Style + Tag in TextMesh<#40A0FF>Pro + + The <<#FFFF00>style="custom style name"> tag makes it possible + to define custom styles which combine several tags into a single one for convenience. + + + Using <<#FFFF00>style="H1"> for instance sets the text to <<#FFFF00>size=2em><<#FFFF00>b><<#FFFF00>#40ff80>. + + + H1 H2 H3 + + + Style are defined in the <#80ff80>TMP Default Style Sheet.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 44 + m_fontSizeBase: 44 + 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_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 840213849} + characterCount: 305 + spriteCount: 0 + spaceCount: 50 + wordCount: 53 + linkCount: 0 + lineCount: 11 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &840213850 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 840213847} + m_CullTransparentMesh: 0 +--- !u!1 &1364507600 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1364507604} + - component: {fileID: 1364507603} + - component: {fileID: 1364507602} + - component: {fileID: 1364507601} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1364507601 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1364507600} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &1364507602 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1364507600} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1364507603 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1364507600} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1364507604 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1364507600} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/11 - The Style Tag.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/11 - The Style Tag.unity.meta new file mode 100644 index 0000000..79b7f8a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/11 - The Style Tag.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 84ed36ad77dd4956b2ffe3769f759879 +timeCreated: 1488146780 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/12 - Link Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/12 - Link Example.unity new file mode 100644 index 0000000..908da60 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/12 - Link Example.unity @@ -0,0 +1,779 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &118419819 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 118419820} + - component: {fileID: 118419822} + - component: {fileID: 118419821} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &118419820 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118419819} + 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_Children: + - {fileID: 934502352} + - {fileID: 687778178} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &118419821 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118419819} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 0 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &118419822 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118419819} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 946327971} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &305575714 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 305575718} + - component: {fileID: 305575717} + - component: {fileID: 305575716} + - component: {fileID: 305575715} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &305575715 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 305575714} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &305575716 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 305575714} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &305575717 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 305575714} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &305575718 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 305575714} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &687778177 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 687778178} + - component: {fileID: 687778180} + - component: {fileID: 687778179} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &687778178 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 687778177} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 118419820} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 75} + m_SizeDelta: {x: -100, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &687778179 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 687778177} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Select Words or Links to interact with them or Hold Shift Key to interact + with individual Characters. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 24 + m_fontSizeBase: 24 + 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_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 0 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 687778179} + characterCount: 101 + spriteCount: 0 + spaceCount: 16 + wordCount: 17 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &687778180 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 687778177} + m_CullTransparentMesh: 0 +--- !u!1 &694875406 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 694875407} + - component: {fileID: 694875409} + - component: {fileID: 694875408} + m_Layer: 0 + m_Name: TMP SubMeshUI [Bangers SDF - Drop Shadow] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &694875407 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 694875406} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 934502352} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &694875408 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 694875406} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2100000, guid: f2dcf029949142e28b974630369c8b4e, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2100000, guid: f2dcf029949142e28b974630369c8b4e, type: 2} + m_isDefaultMaterial: 1 + m_padding: 5.96 + m_canvasRenderer: {fileID: 694875409} + m_TextComponent: {fileID: 934502350} + m_materialReferenceIndex: 1 +--- !u!222 &694875409 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 694875406} + m_CullTransparentMesh: 0 +--- !u!1 &934502347 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 934502352} + - component: {fileID: 934502351} + - component: {fileID: 934502350} + - component: {fileID: 934502349} + - component: {fileID: 934502348} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &934502348 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 934502347} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a05dcd8be7ec4ccbb35c26219884aa37, type: 3} + m_Name: + m_EditorClassIdentifier: + TextPopup_Prefab_01: {fileID: 22450954, guid: b06f0e6c1dfa4356ac918da1bb32c603, + type: 3} +--- !u!114 &934502349 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 934502347} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 21256c5b62f346f18640dad779911e20, type: 3} + m_Name: + m_EditorClassIdentifier: + ShowCharacters: 0 + ShowWords: 0 + ShowLinks: 1 + ShowLines: 0 + ShowMeshBounds: 0 + ShowTextBounds: 0 + ObjectStats: 'Characters: 139 Words: 22 Spaces: 20 Sprites: 0 Links: 2 + + Lines: 5 Pages: 1' + m_TextComponent: {fileID: 934502350} + m_Transform: {fileID: 934502352} +--- !u!114 &934502350 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 934502347} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: 'Text <#80ff80>Interactions in TextMesh<#40A0FF>Pro + + + The <<#ffff00>link="id"><#80ff80>Insert link text here + <<#ffff00>/link> tag allows adding <#80ff80>links + within a text object in TextMesh<#40a0ff>Pro!' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 78 + m_fontSizeBase: 78 + 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_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 934502350} + characterCount: 139 + spriteCount: 0 + spaceCount: 20 + wordCount: 22 + linkCount: 2 + lineCount: 5 + pageCount: 1 + materialCount: 2 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &934502351 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 934502347} + m_CullTransparentMesh: 0 +--- !u!224 &934502352 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 934502347} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 694875407} + m_Father: {fileID: 118419820} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 20} + m_SizeDelta: {x: -40, y: -60} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &946327967 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 946327972} + - component: {fileID: 946327971} + - component: {fileID: 946327968} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &946327968 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 946327967} + m_Enabled: 1 +--- !u!20 &946327971 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 946327967} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &946327972 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 946327967} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/12 - Link Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/12 - Link Example.unity.meta new file mode 100644 index 0000000..0585efa --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/12 - Link Example.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9747140c28254be2adc582210dfb89b8 +timeCreated: 1432629665 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/12a - Text Interactions.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/12a - Text Interactions.unity new file mode 100644 index 0000000..20e8509 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/12a - Text Interactions.unity @@ -0,0 +1,807 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 500878462c972a14d87cb770d2b59923, + type: 2} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &82550135 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 82550137} + - component: {fileID: 82550136} + m_Layer: 0 + m_Name: Event Processor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &82550136 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 82550135} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d736ce056cf444ca96e424f4d9c42b76, type: 3} + m_Name: + m_EditorClassIdentifier: + TextEventHandler: {fileID: 1647263047} +--- !u!4 &82550137 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 82550135} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &164803384 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 164803387} + - component: {fileID: 164803386} + - component: {fileID: 164803385} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &164803385 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 164803384} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &164803386 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 164803384} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &164803387 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 164803384} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1025337336 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1025337341} + - component: {fileID: 1025337340} + - component: {fileID: 1025337337} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1025337337 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1025337336} + m_Enabled: 1 +--- !u!20 &1025337340 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1025337336} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 18 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1025337341 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1025337336} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1531522790 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1531522793} + - component: {fileID: 1531522792} + - component: {fileID: 1531522791} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!114 &1531522791 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1531522790} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &1531522792 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1531522790} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 1 + m_Camera: {fileID: 1025337340} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &1531522793 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1531522790} + 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_Children: + - {fileID: 1767744559} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &1647263045 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1647263053} + - component: {fileID: 1647263052} + - component: {fileID: 1647263048} + - component: {fileID: 1647263046} + - component: {fileID: 1647263047} + m_Layer: 0 + m_Name: TextMeshPro + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1647263046 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1647263045} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 21256c5b62f346f18640dad779911e20, type: 3} + m_Name: + m_EditorClassIdentifier: + ShowCharacters: 0 + ShowWords: 0 + ShowLinks: 1 + ShowLines: 0 + ShowMeshBounds: 0 + ShowTextBounds: 0 + ObjectStats: 'Characters: 70 Words: 10 Spaces: 10 Sprites: 0 Links: 2 + + Lines: + 4 Pages: 1' + m_TextComponent: {fileID: 1647263048} +--- !u!114 &1647263047 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1647263045} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1312ae25639a4bae8e25ae223209cc50, type: 3} + m_Name: + m_EditorClassIdentifier: + m_OnCharacterSelection: + m_PersistentCalls: + m_Calls: [] + m_OnSpriteSelection: + m_PersistentCalls: + m_Calls: [] + m_OnWordSelection: + m_PersistentCalls: + m_Calls: [] + m_OnLineSelection: + m_PersistentCalls: + m_Calls: [] + m_OnLinkSelection: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &1647263048 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1647263045} + 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: See the <#40A0FF>online documentation + for more information about this product \U0001F60A + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 36 + m_fontSizeBase: 36 + 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_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 0 + 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: 2 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1647263052} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1647263052 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1647263045} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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!224 &1647263053 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1647263045} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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} + m_SizeDelta: {x: 38.25, y: 19.44} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1767744558 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1767744559} + - component: {fileID: 1767744562} + - component: {fileID: 1767744561} + - component: {fileID: 1767744563} + - component: {fileID: 1767744560} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1767744559 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767744558} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1531522793} + 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, y: 0} + m_SizeDelta: {x: 386.7, y: 193.6} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1767744560 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767744558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1312ae25639a4bae8e25ae223209cc50, type: 3} + m_Name: + m_EditorClassIdentifier: + m_OnCharacterSelection: + m_PersistentCalls: + m_Calls: [] + m_OnSpriteSelection: + m_PersistentCalls: + m_Calls: [] + m_OnWordSelection: + m_PersistentCalls: + m_Calls: [] + m_OnLineSelection: + m_PersistentCalls: + m_Calls: [] + m_OnLinkSelection: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &1767744561 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767744558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, 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: See the <#40A0FF>online documentation + for more information about this product. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 257 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 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_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 0 + m_isOrthographic: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1767744562 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767744558} + m_CullTransparentMesh: 0 +--- !u!114 &1767744563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1767744558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 21256c5b62f346f18640dad779911e20, type: 3} + m_Name: + m_EditorClassIdentifier: + ShowCharacters: 0 + ShowWords: 0 + ShowLinks: 1 + ShowLines: 0 + ShowMeshBounds: 0 + ShowTextBounds: 0 + ObjectStats: 'Characters: 69 Words: 10 Spaces: 9 Sprites: 0 Links: 2 + + Lines: + 4 Pages: 1' + m_TextComponent: {fileID: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/12a - Text Interactions.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/12a - Text Interactions.unity.meta new file mode 100644 index 0000000..757e195 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/12a - Text Interactions.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 08572ab7713642c8a60789750f0bce5c +timeCreated: 1468999615 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/13 - Soft Hyphenation.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/13 - Soft Hyphenation.unity new file mode 100644 index 0000000..de0a8e4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/13 - Soft Hyphenation.unity @@ -0,0 +1,507 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &622739416 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 622739421} + - component: {fileID: 622739420} + - component: {fileID: 622739417} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &622739417 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 622739416} + m_Enabled: 1 +--- !u!20 &622739420 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 622739416} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &622739421 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 622739416} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &900353244 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 900353248} + - component: {fileID: 900353247} + - component: {fileID: 900353246} + - component: {fileID: 900353245} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &900353245 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 900353244} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &900353246 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 900353244} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &900353247 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 900353244} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &900353248 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 900353244} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1247086620 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1247086621} + - component: {fileID: 1247086623} + - component: {fileID: 1247086622} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1247086621 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1247086620} + 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_Children: + - {fileID: 1308029164} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1247086622 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1247086620} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &1247086623 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1247086620} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &1308029161 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1308029164} + - component: {fileID: 1308029163} + - component: {fileID: 1308029162} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1308029162 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1308029161} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Using <#80ff80>Hy\u00ADphen\u00ADa\u00ADtion can help <#80ff80>im\u00ADprove + the <#80ff80>read\u00ADability of text. This is a <#ffff80>well-known + fact. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + 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_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1308029162} + characterCount: 91 + spriteCount: 0 + spaceCount: 13 + wordCount: 14 + linkCount: 0 + lineCount: 4 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1308029163 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1308029161} + m_CullTransparentMesh: 0 +--- !u!224 &1308029164 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1308029161} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1247086621} + 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, y: 0} + m_SizeDelta: {x: 400, y: 300} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/13 - Soft Hyphenation.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/13 - Soft Hyphenation.unity.meta new file mode 100644 index 0000000..5984bef --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/13 - Soft Hyphenation.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 875684baf40f4d008ce806d03e2a81b2 +timeCreated: 1487545080 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/14 - Multi Font & Sprites.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/14 - Multi Font & Sprites.unity new file mode 100644 index 0000000..fe6dec3 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/14 - Multi Font & Sprites.unity @@ -0,0 +1,544 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 6b9a46634d3f3f0498640b1a019d5853, + type: 2} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &136970341 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 136970346} + - component: {fileID: 136970345} + - component: {fileID: 136970342} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &136970342 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136970341} + m_Enabled: 1 +--- !u!20 &136970345 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136970341} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 36 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &136970346 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 136970341} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &921526337 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 921526342} + - component: {fileID: 921526341} + - component: {fileID: 921526338} + m_Layer: 0 + m_Name: TextMeshPro + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &921526338 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 921526337} + 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: Use <#ffff80>multiple + fonts and <#ffff80>Sprites per text object. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 36 + m_fontSizeBase: 36 + 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: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 921526341} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &921526341 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 921526337} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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!224 &921526342 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 921526337} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1390778677} + - {fileID: 1956776759} + m_Father: {fileID: 0} + 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} + m_SizeDelta: {x: 45, y: 10} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1390778673 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1390778677} + - component: {fileID: 1390778676} + - component: {fileID: 1390778675} + m_Layer: 0 + m_Name: TMP SubMesh [Anton SDF - Drop Shadow] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!33 &1390778675 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1390778673} + m_Mesh: {fileID: 0} +--- !u!23 &1390778676 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1390778673} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 749b9069dc4742c5bfa5c74644049926, 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!4 &1390778677 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1390778673} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 921526342} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1956776755 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1956776759} + - component: {fileID: 1956776758} + - component: {fileID: 1956776757} + m_Layer: 0 + m_Name: TMP SubMesh [TextMeshPro/Sprite] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!33 &1956776757 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1956776755} + m_Mesh: {fileID: 0} +--- !u!23 &1956776758 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1956776755} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2103686, guid: c41005c129ba4d66911b75229fd70b45, 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!4 &1956776759 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1956776755} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 921526342} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/14 - Multi Font & Sprites.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/14 - Multi Font & Sprites.unity.meta new file mode 100644 index 0000000..75f3ef6 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/14 - Multi Font & Sprites.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 22a2fba786ad4c40ac0ba09f0b933100 +timeCreated: 1488062344 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/15 - Inline Graphics & Sprites.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/15 - Inline Graphics & Sprites.unity new file mode 100644 index 0000000..4767065 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/15 - Inline Graphics & Sprites.unity @@ -0,0 +1,595 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &323282589 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 323282593} + - component: {fileID: 323282592} + - component: {fileID: 323282591} + - component: {fileID: 323282594} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &323282591 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323282589} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Example of using <#ffa000>Graphics Inline + with Text in TextMesh<#40a0ff>Pro + and Unity 4.6 & 5.x + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 749b9069dc4742c5bfa5c74644049926, 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: 11400000, guid: fbef3c704dce48f08a44612d6c856c8d, type: 2} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 101 + m_fontSizeBase: 102.9 + m_fontWeight: 400 + m_enableAutoSizing: 1 + m_fontSizeMin: 18 + m_fontSizeMax: 300 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 18.2 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 323282591} + characterCount: 86 + spriteCount: 0 + spaceCount: 17 + wordCount: 15 + linkCount: 0 + lineCount: 4 + pageCount: 1 + materialCount: 2 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: a9df86876be30af4e9b5f5975d8ee7d8, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &323282592 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323282589} + m_CullTransparentMesh: 0 +--- !u!224 &323282593 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323282589} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1464317156} + m_Father: {fileID: 2144085114} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.05, y: 0.05} + m_AnchorMax: {x: 0.95, y: 0.95} + m_AnchoredPosition: {x: -0.024963379, y: 0} + m_SizeDelta: {x: 0.050049, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &323282594 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323282589} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e32c266ee6204b21a427753cb0694c81, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &577034186 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 577034190} + - component: {fileID: 577034189} + - component: {fileID: 577034188} + - component: {fileID: 577034187} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &577034187 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 577034186} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &577034188 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 577034186} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &577034189 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 577034186} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &577034190 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 577034186} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &728267877 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 728267882} + - component: {fileID: 728267881} + - component: {fileID: 728267878} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &728267878 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 728267877} + m_Enabled: 1 +--- !u!20 &728267881 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 728267877} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &728267882 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 728267877} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1464317155 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1464317156} + - component: {fileID: 1464317158} + - component: {fileID: 1464317157} + m_Layer: 0 + m_Name: TMP SubMeshUI [TMPro/Sprite] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1464317156 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1464317155} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 323282593} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1464317157 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1464317155} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2102322, guid: fbef3c704dce48f08a44612d6c856c8d, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 0} + m_spriteAsset: {fileID: 11400000, guid: fbef3c704dce48f08a44612d6c856c8d, type: 2} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2102322, guid: fbef3c704dce48f08a44612d6c856c8d, type: 2} + m_isDefaultMaterial: 1 + m_padding: 0 + m_canvasRenderer: {fileID: 1464317158} + m_TextComponent: {fileID: 323282591} + m_materialReferenceIndex: 0 +--- !u!222 &1464317158 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1464317155} + m_CullTransparentMesh: 0 +--- !u!1 &2144085111 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2144085114} + - component: {fileID: 2144085113} + - component: {fileID: 2144085112} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2144085112 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2144085111} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &2144085113 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2144085111} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 728267881} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &2144085114 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2144085111} + 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_Children: + - {fileID: 323282593} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/15 - Inline Graphics & Sprites.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/15 - Inline Graphics & Sprites.unity.meta new file mode 100644 index 0000000..c08acb8 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/15 - Inline Graphics & Sprites.unity.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: e76e6c0f81964cbda3fe0b7d26ed8060 +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/16 - Linked text overflow mode example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/16 - Linked text overflow mode example.unity new file mode 100644 index 0000000..ffa6a42 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/16 - Linked text overflow mode example.unity @@ -0,0 +1,1063 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &186473238 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 186473239} + - component: {fileID: 186473241} + - component: {fileID: 186473240} + m_Layer: 0 + m_Name: Image 2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &186473239 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 186473238} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1056147835} + m_RootOrder: 4 + 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: 320, y: 35} + m_SizeDelta: {x: 496, y: 375} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &186473240 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 186473238} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -98529514, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Texture: {fileID: 2800000, guid: c76d18757a194d618355f05f815cb0a1, type: 3} + m_UVRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 +--- !u!222 &186473241 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 186473238} + m_CullTransparentMesh: 0 +--- !u!1 &241484348 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 241484353} + - component: {fileID: 241484352} + - component: {fileID: 241484349} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &241484349 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 241484348} + m_Enabled: 1 +--- !u!20 &241484352 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 241484348} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &241484353 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 241484348} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &729816403 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 729816404} + - component: {fileID: 729816406} + - component: {fileID: 729816405} + m_Layer: 0 + m_Name: TextMeshPro Text - Master + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &729816404 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 729816403} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1056147835} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: 265.25} + m_SizeDelta: {x: -144, y: -570.5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &729816405 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 729816403} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: 'The <#ffff80>Linked Overflow text mode makes it possible to <#ffff80>link + text objects together to allow text to flow from one object to another. + + + As the text fills a given text container, the text exceeding this container will + automatically flow to the <#ffff80>linked text object. + + + This feature is located in the text Overflow options and available with both TextMeshPro + components. + + + The text Overflow - Linked mode makes it possible to create sophisticated text + layout similar to those seen in magazines and web pages.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 28 + m_fontSizeBase: 28 + 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: 6 + m_linkedTextComponent: {fileID: 1252276988} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &729816406 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 729816403} + m_CullTransparentMesh: 0 +--- !u!1 &1056147832 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1056147835} + - component: {fileID: 1056147834} + - component: {fileID: 1056147833} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1056147833 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1056147832} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &1056147834 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1056147832} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &1056147835 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1056147832} + 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_Children: + - {fileID: 729816404} + - {fileID: 1755693433} + - {fileID: 1252276987} + - {fileID: 1757337309} + - {fileID: 186473239} + - {fileID: 1754901269} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &1252276986 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1252276987} + - component: {fileID: 1252276989} + - component: {fileID: 1252276988} + m_Layer: 0 + m_Name: TextMeshPro Text - Linked 1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1252276987 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1252276986} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1056147835} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: -243.5} + m_SizeDelta: {x: -144, y: -547} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1252276988 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1252276986} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: 'The <#ffff80>Linked Overflow text mode makes it possible to <#ffff80>link + text objects together to allow text to flow from one object to another. + + + As the text fills a given text container, the text exceeding this container will + automatically flow to the <#ffff80>linked text object. + + + This feature is located in the text Overflow options and available with both TextMeshPro + components. + + + The text Overflow - Linked mode makes it possible to create sophisticated text + layout similar to those seen in magazines and web pages.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 28 + m_fontSizeBase: 28 + 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: 6 + m_linkedTextComponent: {fileID: 1757337310} + parentLinkedComponent: {fileID: 729816405} + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1252276989 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1252276986} + m_CullTransparentMesh: 0 +--- !u!1 &1562093468 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1562093471} + - component: {fileID: 1562093470} + - component: {fileID: 1562093469} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1562093469 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562093468} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1562093470 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562093468} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1562093471 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562093468} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1754901268 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1754901269} + - component: {fileID: 1754901271} + - component: {fileID: 1754901270} + m_Layer: 0 + m_Name: TextMeshPro Text - Linked 3 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1754901269 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1754901268} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1056147835} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -243.5} + m_SizeDelta: {x: -144, y: -547} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1754901270 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1754901268} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: 'The <#ffff80>Linked Overflow text mode makes it possible to <#ffff80>link + text objects together to allow text to flow from one object to another. + + + As the text fills a given text container, the text exceeding this container will + automatically flow to the <#ffff80>linked text object. + + + This feature is located in the text Overflow options and available with both TextMeshPro + components. + + + The text Overflow - Linked mode makes it possible to create sophisticated text + layout similar to those seen in magazines and web pages.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 28 + m_fontSizeBase: 28 + 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: 1757337310} + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1754901271 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1754901268} + m_CullTransparentMesh: 0 +--- !u!1 &1755693432 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1755693433} + - component: {fileID: 1755693435} + - component: {fileID: 1755693434} + m_Layer: 0 + m_Name: Image 1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1755693433 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1755693432} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1056147835} + 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: -320, y: 16.5} + m_SizeDelta: {x: 496, y: 348} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1755693434 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1755693432} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -98529514, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Texture: {fileID: 2800000, guid: 4ccf43d26c4748c792174516f4a8fcef, type: 3} + m_UVRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 +--- !u!222 &1755693435 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1755693432} + m_CullTransparentMesh: 0 +--- !u!1 &1757337308 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1757337309} + - component: {fileID: 1757337311} + - component: {fileID: 1757337310} + m_Layer: 0 + m_Name: TextMeshPro Text - Linked 2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1757337309 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1757337308} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1056147835} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 281.25} + m_SizeDelta: {x: -144, y: -602.5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1757337310 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1757337308} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: 'The <#ffff80>Linked Overflow text mode makes it possible to <#ffff80>link + text objects together to allow text to flow from one object to another. + + + As the text fills a given text container, the text exceeding this container will + automatically flow to the <#ffff80>linked text object. + + + This feature is located in the text Overflow options and available with both TextMeshPro + components. + + + The text Overflow - Linked mode makes it possible to create sophisticated text + layout similar to those seen in magazines and web pages.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e73a58f6e2794ae7b1b7e50b7fb811b0, 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: 28 + m_fontSizeBase: 28 + 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: 6 + m_linkedTextComponent: {fileID: 1754901270} + parentLinkedComponent: {fileID: 1252276988} + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1757337311 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1757337308} + m_CullTransparentMesh: 0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/16 - Linked text overflow mode example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/16 - Linked text overflow mode example.unity.meta new file mode 100644 index 0000000..575730e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/16 - Linked text overflow mode example.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9442cda25baa4a0bb544c4d095b00caa +timeCreated: 1480388889 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/17 - Old Computer Terminal.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/17 - Old Computer Terminal.unity new file mode 100644 index 0000000..036bfd8 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/17 - Old Computer Terminal.unity @@ -0,0 +1,691 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &224141783 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224141784} + - component: {fileID: 224141787} + - component: {fileID: 224141786} + - component: {fileID: 224141785} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224141784 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 224141783} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2065555315} + m_Father: {fileID: 993286720} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &224141785 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 224141783} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -1200242548, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 1 +--- !u!114 &224141786 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 224141783} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.016379312, g: 0.1397059, b: 0, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &224141787 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 224141783} + m_CullTransparentMesh: 0 +--- !u!1 &515056265 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 515056270} + - component: {fileID: 515056269} + - component: {fileID: 515056266} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &515056266 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 515056265} + m_Enabled: 1 +--- !u!20 &515056269 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 515056265} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &515056270 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 515056265} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &993286719 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 993286720} + - component: {fileID: 993286723} + - component: {fileID: 993286722} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &993286720 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 993286719} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 224141784} + m_Father: {fileID: 1504674220} + 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, y: 0} + m_SizeDelta: {x: 640, y: 400} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &993286722 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 993286719} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0.392} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &993286723 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 993286719} + m_CullTransparentMesh: 0 +--- !u!1 &1086682925 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1086682929} + - component: {fileID: 1086682928} + - component: {fileID: 1086682927} + - component: {fileID: 1086682926} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1086682926 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1086682925} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &1086682927 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1086682925} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1086682928 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1086682925} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1086682929 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1086682925} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1504674217 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1504674220} + - component: {fileID: 1504674219} + - component: {fileID: 1504674218} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1504674218 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1504674217} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &1504674219 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1504674217} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &1504674220 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1504674217} + 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_Children: + - {fileID: 993286720} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &2065555314 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2065555315} + - component: {fileID: 2065555318} + - component: {fileID: 2065555317} + - component: {fileID: 2065555316} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2065555315 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2065555314} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 224141784} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -10, y: -10} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2065555316 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2065555314} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 43bcd35a1c0c40ccb6d472893fe2093f, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &2065555317 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2065555314} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: 'This is an example of using the <#ffffff>TextMesh<#40a0ff>Pro + <#ffff00>maxVisibleCharacters and <#ffff00>maxVisibleLines properties + to control how many characters or lines of text will be displayed. This can be + used to create <#80ff80>Reveal or <#80ff80>Teletype FX or even + to simulate an <#80ff80>Old Computer Terminal. + + + This implementation does not involve any string manipulations and thus is allocation + free. It also works with word wrapping to avoid cutting off words as they are + revealed. This also supports the numerous rich text tags available in <#ffffff>TextMesh<#40a0ff>Pro.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: dc36b3fdc14f47ebb36fd484a67e268a, type: 2} + m_sharedMaterial: {fileID: 2140032, guid: dc36b3fdc14f47ebb36fd484a67e268a, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278311680 + m_fontColor: {r: 0, g: 0.8602941, b: 0.0059330147, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 1024 + m_textAlignment: 65535 + m_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 2 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 2065555317} + characterCount: 504 + spriteCount: 0 + spaceCount: 81 + wordCount: 81 + linkCount: 0 + lineCount: 13 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2173394, guid: 0b4bdfba56924184bbe7c948f934fb70, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &2065555318 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2065555314} + m_CullTransparentMesh: 0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/17 - Old Computer Terminal.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/17 - Old Computer Terminal.unity.meta new file mode 100644 index 0000000..686eb6e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/17 - Old Computer Terminal.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3e2e4d7b0bed4cf9ab827e9f32448f69 +timeCreated: 1435300594 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/18 - ScrollRect & Masking & Layout.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/18 - ScrollRect & Masking & Layout.unity new file mode 100644 index 0000000..c64be98 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/18 - ScrollRect & Masking & Layout.unity @@ -0,0 +1,9490 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &64233515 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 64233516} + - component: {fileID: 64233518} + - component: {fileID: 64233517} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &64233516 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 64233515} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1456085081} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 295, y: -87} + m_SizeDelta: {x: 570, y: 164} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &64233517 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 64233515} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: A. This block of text contains three lines of text which requires the container + to dynamically expand vertically. +--- !u!222 &64233518 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 64233515} + m_CullTransparentMesh: 0 +--- !u!1 &92594157 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 92594158} + - component: {fileID: 92594160} + - component: {fileID: 92594159} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &92594158 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 92594157} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 897593938} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 294.99997, y: -106} + m_SizeDelta: {x: 569.99994, y: 202} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &92594159 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 92594157} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: 'Question 1 + + This is an example of using TextMeshPro in Unity to display text using + the New UI''s auto layout functionality.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 0 + m_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 1 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 0 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &92594160 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 92594157} + m_CullTransparentMesh: 0 +--- !u!1 &112616780 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 112616781} + m_Layer: 5 + m_Name: Anchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &112616781 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 112616780} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2099726592} + - {fileID: 536147347} + m_Father: {fileID: 953417884} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 1} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 700, y: 800} + m_Pivot: {x: 0.5, y: 1} +--- !u!1 &113574880 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 113574881} + - component: {fileID: 113574883} + - component: {fileID: 113574882} + m_Layer: 0 + m_Name: TMP SubMeshUI [Anton SDF Material] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &113574881 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 113574880} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1060791689} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &113574882 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 113574880} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_isDefaultMaterial: 1 + m_padding: 6.5 + m_canvasRenderer: {fileID: 113574883} + m_TextComponent: {fileID: 1060791690} + m_materialReferenceIndex: 0 +--- !u!222 &113574883 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 113574880} + m_CullTransparentMesh: 0 +--- !u!1 &178325484 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 178325490} + - component: {fileID: 178325489} + - component: {fileID: 178325488} + - component: {fileID: 178325487} + - component: {fileID: 178325486} + - component: {fileID: 178325485} + m_Layer: 5 + m_Name: Answer E + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &178325485 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178325484} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &178325486 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178325484} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &178325487 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178325484} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 178325488} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &178325488 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178325484} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &178325489 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178325484} + m_CullTransparentMesh: 0 +--- !u!224 &178325490 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178325484} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 410344772} + m_Father: {fileID: 1559754537} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 300, y: -755.5} + m_SizeDelta: {x: 590, y: 133} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &181427277 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 181427278} + - component: {fileID: 181427280} + - component: {fileID: 181427279} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &181427278 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181427277} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 945160589} + m_Father: {fileID: 382277095} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &181427279 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181427277} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: D.<#ff0000>You selected the wrong answer. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + 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_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 181427279} + characterCount: 32 + spriteCount: 0 + spaceCount: 4 + wordCount: 6 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 2 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &181427280 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181427277} + m_CullTransparentMesh: 0 +--- !u!1 &197293552 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 197293553} + - component: {fileID: 197293558} + - component: {fileID: 197293557} + - component: {fileID: 197293556} + - component: {fileID: 197293555} + - component: {fileID: 197293554} + m_Layer: 5 + m_Name: Answer B + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &197293553 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 197293552} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1164028272} + m_Father: {fileID: 1559754537} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 300, y: -455.5} + m_SizeDelta: {x: 590, y: 133} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &197293554 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 197293552} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &197293555 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 197293552} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &197293556 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 197293552} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 197293557} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &197293557 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 197293552} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &197293558 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 197293552} + m_CullTransparentMesh: 0 +--- !u!1 &217857655 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 217857656} + - component: {fileID: 217857661} + - component: {fileID: 217857660} + - component: {fileID: 217857659} + - component: {fileID: 217857658} + - component: {fileID: 217857657} + m_Layer: 5 + m_Name: Answer C + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &217857656 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 217857655} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 969259720} + m_Father: {fileID: 1871798295} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &217857657 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 217857655} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &217857658 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 217857655} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &217857659 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 217857655} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 217857660} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &217857660 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 217857655} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &217857661 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 217857655} + m_CullTransparentMesh: 0 +--- !u!1 &302839334 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 302839335} + - component: {fileID: 302839337} + - component: {fileID: 302839336} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &302839335 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 302839334} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 493987983} + m_Father: {fileID: 519242055} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &302839336 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 302839334} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: B.<#ffff00>Multiple fonts are + used to display the text. One for the bullets and the other for the rest of the + text. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + 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_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 302839336} + characterCount: 106 + spriteCount: 0 + spaceCount: 20 + wordCount: 22 + linkCount: 0 + lineCount: 3 + pageCount: 1 + materialCount: 2 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &302839337 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 302839334} + m_CullTransparentMesh: 0 +--- !u!1 &351715036 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 351715037} + - component: {fileID: 351715039} + - component: {fileID: 351715038} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &351715037 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 351715036} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1257376144} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &351715038 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 351715036} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9098039, g: 0.9098039, b: 0.9098039, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &351715039 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 351715036} + m_CullTransparentMesh: 0 +--- !u!1 &355544155 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 355544156} + - component: {fileID: 355544161} + - component: {fileID: 355544160} + - component: {fileID: 355544159} + - component: {fileID: 355544158} + - component: {fileID: 355544157} + m_Layer: 5 + m_Name: Answer A + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &355544156 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 355544155} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1940016222} + m_Father: {fileID: 2034524132} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 299.99997, y: -307.5} + m_SizeDelta: {x: 589.99994, y: 171} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &355544157 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 355544155} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &355544158 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 355544155} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &355544159 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 355544155} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 355544160} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &355544160 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 355544155} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &355544161 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 355544155} + m_CullTransparentMesh: 0 +--- !u!1 &373069844 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 373069845} + - component: {fileID: 373069847} + - component: {fileID: 373069846} + m_Layer: 0 + m_Name: TMP SubMeshUI [Anton SDF Material] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &373069845 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 373069844} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 969259720} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &373069846 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 373069844} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_isDefaultMaterial: 1 + m_padding: 6.5 + m_canvasRenderer: {fileID: 373069847} + m_TextComponent: {fileID: 969259721} + m_materialReferenceIndex: 0 +--- !u!222 &373069847 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 373069844} + m_CullTransparentMesh: 0 +--- !u!1 &379533974 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 379533975} + - component: {fileID: 379533977} + - component: {fileID: 379533976} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &379533975 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 379533974} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 672877458} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &379533976 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 379533974} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9098039, g: 0.9098039, b: 0.9098039, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &379533977 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 379533974} + m_CullTransparentMesh: 0 +--- !u!1 &382277094 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 382277095} + - component: {fileID: 382277100} + - component: {fileID: 382277099} + - component: {fileID: 382277098} + - component: {fileID: 382277097} + - component: {fileID: 382277096} + m_Layer: 5 + m_Name: Answer D + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &382277095 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 382277094} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 181427278} + m_Father: {fileID: 1871798295} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &382277096 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 382277094} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &382277097 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 382277094} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &382277098 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 382277094} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 382277099} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &382277099 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 382277094} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &382277100 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 382277094} + m_CullTransparentMesh: 0 +--- !u!1 &410344771 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 410344772} + - component: {fileID: 410344774} + - component: {fileID: 410344773} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &410344772 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410344771} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 178325490} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 295, y: -66.5} + m_SizeDelta: {x: 570, y: 123} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &410344773 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410344771} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: E. This block of text contains three lines of text. The second line ends + up outside the scrolling area. +--- !u!222 &410344774 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 410344771} + m_CullTransparentMesh: 0 +--- !u!1 &463584090 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 463584091} + - component: {fileID: 463584093} + - component: {fileID: 463584092} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &463584091 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 463584090} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1199396876} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 295, y: -30} + m_SizeDelta: {x: 570, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &463584092 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 463584090} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: D.You selected the wrong answer. +--- !u!222 &463584093 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 463584090} + m_CullTransparentMesh: 0 +--- !u!1 &493987982 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 493987983} + - component: {fileID: 493987985} + - component: {fileID: 493987984} + m_Layer: 0 + m_Name: TMP SubMeshUI [Anton SDF Material] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &493987983 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 493987982} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 302839335} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &493987984 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 493987982} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_isDefaultMaterial: 1 + m_padding: 6.5 + m_canvasRenderer: {fileID: 493987985} + m_TextComponent: {fileID: 302839336} + m_materialReferenceIndex: 0 +--- !u!222 &493987985 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 493987982} + m_CullTransparentMesh: 0 +--- !u!1 &519242054 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 519242055} + - component: {fileID: 519242060} + - component: {fileID: 519242059} + - component: {fileID: 519242058} + - component: {fileID: 519242057} + - component: {fileID: 519242056} + m_Layer: 5 + m_Name: Answer B + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &519242055 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519242054} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 302839335} + m_Father: {fileID: 1871798295} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &519242056 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519242054} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &519242057 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519242054} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &519242058 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519242054} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 519242059} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &519242059 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519242054} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &519242060 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519242054} + m_CullTransparentMesh: 0 +--- !u!1 &519990992 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 519990993} + - component: {fileID: 519990998} + - component: {fileID: 519990997} + - component: {fileID: 519990996} + - component: {fileID: 519990995} + - component: {fileID: 519990994} + m_Layer: 5 + m_Name: Answer D + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &519990993 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519990992} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 710764945} + m_Father: {fileID: 594570832} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 330, y: -654} + m_SizeDelta: {x: 650, y: 60} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &519990994 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519990992} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &519990995 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519990992} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &519990996 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519990992} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 519990997} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &519990997 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519990992} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &519990998 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519990992} + m_CullTransparentMesh: 0 +--- !u!1 &536147346 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 536147347} + - component: {fileID: 536147351} + - component: {fileID: 536147350} + - component: {fileID: 536147349} + - component: {fileID: 536147348} + m_Layer: 5 + m_Name: Scroll Rect + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &536147347 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 536147346} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 594570832} + m_Father: {fileID: 112616781} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -40, y: -40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &536147348 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 536147346} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -146154839, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &536147349 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 536147346} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 594570832} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 0} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 0} + m_HorizontalScrollbarVisibility: 0 + m_VerticalScrollbarVisibility: 0 + m_HorizontalScrollbarSpacing: 0 + m_VerticalScrollbarSpacing: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &536147350 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 536147346} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.5147059, g: 0.5147059, b: 0.5147059, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &536147351 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 536147346} + m_CullTransparentMesh: 0 +--- !u!1 &594570831 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 594570832} + - component: {fileID: 594570836} + - component: {fileID: 594570835} + - component: {fileID: 594570834} + - component: {fileID: 594570833} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &594570832 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 594570831} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1175669143} + - {fileID: 1729765364} + - {fileID: 1853075848} + - {fileID: 1368233943} + - {fileID: 519990993} + - {fileID: 1452511679} + m_Father: {fileID: 536147347} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 827} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &594570833 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 594570831} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!114 &594570834 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 594570831} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 5 + m_Right: 5 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 5 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &594570835 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 594570831} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9098039, g: 0.9098039, b: 0.9098039, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &594570836 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 594570831} + m_CullTransparentMesh: 0 +--- !u!1 &672877457 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 672877458} + m_Layer: 5 + m_Name: Anchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &672877458 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 672877457} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 379533975} + - {fileID: 1982914453} + m_Father: {fileID: 1576580512} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: -0.000030517578, y: 0} + m_SizeDelta: {x: -0.000061035156, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &673616920 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 673616921} + - component: {fileID: 673616923} + - component: {fileID: 673616922} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &673616921 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 673616920} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1368233943} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 325, y: -46} + m_SizeDelta: {x: 630, y: 82} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &673616922 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 673616920} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: C. This block of text contains one line of text. +--- !u!222 &673616923 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 673616920} + m_CullTransparentMesh: 0 +--- !u!1 &710764944 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 710764945} + - component: {fileID: 710764947} + - component: {fileID: 710764946} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &710764945 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 710764944} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 519990993} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 325, y: -30} + m_SizeDelta: {x: 630, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &710764946 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 710764944} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: D.You selected the wrong answer. +--- !u!222 &710764947 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 710764944} + m_CullTransparentMesh: 0 +--- !u!1 &737955031 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 737955032} + - component: {fileID: 737955034} + - component: {fileID: 737955033} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &737955032 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 737955031} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1975887975} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 294.99997, y: -65.5} + m_SizeDelta: {x: 569.99994, y: 121} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &737955033 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 737955031} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: B.Indent Tag allows multiple lines of text to be nicely aligned + with the bullets. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 0 + m_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 1 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 0 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &737955034 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 737955031} + m_CullTransparentMesh: 0 +--- !u!1 &745530092 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 745530093} + - component: {fileID: 745530096} + - component: {fileID: 745530095} + - component: {fileID: 745530094} + - component: {fileID: 745530097} + m_Layer: 5 + m_Name: Canvas UI Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &745530093 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 745530092} + 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_Children: + - {fileID: 1329726108} + m_Father: {fileID: 1236983896} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &745530094 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 745530092} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &745530095 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 745530092} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &745530096 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 745530092} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!114 &745530097 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 745530092} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 24b0dc2d1d494adbbec1f4db26b4cf83, type: 3} + m_Name: + m_EditorClassIdentifier: + UpdateInterval: 1 + AnchorPosition: 0 +--- !u!1 &760195238 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 760195239} + - component: {fileID: 760195243} + - component: {fileID: 760195242} + - component: {fileID: 760195241} + - component: {fileID: 760195240} + m_Layer: 5 + m_Name: Scroll Rect + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &760195239 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 760195238} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1871798295} + m_Father: {fileID: 1257376144} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -40, y: -40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &760195240 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 760195238} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -146154839, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &760195241 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 760195238} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 1871798295} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 0} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 0} + m_HorizontalScrollbarVisibility: 0 + m_VerticalScrollbarVisibility: 0 + m_HorizontalScrollbarSpacing: 0 + m_VerticalScrollbarSpacing: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &760195242 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 760195238} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.5147059, g: 0.5147059, b: 0.5147059, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &760195243 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 760195238} + m_CullTransparentMesh: 0 +--- !u!1 &785126631 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 785126632} + - component: {fileID: 785126634} + - component: {fileID: 785126633} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &785126632 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 785126631} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1904784088} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 294.99997, y: -85.5} + m_SizeDelta: {x: 569.99994, y: 161} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &785126633 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 785126631} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: E.This block of text contains three lines of text. The second + line ends up outside the scrolling area. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 0 + m_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 1 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 0 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &785126634 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 785126631} + m_CullTransparentMesh: 0 +--- !u!1 &792312853 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 792312854} + - component: {fileID: 792312856} + - component: {fileID: 792312855} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &792312854 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 792312853} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2014757822} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 294.99997, y: -45.5} + m_SizeDelta: {x: 569.99994, y: 81} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &792312855 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 792312853} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: C.This block of text contains one line of text. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 0 + m_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 1 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 0 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &792312856 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 792312853} + m_CullTransparentMesh: 0 +--- !u!1 &799230986 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 799230987} + - component: {fileID: 799230989} + - component: {fileID: 799230988} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &799230987 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 799230986} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1853075848} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 325, y: -66.5} + m_SizeDelta: {x: 630, y: 123} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &799230988 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 799230986} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: B. Indent Tag allows multiple lines of text to be nicely aligned with the + bullets. +--- !u!222 &799230989 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 799230986} + m_CullTransparentMesh: 0 +--- !u!1 &826920723 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 826920724} + - component: {fileID: 826920729} + - component: {fileID: 826920728} + - component: {fileID: 826920727} + - component: {fileID: 826920726} + - component: {fileID: 826920725} + m_Layer: 5 + m_Name: Answer D + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &826920724 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826920723} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1756545447} + m_Father: {fileID: 2034524132} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 299.99997, y: -660} + m_SizeDelta: {x: 589.99994, y: 60} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &826920725 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826920723} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &826920726 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826920723} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &826920727 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826920723} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 826920728} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &826920728 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826920723} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &826920729 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 826920723} + m_CullTransparentMesh: 0 +--- !u!1 &855995075 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 855995076} + - component: {fileID: 855995078} + - component: {fileID: 855995077} + m_Layer: 0 + m_Name: TMP SubMeshUI [Anton SDF Material] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &855995076 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 855995075} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 929582474} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &855995077 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 855995075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_isDefaultMaterial: 1 + m_padding: 6.5 + m_canvasRenderer: {fileID: 855995078} + m_TextComponent: {fileID: 929582475} + m_materialReferenceIndex: 0 +--- !u!222 &855995078 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 855995075} + m_CullTransparentMesh: 0 +--- !u!1 &857729202 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 857729203} + - component: {fileID: 857729205} + - component: {fileID: 857729204} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &857729203 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 857729202} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1329726108} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &857729204 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 857729202} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9098039, g: 0.9098039, b: 0.9098039, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &857729205 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 857729202} + m_CullTransparentMesh: 0 +--- !u!1 &897593937 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 897593938} + - component: {fileID: 897593942} + - component: {fileID: 897593941} + - component: {fileID: 897593940} + - component: {fileID: 897593939} + - component: {fileID: 897593943} + m_Layer: 5 + m_Name: Question + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &897593938 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 897593937} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 92594158} + m_Father: {fileID: 2034524132} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 299.99997, y: -111} + m_SizeDelta: {x: 589.99994, y: 212} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &897593939 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 897593937} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &897593940 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 897593937} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 897593941} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &897593941 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 897593937} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.62521625, g: 0.85875535, b: 0.86764705, a: 0.88235295} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &897593942 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 897593937} + m_CullTransparentMesh: 0 +--- !u!114 &897593943 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 897593937} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 200 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &929582473 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 929582474} + - component: {fileID: 929582476} + - component: {fileID: 929582475} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &929582474 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 929582473} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 855995076} + m_Father: {fileID: 1876543866} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &929582475 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 929582473} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: A.Each block of text is using the <<#ffff00>indent> + tag to nicely align the bullets and text. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + 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_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 929582475} + characterCount: 84 + spriteCount: 0 + spaceCount: 15 + wordCount: 17 + linkCount: 0 + lineCount: 3 + pageCount: 1 + materialCount: 2 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &929582476 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 929582473} + m_CullTransparentMesh: 0 +--- !u!1 &941241665 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 941241668} + - component: {fileID: 941241667} + - component: {fileID: 941241666} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &941241666 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 941241665} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: A. This block of text contains three lines of text which requires the container + to dynamically expand vertically. +--- !u!222 &941241667 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 941241665} + m_CullTransparentMesh: 0 +--- !u!224 &941241668 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 941241665} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1729765364} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 325, y: -87} + m_SizeDelta: {x: 630, y: 164} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &945160588 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 945160589} + - component: {fileID: 945160591} + - component: {fileID: 945160590} + m_Layer: 0 + m_Name: TMP SubMeshUI [Anton SDF Material] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &945160589 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945160588} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 181427278} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &945160590 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945160588} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_isDefaultMaterial: 1 + m_padding: 6.5 + m_canvasRenderer: {fileID: 945160591} + m_TextComponent: {fileID: 181427279} + m_materialReferenceIndex: 0 +--- !u!222 &945160591 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945160588} + m_CullTransparentMesh: 0 +--- !u!1 &953417883 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 953417884} + - component: {fileID: 953417888} + - component: {fileID: 953417887} + - component: {fileID: 953417886} + - component: {fileID: 953417885} + m_Layer: 5 + m_Name: Canvas UI Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &953417884 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 953417883} + 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_Children: + - {fileID: 112616781} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &953417885 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 953417883} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 24b0dc2d1d494adbbec1f4db26b4cf83, type: 3} + m_Name: + m_EditorClassIdentifier: + UpdateInterval: 1 + AnchorPosition: 0 +--- !u!114 &953417886 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 953417883} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &953417887 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 953417883} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &953417888 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 953417883} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &969259719 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 969259720} + - component: {fileID: 969259722} + - component: {fileID: 969259721} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &969259720 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 969259719} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 373069845} + - {fileID: 2060325072} + m_Father: {fileID: 217857656} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &969259721 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 969259719} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: C.Sprites can be + used as well inline with the text. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + 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_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 969259721} + characterCount: 53 + spriteCount: 0 + spaceCount: 10 + wordCount: 11 + linkCount: 0 + lineCount: 2 + pageCount: 1 + materialCount: 3 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &969259722 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 969259719} + m_CullTransparentMesh: 0 +--- !u!1 &973268816 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 973268817} + - component: {fileID: 973268821} + - component: {fileID: 973268820} + - component: {fileID: 973268819} + - component: {fileID: 973268818} + m_Layer: 5 + m_Name: Scroll Rect + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &973268817 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 973268816} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1559754537} + m_Father: {fileID: 1329726108} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -40, y: -40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &973268818 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 973268816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -146154839, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &973268819 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 973268816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 1559754537} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 0} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 0} + m_HorizontalScrollbarVisibility: 0 + m_VerticalScrollbarVisibility: 0 + m_HorizontalScrollbarSpacing: 0 + m_VerticalScrollbarSpacing: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &973268820 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 973268816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.5147059, g: 0.5147059, b: 0.5147059, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &973268821 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 973268816} + m_CullTransparentMesh: 0 +--- !u!1 &1040010065 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1040010069} + - component: {fileID: 1040010068} + - component: {fileID: 1040010067} + - component: {fileID: 1040010066} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1040010066 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1040010065} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &1040010067 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1040010065} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1040010068 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1040010065} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1040010069 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1040010065} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1060791688 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1060791689} + - component: {fileID: 1060791691} + - component: {fileID: 1060791690} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1060791689 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1060791688} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 113574881} + m_Father: {fileID: 1519050538} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1060791690 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1060791688} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: E.This block of text contains three + lines of text. The second line ends up outside the scrolling area. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + 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_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1060791690} + characterCount: 102 + spriteCount: 0 + spaceCount: 17 + wordCount: 19 + linkCount: 0 + lineCount: 3 + pageCount: 1 + materialCount: 2 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1060791691 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1060791688} + m_CullTransparentMesh: 0 +--- !u!1 &1126209066 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1126209067} + - component: {fileID: 1126209072} + - component: {fileID: 1126209071} + - component: {fileID: 1126209070} + - component: {fileID: 1126209069} + - component: {fileID: 1126209068} + m_Layer: 5 + m_Name: Question + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1126209067 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1126209066} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1848649448} + m_Father: {fileID: 1559754537} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 300, y: -105} + m_SizeDelta: {x: 590, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1126209068 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1126209066} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 200 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1126209069 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1126209066} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1126209070 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1126209066} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1126209071} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1126209071 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1126209066} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.62521625, g: 0.85875535, b: 0.86764705, a: 0.88235295} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1126209072 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1126209066} + m_CullTransparentMesh: 0 +--- !u!1 &1139761475 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1139761476} + - component: {fileID: 1139761478} + - component: {fileID: 1139761477} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1139761476 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139761475} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1629068645} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 295, y: -46} + m_SizeDelta: {x: 570, y: 82} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1139761477 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139761475} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: C. This block of text contains one line of text. +--- !u!222 &1139761478 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139761475} + m_CullTransparentMesh: 0 +--- !u!1 &1164028271 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1164028272} + - component: {fileID: 1164028274} + - component: {fileID: 1164028273} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1164028272 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1164028271} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 197293553} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 295, y: -66.5} + m_SizeDelta: {x: 570, y: 123} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1164028273 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1164028271} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: B. Indent Tag allows multiple lines of text to be nicely aligned with the + bullets. +--- !u!222 &1164028274 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1164028271} + m_CullTransparentMesh: 0 +--- !u!1 &1175669142 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1175669143} + - component: {fileID: 1175669148} + - component: {fileID: 1175669147} + - component: {fileID: 1175669146} + - component: {fileID: 1175669145} + - component: {fileID: 1175669144} + m_Layer: 5 + m_Name: Question + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1175669143 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1175669142} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2138298319} + m_Father: {fileID: 594570832} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 330, y: -105} + m_SizeDelta: {x: 650, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1175669144 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1175669142} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 200 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1175669145 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1175669142} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1175669146 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1175669142} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1175669147} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1175669147 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1175669142} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.62521625, g: 0.85875535, b: 0.86764705, a: 0.88235295} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1175669148 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1175669142} + m_CullTransparentMesh: 0 +--- !u!1 &1194858313 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1194858314} + - component: {fileID: 1194858316} + - component: {fileID: 1194858315} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1194858314 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1194858313} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1452511679} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 325, y: -66.5} + m_SizeDelta: {x: 630, y: 123} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1194858315 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1194858313} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: E. This block of text contains three lines of text. The second line ends + up outside the scrolling area. +--- !u!222 &1194858316 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1194858313} + m_CullTransparentMesh: 0 +--- !u!1 &1199396875 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1199396876} + - component: {fileID: 1199396881} + - component: {fileID: 1199396880} + - component: {fileID: 1199396879} + - component: {fileID: 1199396878} + - component: {fileID: 1199396877} + m_Layer: 5 + m_Name: Answer D + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1199396876 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1199396875} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 463584091} + m_Father: {fileID: 1559754537} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 300, y: -654} + m_SizeDelta: {x: 590, y: 60} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1199396877 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1199396875} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1199396878 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1199396875} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1199396879 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1199396875} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1199396880} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1199396880 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1199396875} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1199396881 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1199396875} + m_CullTransparentMesh: 0 +--- !u!1 &1236983895 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1236983896} + m_Layer: 0 + m_Name: Side by Side + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &1236983896 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1236983895} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1576580512} + - {fileID: 745530093} + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1257376143 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1257376144} + m_Layer: 5 + m_Name: Anchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1257376144 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1257376143} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 351715037} + - {fileID: 760195239} + m_Father: {fileID: 1736308204} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 700, y: -10} + m_Pivot: {x: 0.5, y: 1} +--- !u!1 &1322155519 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1322155520} + - component: {fileID: 1322155522} + - component: {fileID: 1322155521} + m_Layer: 0 + m_Name: TMP SubMeshUI [Bangers SDF Material] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1322155520 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1322155519} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1699720104} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1322155521 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1322155519} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2100000, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2100000, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_isDefaultMaterial: 0 + m_padding: 6.5 + m_canvasRenderer: {fileID: 1322155522} + m_TextComponent: {fileID: 1699720105} + m_materialReferenceIndex: 0 +--- !u!222 &1322155522 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1322155519} + m_CullTransparentMesh: 0 +--- !u!1 &1329726107 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1329726108} + m_Layer: 5 + m_Name: Anchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1329726108 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1329726107} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 857729203} + - {fileID: 973268817} + m_Father: {fileID: 745530093} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1368233942 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1368233943} + - component: {fileID: 1368233948} + - component: {fileID: 1368233947} + - component: {fileID: 1368233946} + - component: {fileID: 1368233945} + - component: {fileID: 1368233944} + m_Layer: 5 + m_Name: Answer C + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1368233943 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368233942} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 673616921} + m_Father: {fileID: 594570832} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 330, y: -573} + m_SizeDelta: {x: 650, y: 92} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1368233944 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368233942} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1368233945 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368233942} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1368233946 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368233942} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1368233947} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1368233947 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368233942} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1368233948 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368233942} + m_CullTransparentMesh: 0 +--- !u!1 &1374660295 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1374660301} + - component: {fileID: 1374660300} + - component: {fileID: 1374660299} + - component: {fileID: 1374660298} + - component: {fileID: 1374660297} + - component: {fileID: 1374660296} + m_Layer: 5 + m_Name: Question + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1374660296 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1374660295} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 200 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1374660297 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1374660295} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1374660298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1374660295} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1374660299} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1374660299 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1374660295} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.62521625, g: 0.85875535, b: 0.86764705, a: 0.88235295} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1374660300 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1374660295} + m_CullTransparentMesh: 0 +--- !u!224 &1374660301 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1374660295} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1699720104} + m_Father: {fileID: 1871798295} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1452511678 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1452511679} + - component: {fileID: 1452511684} + - component: {fileID: 1452511683} + - component: {fileID: 1452511682} + - component: {fileID: 1452511681} + - component: {fileID: 1452511680} + m_Layer: 5 + m_Name: Answer E + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1452511679 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1452511678} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1194858314} + m_Father: {fileID: 594570832} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 330, y: -755.5} + m_SizeDelta: {x: 650, y: 133} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1452511680 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1452511678} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1452511681 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1452511678} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1452511682 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1452511678} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1452511683} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1452511683 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1452511678} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1452511684 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1452511678} + m_CullTransparentMesh: 0 +--- !u!1 &1456085080 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1456085081} + - component: {fileID: 1456085086} + - component: {fileID: 1456085085} + - component: {fileID: 1456085084} + - component: {fileID: 1456085083} + - component: {fileID: 1456085082} + m_Layer: 5 + m_Name: Answer A + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1456085081 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456085080} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 64233516} + m_Father: {fileID: 1559754537} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 300, y: -297} + m_SizeDelta: {x: 590, y: 174} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1456085082 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456085080} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1456085083 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456085080} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1456085084 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456085080} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1456085085} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1456085085 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456085080} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1456085086 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456085080} + m_CullTransparentMesh: 0 +--- !u!1 &1519050537 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1519050538} + - component: {fileID: 1519050543} + - component: {fileID: 1519050542} + - component: {fileID: 1519050541} + - component: {fileID: 1519050540} + - component: {fileID: 1519050539} + m_Layer: 5 + m_Name: Answer E + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1519050538 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519050537} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1060791689} + m_Father: {fileID: 1871798295} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1519050539 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519050537} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1519050540 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519050537} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1519050541 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519050537} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1519050542} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1519050542 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519050537} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1519050543 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519050537} + m_CullTransparentMesh: 0 +--- !u!1 &1559754536 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1559754537} + - component: {fileID: 1559754541} + - component: {fileID: 1559754540} + - component: {fileID: 1559754539} + - component: {fileID: 1559754538} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1559754537 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1559754536} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1126209067} + - {fileID: 1456085081} + - {fileID: 197293553} + - {fileID: 1629068645} + - {fileID: 1199396876} + - {fileID: 178325490} + m_Father: {fileID: 973268817} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 827} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &1559754538 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1559754536} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!114 &1559754539 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1559754536} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 5 + m_Right: 5 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 5 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1559754540 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1559754536} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9098039, g: 0.9098039, b: 0.9098039, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1559754541 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1559754536} + m_CullTransparentMesh: 0 +--- !u!1 &1576580511 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1576580512} + - component: {fileID: 1576580515} + - component: {fileID: 1576580514} + - component: {fileID: 1576580513} + - component: {fileID: 1576580516} + m_Layer: 5 + m_Name: Canvas TMP + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1576580512 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1576580511} + 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_Children: + - {fileID: 672877458} + m_Father: {fileID: 1236983896} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1576580513 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1576580511} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1576580514 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1576580511} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &1576580515 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1576580511} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!114 &1576580516 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1576580511} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 24b0dc2d1d494adbbec1f4db26b4cf83, type: 3} + m_Name: + m_EditorClassIdentifier: + UpdateInterval: 1 + AnchorPosition: 2 +--- !u!1 &1629068644 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1629068645} + - component: {fileID: 1629068650} + - component: {fileID: 1629068649} + - component: {fileID: 1629068648} + - component: {fileID: 1629068647} + - component: {fileID: 1629068646} + m_Layer: 5 + m_Name: Answer C + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1629068645 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629068644} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1139761476} + m_Father: {fileID: 1559754537} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 300, y: -573} + m_SizeDelta: {x: 590, y: 92} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1629068646 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629068644} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1629068647 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629068644} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1629068648 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629068644} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1629068649} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1629068649 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629068644} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1629068650 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629068644} + m_CullTransparentMesh: 0 +--- !u!1 &1686108074 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1686108077} + - component: {fileID: 1686108076} + - component: {fileID: 1686108075} + m_Layer: 0 + m_Name: TMP SubMeshUI [Anton SDF Material] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1686108075 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1686108074} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2140474, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_isDefaultMaterial: 1 + m_padding: 6.5 + m_canvasRenderer: {fileID: 1686108076} + m_TextComponent: {fileID: 1699720105} + m_materialReferenceIndex: 0 +--- !u!222 &1686108076 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1686108074} + m_CullTransparentMesh: 0 +--- !u!224 &1686108077 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1686108074} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1699720104} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1699720103 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1699720104} + - component: {fileID: 1699720106} + - component: {fileID: 1699720105} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1699720104 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1699720103} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1686108077} + - {fileID: 1322155520} + m_Father: {fileID: 1374660301} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1699720105 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1699720103} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: 'Question 1 + + Example of using Unity''s New UI and Layout components along with Masking with + TextMesh<#0040ff>Pro!' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + 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_isAlignmentEnumConverted: 0 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 14.97 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1699720105} + characterCount: 101 + spriteCount: 0 + spaceCount: 15 + wordCount: 16 + linkCount: 0 + lineCount: 4 + pageCount: 1 + materialCount: 3 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1699720106 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1699720103} + m_CullTransparentMesh: 0 +--- !u!1 &1729765363 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1729765364} + - component: {fileID: 1729765369} + - component: {fileID: 1729765368} + - component: {fileID: 1729765367} + - component: {fileID: 1729765366} + - component: {fileID: 1729765365} + m_Layer: 5 + m_Name: Answer A + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1729765364 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729765363} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 941241668} + m_Father: {fileID: 594570832} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 330, y: -297} + m_SizeDelta: {x: 650, y: 174} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1729765365 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729765363} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1729765366 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729765363} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1729765367 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729765363} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1729765368} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1729765368 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729765363} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1729765369 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729765363} + m_CullTransparentMesh: 0 +--- !u!1 &1736308203 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1736308204} + - component: {fileID: 1736308207} + - component: {fileID: 1736308206} + - component: {fileID: 1736308205} + - component: {fileID: 1736308208} + m_Layer: 5 + m_Name: Canvas TMP + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1736308204 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1736308203} + 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_Children: + - {fileID: 1257376144} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1736308205 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1736308203} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1736308206 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1736308203} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &1736308207 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1736308203} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!114 &1736308208 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1736308203} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 24b0dc2d1d494adbbec1f4db26b4cf83, type: 3} + m_Name: + m_EditorClassIdentifier: + UpdateInterval: 1 + AnchorPosition: 2 +--- !u!1 &1756545446 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1756545447} + - component: {fileID: 1756545449} + - component: {fileID: 1756545448} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1756545447 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1756545446} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 826920724} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 294.99997, y: -30} + m_SizeDelta: {x: 569.99994, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1756545448 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1756545446} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: D.<#ff0000>You selected the wrong answer. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 0 + m_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 1 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 0 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1756545449 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1756545446} + m_CullTransparentMesh: 0 +--- !u!1 &1848649447 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1848649448} + - component: {fileID: 1848649450} + - component: {fileID: 1848649449} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1848649448 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1848649447} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1126209067} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 295, y: -100} + m_SizeDelta: {x: 570, y: 190} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1848649449 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1848649447} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'Question 1 + + This is an example of using Ui.Text in Unity to display text using the New UI''s + auto layout functionality.' +--- !u!222 &1848649450 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1848649447} + m_CullTransparentMesh: 0 +--- !u!1 &1853075847 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1853075848} + - component: {fileID: 1853075853} + - component: {fileID: 1853075852} + - component: {fileID: 1853075851} + - component: {fileID: 1853075850} + - component: {fileID: 1853075849} + m_Layer: 5 + m_Name: Answer B + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1853075848 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853075847} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 799230987} + m_Father: {fileID: 594570832} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 330, y: -455.5} + m_SizeDelta: {x: 650, y: 133} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1853075849 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853075847} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1853075850 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853075847} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1853075851 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853075847} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1853075852} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1853075852 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853075847} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1853075853 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853075847} + m_CullTransparentMesh: 0 +--- !u!1 &1860225093 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1860225098} + - component: {fileID: 1860225097} + - component: {fileID: 1860225094} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1860225094 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1860225093} + m_Enabled: 1 +--- !u!20 &1860225097 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1860225093} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1860225098 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1860225093} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1871798294 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1871798295} + - component: {fileID: 1871798299} + - component: {fileID: 1871798298} + - component: {fileID: 1871798297} + - component: {fileID: 1871798296} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1871798295 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1871798294} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1374660301} + - {fileID: 1876543866} + - {fileID: 519242055} + - {fileID: 217857656} + - {fileID: 382277095} + - {fileID: 1519050538} + m_Father: {fileID: 760195239} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &1871798296 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1871798294} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!114 &1871798297 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1871798294} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 5 + m_Right: 5 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 5 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1871798298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1871798294} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9098039, g: 0.9098039, b: 0.9098039, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1871798299 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1871798294} + m_CullTransparentMesh: 0 +--- !u!1 &1876543865 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1876543866} + - component: {fileID: 1876543871} + - component: {fileID: 1876543870} + - component: {fileID: 1876543869} + - component: {fileID: 1876543868} + - component: {fileID: 1876543867} + m_Layer: 5 + m_Name: Answer A + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1876543866 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1876543865} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 929582474} + m_Father: {fileID: 1871798295} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1876543867 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1876543865} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1876543868 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1876543865} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1876543869 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1876543865} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1876543870} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1876543870 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1876543865} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1876543871 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1876543865} + m_CullTransparentMesh: 0 +--- !u!1 &1904784087 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1904784088} + - component: {fileID: 1904784093} + - component: {fileID: 1904784092} + - component: {fileID: 1904784091} + - component: {fileID: 1904784090} + - component: {fileID: 1904784089} + m_Layer: 5 + m_Name: Answer E + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1904784088 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1904784087} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 785126632} + m_Father: {fileID: 2034524132} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 299.99997, y: -780.5} + m_SizeDelta: {x: 589.99994, y: 171} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1904784089 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1904784087} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1904784090 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1904784087} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1904784091 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1904784087} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1904784092} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1904784092 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1904784087} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1904784093 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1904784087} + m_CullTransparentMesh: 0 +--- !u!1 &1940016221 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1940016222} + - component: {fileID: 1940016224} + - component: {fileID: 1940016223} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1940016222 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940016221} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 355544156} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 294.99997, y: -85.5} + m_SizeDelta: {x: 569.99994, y: 161} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1940016223 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940016221} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: A.This block of text contains three lines of text which requires + the container to dynamically expand vertically. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 0 + m_isAlignmentEnumConverted: 0 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 1 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 0 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 2100000, guid: 316f956b856b45c448987b5018ec3ef4, type: 2} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1940016224 +CanvasRenderer: + m_ObjectHideFlags: 2 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940016221} + m_CullTransparentMesh: 0 +--- !u!1 &1975887974 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1975887975} + - component: {fileID: 1975887980} + - component: {fileID: 1975887979} + - component: {fileID: 1975887978} + - component: {fileID: 1975887977} + - component: {fileID: 1975887976} + m_Layer: 5 + m_Name: Answer B + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1975887975 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1975887974} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 737955032} + m_Father: {fileID: 2034524132} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 299.99997, y: -463.5} + m_SizeDelta: {x: 589.99994, y: 131} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1975887976 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1975887974} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1975887977 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1975887974} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &1975887978 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1975887974} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1975887979} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1975887979 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1975887974} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1975887980 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1975887974} + m_CullTransparentMesh: 0 +--- !u!1 &1982914452 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1982914453} + - component: {fileID: 1982914457} + - component: {fileID: 1982914456} + - component: {fileID: 1982914454} + - component: {fileID: 1982914455} + m_Layer: 5 + m_Name: Scroll Rect + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1982914453 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982914452} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2034524132} + m_Father: {fileID: 672877458} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -40, y: -40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1982914454 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982914452} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 2034524132} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 0} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 0} + m_HorizontalScrollbarVisibility: 0 + m_VerticalScrollbarVisibility: 0 + m_HorizontalScrollbarSpacing: 0 + m_VerticalScrollbarSpacing: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1982914455 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982914452} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -146154839, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &1982914456 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982914452} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.5147059, g: 0.5147059, b: 0.5147059, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1982914457 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1982914452} + m_CullTransparentMesh: 0 +--- !u!1 &2014757816 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2014757822} + - component: {fileID: 2014757821} + - component: {fileID: 2014757820} + - component: {fileID: 2014757819} + - component: {fileID: 2014757818} + - component: {fileID: 2014757817} + m_Layer: 5 + m_Name: Answer C + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2014757817 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2014757816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: 60 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &2014757818 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2014757816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &2014757819 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2014757816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 2014757820} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &2014757820 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2014757816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.6691177, g: 0.6691177, b: 0.6691177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &2014757821 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2014757816} + m_CullTransparentMesh: 0 +--- !u!224 &2014757822 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2014757816} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 792312854} + m_Father: {fileID: 2034524132} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 299.99997, y: -579.5} + m_SizeDelta: {x: 589.99994, y: 91} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &2034524131 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2034524132} + - component: {fileID: 2034524136} + - component: {fileID: 2034524135} + - component: {fileID: 2034524134} + - component: {fileID: 2034524133} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2034524132 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2034524131} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 897593938} + - {fileID: 355544156} + - {fileID: 1975887975} + - {fileID: 2014757822} + - {fileID: 826920724} + - {fileID: 1904784088} + m_Father: {fileID: 1982914453} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 871} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &2034524133 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2034524131} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!114 &2034524134 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2034524131} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 5 + m_Right: 5 + m_Top: 5 + m_Bottom: 5 + m_ChildAlignment: 0 + m_Spacing: 5 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 +--- !u!114 &2034524135 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2034524131} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9098039, g: 0.9098039, b: 0.9098039, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &2034524136 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2034524131} + m_CullTransparentMesh: 0 +--- !u!1 &2060325071 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2060325072} + - component: {fileID: 2060325074} + - component: {fileID: 2060325073} + m_Layer: 0 + m_Name: TMP SubMeshUI [TextMeshPro/Sprite] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2060325072 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2060325071} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 969259720} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2060325073 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2060325071} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 2103686, guid: c41005c129ba4d66911b75229fd70b45, type: 2} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 0} + m_spriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, type: 2} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 2103686, guid: c41005c129ba4d66911b75229fd70b45, type: 2} + m_isDefaultMaterial: 1 + m_padding: 4 + m_canvasRenderer: {fileID: 2060325074} + m_TextComponent: {fileID: 969259721} + m_materialReferenceIndex: 0 +--- !u!222 &2060325074 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2060325071} + m_CullTransparentMesh: 0 +--- !u!1 &2099726591 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2099726592} + - component: {fileID: 2099726594} + - component: {fileID: 2099726593} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2099726592 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2099726591} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 112616781} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2099726593 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2099726591} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9098039, g: 0.9098039, b: 0.9098039, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &2099726594 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2099726591} + m_CullTransparentMesh: 0 +--- !u!1 &2138298318 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2138298319} + - component: {fileID: 2138298321} + - component: {fileID: 2138298320} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2138298319 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2138298318} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1175669143} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 325, y: -100} + m_SizeDelta: {x: 630, y: 190} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2138298320 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2138298318} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'Question 1 + + This is an example of using Ui.Text in Unity to display text using the New UI''s + auto layout functionality.' +--- !u!222 &2138298321 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2138298318} + m_CullTransparentMesh: 0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/18 - ScrollRect & Masking & Layout.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/18 - ScrollRect & Masking & Layout.unity.meta new file mode 100644 index 0000000..ffcc216 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/18 - ScrollRect & Masking & Layout.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 03f9d74cec8e4b94a29d2dfd177c821b +timeCreated: 1445416487 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/19 - Masking Texture & Soft Mask.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/19 - Masking Texture & Soft Mask.unity new file mode 100644 index 0000000..21dd2bd --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/19 - Masking Texture & Soft Mask.unity @@ -0,0 +1,604 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &141179451 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 141179456} + - component: {fileID: 141179455} + - component: {fileID: 141179452} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &141179452 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 141179451} + m_Enabled: 1 +--- !u!20 &141179455 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 141179451} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &141179456 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 141179451} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &794150059 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 794150060} + - component: {fileID: 794150062} + - component: {fileID: 794150061} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &794150060 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 794150059} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1633828367} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: -0.00000047683716} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &794150061 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 794150059} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: 'Soft Masking + + Move the text object relative to the parent with the 2D Rect Mask.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 42df1c7856584b6b8db9a509b6b10074, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 48 + m_fontSizeBase: 48 + 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_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 0 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 794150061} + characterCount: 79 + spriteCount: 0 + spaceCount: 14 + wordCount: 15 + linkCount: 0 + lineCount: 4 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &794150062 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 794150059} + m_CullTransparentMesh: 0 +--- !u!1 &984250720 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 984250723} + - component: {fileID: 984250722} + - component: {fileID: 984250721} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &984250721 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 984250720} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &984250722 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 984250720} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &984250723 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 984250720} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &995120765 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 995120769} + - component: {fileID: 995120768} + - component: {fileID: 995120767} + - component: {fileID: 995120766} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &995120766 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 995120765} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &995120767 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 995120765} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &995120768 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 995120765} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &995120769 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 995120765} + 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_Children: + - {fileID: 1633828367} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &1633828366 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1633828367} + - component: {fileID: 1633828370} + - component: {fileID: 1633828369} + - component: {fileID: 1633828368} + m_Layer: 5 + m_Name: Image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1633828367 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633828366} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 794150060} + m_Father: {fileID: 995120769} + 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, y: 0} + m_SizeDelta: {x: 200, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1633828368 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633828366} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -146154839, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &1633828369 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633828366} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.322, g: 0.53676474, b: 0.53676474, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1633828370 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633828366} + m_CullTransparentMesh: 0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/19 - Masking Texture & Soft Mask.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/19 - Masking Texture & Soft Mask.unity.meta new file mode 100644 index 0000000..0303c7d --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/19 - Masking Texture & Soft Mask.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9abcd5bd764646568a6ea70d00f9264c +timeCreated: 1465858578 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/20 - Input Field with Scrollbar.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/20 - Input Field with Scrollbar.unity new file mode 100644 index 0000000..39f4f24 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/20 - Input Field with Scrollbar.unity @@ -0,0 +1,2242 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &178751543 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 178751544} + m_Layer: 5 + m_Name: Content + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &178751544 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178751543} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1641939326} + m_Father: {fileID: 981581977} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -10, y: -10} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &184190504 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 184190509} + - component: {fileID: 184190508} + - component: {fileID: 184190505} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &184190505 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 184190504} + m_Enabled: 1 +--- !u!20 &184190508 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 184190504} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &184190509 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 184190504} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &222810364 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 222810365} + - component: {fileID: 222810368} + - component: {fileID: 222810367} + - component: {fileID: 222810366} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &222810365 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 222810364} + 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_Children: + - {fileID: 1652711586} + - {fileID: 1535389321} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &222810366 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 222810364} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &222810367 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 222810364} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &222810368 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 222810364} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &337669131 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 337669132} + - component: {fileID: 337669133} + m_Layer: 5 + m_Name: Text Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &337669132 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 337669131} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 894215173} + - {fileID: 655286161} + m_Father: {fileID: 1856700217} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -0.5} + m_SizeDelta: {x: -20, y: -13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &337669133 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 337669131} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -146154839, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &344071588 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 344071589} + - component: {fileID: 344071590} + m_Layer: 5 + m_Name: Text Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &344071589 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 344071588} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 891486379} + - {fileID: 640198376} + m_Father: {fileID: 1652711586} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -0.5} + m_SizeDelta: {x: -20, y: -13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &344071590 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 344071588} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -146154839, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &528619525 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 528619526} + - component: {fileID: 528619529} + - component: {fileID: 528619528} + - component: {fileID: 528619527} + m_Layer: 5 + m_Name: Chat Output - Scrollview + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &528619526 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 528619525} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 981581977} + - {fileID: 1511748068} + m_Father: {fileID: 1535389321} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 5, y: 50} + m_SizeDelta: {x: -5, y: 300} + m_Pivot: {x: 0, y: 0} +--- !u!114 &528619527 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 528619525} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0.392} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &528619528 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 528619525} + m_CullTransparentMesh: 0 +--- !u!114 &528619529 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 528619525} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 1641939326} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 178751544} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 1511748069} + m_HorizontalScrollbarVisibility: 2 + m_VerticalScrollbarVisibility: 1 + m_HorizontalScrollbarSpacing: -3 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &640198374 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 640198376} + - component: {fileID: 640198377} + - component: {fileID: 640198375} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &640198375 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 640198374} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: "This is an example of using a <#ff4f00>Scrollbar with the TextMesh<#4080ff>Pro + Text Input Field.\n\nThe Scrollbar position and size adjusts automatically as + new text is added.\n\nThe Home and End keys move the caret to the start or end + of each line.\n\nYou can now also use Page Up and Page Down to navigate through + the text.\n\nHolding down shift allows for multiple lines of text to be selected.\n\nDouble + clicks on words to select them.\u200B" + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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: 36 + m_fontSizeBase: 36 + 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: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_Maskable: 1 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!224 &640198376 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 640198374} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 344071589} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 5, y: 0} + m_SizeDelta: {x: -5, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &640198377 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 640198374} + m_CullTransparentMesh: 0 +--- !u!1 &655286160 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 655286161} + - component: {fileID: 655286163} + - component: {fileID: 655286162} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &655286161 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 655286160} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 337669132} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &655286162 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 655286160} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: "\u200B" + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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: 22 + m_fontSizeBase: 22 + 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: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_Maskable: 1 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &655286163 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 655286160} + m_CullTransparentMesh: 0 +--- !u!1 &670165398 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 670165399} + - component: {fileID: 670165401} + - component: {fileID: 670165400} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &670165399 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 670165398} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1716245244} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &670165400 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 670165398} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &670165401 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 670165398} + m_CullTransparentMesh: 0 +--- !u!1 &891486377 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 891486379} + - component: {fileID: 891486380} + - component: {fileID: 891486378} + m_Layer: 5 + m_Name: Placeholder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &891486378 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 891486377} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Enter text... + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 2133996082 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 0.5} + 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 2 + 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: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_Maskable: 1 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!224 &891486379 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 891486377} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 344071589} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 2.5, y: 0} + m_SizeDelta: {x: -5, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &891486380 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 891486377} + m_CullTransparentMesh: 0 +--- !u!1 &894215172 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 894215173} + - component: {fileID: 894215175} + - component: {fileID: 894215174} + m_Layer: 5 + m_Name: Placeholder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &894215173 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 894215172} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 337669132} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &894215174 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 894215172} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Enter text... + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 2133996082 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 0.5} + 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: 22 + m_fontSizeBase: 22 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 2 + 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: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_Maskable: 1 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &894215175 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 894215172} + m_CullTransparentMesh: 0 +--- !u!1 &910878157 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 910878158} + - component: {fileID: 910878160} + - component: {fileID: 910878159} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &910878158 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910878157} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1222391736} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &910878159 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910878157} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &910878160 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910878157} + m_CullTransparentMesh: 0 +--- !u!1 &981581976 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 981581977} + - component: {fileID: 981581978} + m_Layer: 5 + m_Name: Viewport + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &981581977 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 981581976} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 178751544} + m_Father: {fileID: 528619526} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 5, y: -5} + m_SizeDelta: {x: -25, y: -10} + m_Pivot: {x: 0, y: 1} +--- !u!114 &981581978 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 981581976} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -146154839, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &1093300042 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1093300043} + - component: {fileID: 1093300044} + m_Layer: 0 + m_Name: Chat Controller + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1093300043 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1093300042} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -85.92413, y: -80.43292, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1535389321} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1093300044 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1093300042} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 53d91f98a2664f5cb9af11de72ac54ec, type: 3} + m_Name: + m_EditorClassIdentifier: + ChatInputField: {fileID: 1856700218} + ChatDisplayOutput: {fileID: 1641939327} + ChatScrollbar: {fileID: 1511748069} +--- !u!1 &1154752061 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1154752063} + - component: {fileID: 1154752065} + - component: {fileID: 1154752064} + - component: {fileID: 1154752062} + m_Layer: 5 + m_Name: Scrollbar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1154752062 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1154752061} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -2061169968, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 670165400} + m_HandleRect: {fileID: 670165399} + m_Direction: 3 + m_Value: 0 + m_Size: 0.2543612 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!224 &1154752063 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1154752061} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1716245244} + m_Father: {fileID: 1652711586} + 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: 252.7, y: -0.0000030994415} + m_SizeDelta: {x: 20, y: 260} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1154752064 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1154752061} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1154752065 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1154752061} + m_CullTransparentMesh: 0 +--- !u!1 &1222391735 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1222391736} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1222391736 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1222391735} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 910878158} + m_Father: {fileID: 1511748068} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1511748067 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1511748068} + - component: {fileID: 1511748071} + - component: {fileID: 1511748070} + - component: {fileID: 1511748069} + m_Layer: 5 + m_Name: Scrollbar Vertical + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1511748068 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1511748067} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1222391736} + m_Father: {fileID: 528619526} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 0} + m_Pivot: {x: 1, y: 1} +--- !u!114 &1511748069 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1511748067} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -2061169968, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 910878159} + m_HandleRect: {fileID: 910878158} + m_Direction: 2 + m_Value: 0 + m_Size: 1 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &1511748070 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1511748067} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1511748071 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1511748067} + m_CullTransparentMesh: 0 +--- !u!1 &1535389320 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1535389321} + m_Layer: 5 + m_Name: Simple Chat + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1535389321 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1535389320} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1856700217} + - {fileID: 528619526} + - {fileID: 1093300043} + m_Father: {fileID: 222810365} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1641939325 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1641939326} + - component: {fileID: 1641939328} + - component: {fileID: 1641939327} + - component: {fileID: 1641939329} + m_Layer: 5 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1641939326 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1641939325} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 178751544} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1641939327 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1641939325} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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: 22 + m_fontSizeBase: 22 + 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: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + 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 + m_Maskable: 1 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1641939328 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1641939325} + m_CullTransparentMesh: 0 +--- !u!114 &1641939329 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1641939325} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!1 &1652711582 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1652711586} + - component: {fileID: 1652711585} + - component: {fileID: 1652711584} + - component: {fileID: 1652711583} + m_Layer: 5 + m_Name: TMP InputField + Scrollbar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1652711583 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1652711582} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2da0c512f12947e489f739169773d7ca, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1652711584} + m_TextViewport: {fileID: 344071589} + m_TextComponent: {fileID: 640198375} + m_Placeholder: {fileID: 891486378} + m_VerticalScrollbar: {fileID: 1154752062} + m_VerticalScrollbarEventHandler: {fileID: 0} + m_LayoutGroup: {fileID: 0} + m_ScrollSensitivity: 1 + m_ContentType: 0 + m_InputType: 0 + m_AsteriskChar: 42 + m_KeyboardType: 0 + m_LineType: 2 + m_HideMobileInput: 0 + m_HideSoftKeyboard: 0 + m_CharacterValidation: 0 + m_RegexValue: + m_GlobalPointSize: 36 + m_CharacterLimit: 0 + m_OnEndEdit: + m_PersistentCalls: + m_Calls: [] + m_OnSubmit: + m_PersistentCalls: + m_Calls: [] + m_OnSelect: + m_PersistentCalls: + m_Calls: [] + m_OnDeselect: + m_PersistentCalls: + m_Calls: [] + m_OnTextSelection: + m_PersistentCalls: + m_Calls: [] + m_OnEndTextSelection: + m_PersistentCalls: + m_Calls: [] + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_OnTouchScreenKeyboardStatusChanged: + m_PersistentCalls: + m_Calls: [] + m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_CustomCaretColor: 0 + m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412} + m_Text: 'This is an example of using a <#ff4f00>Scrollbar with the TextMesh<#4080ff>Pro + Text Input Field. + + + The Scrollbar position and size adjusts automatically as new text is added. + + + The Home and End keys move the caret to the start or end of each line. + + + You can now also use Page Up and Page Down to navigate through the text. + + + Holding down shift allows for multiple lines of text to be selected. + + + Double clicks on words to select them.' + m_CaretBlinkRate: 0.85 + m_CaretWidth: 1 + m_ReadOnly: 0 + m_RichText: 1 + m_GlobalFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_OnFocusSelectAll: 0 + m_ResetOnDeActivation: 0 + m_RestoreOriginalTextOnEscape: 1 + m_isRichTextEditingAllowed: 1 + m_LineLimit: 0 + m_InputValidator: {fileID: 0} +--- !u!114 &1652711584 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1652711582} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1652711585 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1652711582} + m_CullTransparentMesh: 0 +--- !u!224 &1652711586 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1652711582} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 344071589} + - {fileID: 1154752063} + m_Father: {fileID: 222810365} + 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: 320, y: 180} + m_SizeDelta: {x: 475, y: 260} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1716245243 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1716245244} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1716245244 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1716245243} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 670165399} + m_Father: {fileID: 1154752063} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1849378852 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1849378856} + - component: {fileID: 1849378855} + - component: {fileID: 1849378854} + - component: {fileID: 1849378853} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1849378853 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849378852} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &1849378854 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849378852} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1849378855 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849378852} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1849378856 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1849378852} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1856700216 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1856700217} + - component: {fileID: 1856700220} + - component: {fileID: 1856700219} + - component: {fileID: 1856700218} + m_Layer: 5 + m_Name: Chat Input Field + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1856700217 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1856700216} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 337669132} + m_Father: {fileID: 1535389321} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 2.5, y: 25} + m_SizeDelta: {x: -5, y: 40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1856700218 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1856700216} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2da0c512f12947e489f739169773d7ca, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1856700219} + m_TextViewport: {fileID: 337669132} + m_TextComponent: {fileID: 655286162} + m_Placeholder: {fileID: 894215174} + m_VerticalScrollbar: {fileID: 0} + m_VerticalScrollbarEventHandler: {fileID: 0} + m_LayoutGroup: {fileID: 0} + m_ScrollSensitivity: 1 + m_ContentType: 0 + m_InputType: 0 + m_AsteriskChar: 42 + m_KeyboardType: 0 + m_LineType: 0 + m_HideMobileInput: 0 + m_HideSoftKeyboard: 0 + m_CharacterValidation: 0 + m_RegexValue: + m_GlobalPointSize: 22 + m_CharacterLimit: 0 + m_OnEndEdit: + m_PersistentCalls: + m_Calls: [] + m_OnSubmit: + m_PersistentCalls: + m_Calls: [] + m_OnSelect: + m_PersistentCalls: + m_Calls: [] + m_OnDeselect: + m_PersistentCalls: + m_Calls: [] + m_OnTextSelection: + m_PersistentCalls: + m_Calls: [] + m_OnEndTextSelection: + m_PersistentCalls: + m_Calls: [] + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_OnTouchScreenKeyboardStatusChanged: + m_PersistentCalls: + m_Calls: [] + m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_CustomCaretColor: 0 + m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412} + m_Text: + m_CaretBlinkRate: 0.85 + m_CaretWidth: 1 + m_ReadOnly: 0 + m_RichText: 1 + m_GlobalFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_OnFocusSelectAll: 0 + m_ResetOnDeActivation: 1 + m_RestoreOriginalTextOnEscape: 0 + m_isRichTextEditingAllowed: 1 + m_LineLimit: 0 + m_InputValidator: {fileID: 0} +--- !u!114 &1856700219 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1856700216} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1856700220 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1856700216} + m_CullTransparentMesh: 0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/20 - Input Field with Scrollbar.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/20 - Input Field with Scrollbar.unity.meta new file mode 100644 index 0000000..80b9d38 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/20 - Input Field with Scrollbar.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 337f92480dd24675aae9e79210fb1ad9 +timeCreated: 1487199155 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/21 - Script Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/21 - Script Example.unity new file mode 100644 index 0000000..9fc7996 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/21 - Script Example.unity @@ -0,0 +1,239 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1079079952 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079079957} + - component: {fileID: 1079079956} + - component: {fileID: 1079079953} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1079079953 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 +--- !u!20 &1079079956 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 100 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1079079957 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079079952} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -28.517307} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1888731522 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1888731524} + - component: {fileID: 1888731523} + m_Layer: 0 + m_Name: Simple Script + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1888731523 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1888731522} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9eff140b25d64601aabc6ba32245d099, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1888731524 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1888731522} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/21 - Script Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/21 - Script Example.unity.meta new file mode 100644 index 0000000..bb879c7 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/21 - Script Example.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 50f52f9274434ecfb34dd87f0836f323 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/22 - Basic Scripting Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/22 - Basic Scripting Example.unity new file mode 100644 index 0000000..3ff1433 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/22 - Basic Scripting Example.unity @@ -0,0 +1,447 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &486248254 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 486248258} + - component: {fileID: 486248257} + - component: {fileID: 486248256} + - component: {fileID: 486248255} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &486248255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 486248254} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &486248256 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 486248254} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &486248257 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 486248254} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &486248258 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 486248254} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &691654662 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 691654663} + - component: {fileID: 691654665} + - component: {fileID: 691654664} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &691654663 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 691654662} + 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_Children: + - {fileID: 993643434} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &691654664 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 691654662} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &691654665 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 691654662} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 1 + m_Camera: {fileID: 1166195106} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &993643432 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 993643434} + - component: {fileID: 993643433} + m_Layer: 0 + m_Name: 'Text Object #1' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &993643433 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 993643432} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6f2c5b59b6874405865e2616e4ec276a, type: 3} + m_Name: + m_EditorClassIdentifier: + ObjectType: 1 + isStatic: 0 +--- !u!224 &993643434 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 993643432} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 691654663} + 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, y: 75} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1166195102 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1166195107} + - component: {fileID: 1166195106} + - component: {fileID: 1166195103} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1166195103 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1166195102} + m_Enabled: 1 +--- !u!20 &1166195106 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1166195102} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 36 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1166195107 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1166195102} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1590754846 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1590754848} + - component: {fileID: 1590754847} + m_Layer: 0 + m_Name: 'Text Object #2' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1590754847 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1590754846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6f2c5b59b6874405865e2616e4ec276a, type: 3} + m_Name: + m_EditorClassIdentifier: + ObjectType: 0 + isStatic: 0 +--- !u!4 &1590754848 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1590754846} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -7.5, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/22 - Basic Scripting Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/22 - Basic Scripting Example.unity.meta new file mode 100644 index 0000000..8f2fffe --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/22 - Basic Scripting Example.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6250f98e58fe4abbaada5d84b7ca846d +timeCreated: 1449626883 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/23 - Animating Vertex Attributes.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/23 - Animating Vertex Attributes.unity new file mode 100644 index 0000000..f63cfc6 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/23 - Animating Vertex Attributes.unity @@ -0,0 +1,520 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &66853331 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 66853334} + - component: {fileID: 66853333} + - component: {fileID: 66853332} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &66853332 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 66853331} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &66853333 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 66853331} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &66853334 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 66853331} + 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_Children: + - {fileID: 1992478846} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &1353010457 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1353010460} + - component: {fileID: 1353010459} + - component: {fileID: 1353010458} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1353010458 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1353010457} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1353010459 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1353010457} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1353010460 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1353010457} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1803781509 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1803781514} + - component: {fileID: 1803781513} + - component: {fileID: 1803781510} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1803781510 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1803781509} + m_Enabled: 1 +--- !u!20 &1803781513 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1803781509} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1803781514 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1803781509} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1992478845 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1992478846} + - component: {fileID: 1992478849} + - component: {fileID: 1992478848} + - component: {fileID: 1992478847} + - component: {fileID: 1992478850} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1992478846 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1992478845} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 66853334} + 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.000015258789, y: 0} + m_SizeDelta: {x: 670.1, y: 357.5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1992478847 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1992478845} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2ed57967c52645d390a89dcf8f61ba73, type: 3} + m_Name: + m_EditorClassIdentifier: + AngleMultiplier: 1 + SpeedMultiplier: 1 + CurveScale: 25 +--- !u!114 &1992478848 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1992478845} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Animating Vertex Attributes + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 749b9069dc4742c5bfa5c74644049926, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 92 + m_fontSizeBase: 92 + 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_isAlignmentEnumConverted: 1 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 0 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1992478848} + characterCount: 27 + spriteCount: 0 + spaceCount: 2 + wordCount: 3 + linkCount: 0 + lineCount: 2 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1992478849 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1992478845} + m_CullTransparentMesh: 0 +--- !u!114 &1992478850 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1992478845} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 91b8ba3d52e041fab2d0e0f169855539, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/23 - Animating Vertex Attributes.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/23 - Animating Vertex Attributes.unity.meta new file mode 100644 index 0000000..db7c2c8 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/23 - Animating Vertex Attributes.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 54e994244b4b467e8583cf2da6dcc716 +timeCreated: 1461311052 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example URP.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example URP.unity new file mode 100644 index 0000000..4107d10 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example URP.unity @@ -0,0 +1,3160 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 1 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 1 + m_FogColor: {r: 0.2784314, g: 0.2784314, b: 0.2784314, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 200 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 92bb8874fcf329247bea65570fd7532a, type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &45386653 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 45386654} + - component: {fileID: 45386657} + - component: {fileID: 45386656} + - component: {fileID: 45386655} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &45386654 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45386653} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.13052633, z: 0, w: -0.9914449} + m_LocalPosition: {x: 3.100965, y: -2.5, z: 0.3603902} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1198835735} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &45386655 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45386653} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &45386656 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45386653} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &45386657 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45386653} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &88657228 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 88657232} + - component: {fileID: 88657231} + - component: {fileID: 88657230} + - component: {fileID: 88657229} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &88657229 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88657228} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &88657230 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88657228} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &88657231 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88657228} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &88657232 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88657228} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.13052633, z: 0, w: -0.9914449} + m_LocalPosition: {x: 3.100965, y: -2.5, z: 0.3603902} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 551637154} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &130188541 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 130188545} + - component: {fileID: 130188544} + - component: {fileID: 130188542} + m_Layer: 0 + m_Name: Ground + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &130188542 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 130188541} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 71529b88994c1a341b22bc57c038674a, 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!33 &130188544 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 130188541} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &130188545 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 130188541} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 20, y: 1, z: 20} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &151148667 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 151148673} + - component: {fileID: 151148671} + - component: {fileID: 151148668} + m_Layer: 0 + m_Name: TextMesh Pro - Caption + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &151148668 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151148667} + 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: The Ultimate Text Solution for Unity + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 5302535af1044152a457ed104f1f4b91, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 90722b8bd74d9aa49958562aff7bdf76, 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: 22 + m_fontSizeBase: 22 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 24 + m_fontSizeMax: 96 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 2.7 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: -10 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + 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: 151148671} + m_maskType: 0 +--- !u!23 &151148671 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151148667} + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 90722b8bd74d9aa49958562aff7bdf76, 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!224 &151148673 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151148667} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 1.65} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 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, y: 7.69} + m_SizeDelta: {x: 40, y: 5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &176749293 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 176749294} + m_Layer: 0 + m_Name: Crate Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &176749294 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 176749293} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: -0.8657618, z: 0, w: 0.5004564} + m_LocalPosition: {x: 24.020954, y: 5, z: 9.024419} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1533777692} + - {fileID: 727433510} + - {fileID: 1109394275} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &181840061 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 181840064} + - component: {fileID: 181840063} + - component: {fileID: 181840062} + - component: {fileID: 181840065} + m_Layer: 0 + m_Name: Point Light - Red + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &181840062 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181840061} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 2 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 1.25 + RotationRange: 20 +--- !u!108 &181840063 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181840061} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 2 + m_Color: {r: 1, g: 0, b: 0, a: 1} + m_Intensity: 300 + m_Range: 30 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &181840064 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181840061} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 10, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1423076965} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &181840065 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181840061} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &185619762 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 185619763} + - component: {fileID: 185619766} + - component: {fileID: 185619765} + - component: {fileID: 185619764} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &185619763 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 185619762} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.08776625, z: 0, w: 0.99614114} + m_LocalPosition: {x: -3.4550133, y: -2.5, z: 0.58618975} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 551637154} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &185619764 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 185619762} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &185619765 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 185619762} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &185619766 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 185619762} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &280649733 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 280649738} + - component: {fileID: 280649737} + - component: {fileID: 280649734} + - component: {fileID: 280649740} + - component: {fileID: 280649739} + - component: {fileID: 280649741} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &280649734 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 +--- !u!20 &280649737 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.2784314, g: 0.2784314, b: 0.2784314, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 54 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &280649738 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + serializedVersion: 2 + m_LocalRotation: {x: -0.14296447, y: -0.27517763, z: 0.04141913, w: -0.94980156} + m_LocalPosition: {x: -83.26071, y: 35.23844, z: -101.45492} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &280649739 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2d687537154440a3913a9a3c7977978c, type: 3} + m_Name: + m_EditorClassIdentifier: + CameraTarget: {fileID: 914799696} + FollowDistance: 45 + MaxFollowDistance: 500 + MinFollowDistance: 2 + ElevationAngle: 10 + MaxElevationAngle: 85 + MinElevationAngle: 0 + OrbitalAngle: 0 + CameraMode: 0 + MovementSmoothing: 1 + RotationSmoothing: 0 + MovementSmoothingValue: 25 + RotationSmoothingValue: 5 + MoveSensitivity: 2 +--- !u!114 &280649740 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 686ec78b56aa445795335fbadafcfaa4, type: 3} + m_Name: + m_EditorClassIdentifier: + UpdateInterval: 1 + AnchorPosition: 2 +--- !u!114 &280649741 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 +--- !u!1 &551637153 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 551637154} + m_Layer: 0 + m_Name: Crate Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &551637154 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 551637153} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: -0.8657618, z: 0, w: 0.5004564} + m_LocalPosition: {x: -2.9828825, y: 5, z: 37.440086} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 88657232} + - {fileID: 185619763} + - {fileID: 1231649826} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &727433509 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 727433510} + - component: {fileID: 727433513} + - component: {fileID: 727433512} + - component: {fileID: 727433511} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &727433510 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727433509} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.08776625, z: 0, w: 0.99614114} + m_LocalPosition: {x: -3.4550133, y: -2.5, z: 0.58618975} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 176749294} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &727433511 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727433509} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &727433512 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727433509} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &727433513 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727433509} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &914799695 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 914799696} + m_Layer: 0 + m_Name: Camera Anchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &914799696 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 914799695} + 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} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1041320347 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1041320350} + - component: {fileID: 1041320349} + - component: {fileID: 1041320348} + - component: {fileID: 1041320351} + m_Layer: 0 + m_Name: Spotlight - Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1041320348 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1041320347} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 1 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 1.5 + RotationRange: 25 +--- !u!108 &1041320349 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1041320347} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 0 + m_Color: {r: 0, g: 0, b: 1, a: 1} + m_Intensity: 2.078326 + m_Range: 100 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1041320350 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1041320347} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 25, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1888380059} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1041320351 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1041320347} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &1079961348 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079961351} + - component: {fileID: 1079961350} + - component: {fileID: 1079961349} + - component: {fileID: 1079961352} + m_Layer: 0 + m_Name: Point Light - Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1079961349 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079961348} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 2 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 1 + RotationRange: 20 +--- !u!108 &1079961350 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079961348} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 2 + m_Color: {r: 0, g: 0, b: 1, a: 1} + m_Intensity: 300 + m_Range: 30 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1079961351 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079961348} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -6.86, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1423076965} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1079961352 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079961348} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &1097136440 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1097136442} + - component: {fileID: 1097136441} + - component: {fileID: 1097136443} + m_Layer: 0 + m_Name: Directional light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1097136441 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097136440} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 1 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 0.48453492 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.107 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1097136442 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097136440} + serializedVersion: 2 + m_LocalRotation: {x: 0.2677142, y: 0.16857424, z: -0.04763104, w: 0.9474403} + m_LocalPosition: {x: -1.5021362, y: 36.79033, z: -19.266798} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1097136443 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097136440} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &1109394274 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1109394275} + - component: {fileID: 1109394278} + - component: {fileID: 1109394277} + - component: {fileID: 1109394276} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1109394275 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1109394274} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: -0.17020881, z: 0, w: 0.98540807} + m_LocalPosition: {x: 0.067751884, y: 2.5291405, z: -0.13494396} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 176749294} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &1109394276 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1109394274} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &1109394277 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1109394274} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1109394278 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1109394274} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1139141065 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1139141069} + - component: {fileID: 1139141068} + - component: {fileID: 1139141067} + - component: {fileID: 1139141066} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &1139141066 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139141065} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &1139141067 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139141065} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1139141068 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139141065} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1139141069 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139141065} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.08776625, z: 0, w: 0.99614114} + m_LocalPosition: {x: -3.4550133, y: -2.5, z: 0.58618975} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1198835735} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1142730609 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1142730611} + - component: {fileID: 1142730610} + - component: {fileID: 1142730612} + - component: {fileID: 1142730613} + m_Layer: 0 + m_Name: Spotlight - Green + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1142730610 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1142730609} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 0 + m_Color: {r: 0, g: 1, b: 0, a: 1} + m_Intensity: 2.078326 + m_Range: 100 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1142730611 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1142730609} + 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: 1888380059} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1142730612 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1142730609} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 1 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 2 + RotationRange: 25 +--- !u!114 &1142730613 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1142730609} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &1185126715 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1185126718} + - component: {fileID: 1185126717} + - component: {fileID: 1185126716} + - component: {fileID: 1185126719} + m_Layer: 0 + m_Name: Spotlight - White + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!114 &1185126716 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1185126715} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 1 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 0 + RotationRange: 30 +--- !u!108 &1185126717 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1185126715} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 1.8778619 + m_Range: 100 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1185126718 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1185126715} + serializedVersion: 2 + m_LocalRotation: {x: 0.17453936, y: 0, z: 0, w: 0.98465025} + m_LocalPosition: {x: 0.22756672, y: 25, z: -50} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1185126719 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1185126715} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &1198835734 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1198835735} + m_Layer: 0 + m_Name: Crate Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1198835735 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1198835734} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -22.891533, y: 5, z: -4.165652} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 45386654} + - {fileID: 1139141069} + - {fileID: 1547569612} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1231649825 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1231649826} + - component: {fileID: 1231649829} + - component: {fileID: 1231649828} + - component: {fileID: 1231649827} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1231649826 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231649825} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: -0.17020881, z: 0, w: 0.98540807} + m_LocalPosition: {x: 0.067751884, y: 2.5291405, z: -0.13494396} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 551637154} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &1231649827 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231649825} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &1231649828 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231649825} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1231649829 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231649825} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1328606984 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1328606987} + - component: {fileID: 1328606986} + - component: {fileID: 1328606985} + - component: {fileID: 1328606988} + m_Layer: 0 + m_Name: Spotlight - Red + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1328606985 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328606984} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 1 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 2.5 + RotationRange: 25 +--- !u!108 &1328606986 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328606984} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 0 + m_Color: {r: 1, g: 0, b: 0, a: 1} + m_Intensity: 2.078326 + m_Range: 100 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1328606987 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328606984} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -25, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1888380059} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1328606988 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328606984} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &1423076964 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1423076965} + m_Layer: 0 + m_Name: Pointlight - Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1423076965 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1423076964} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 10, z: -15} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1079961351} + - {fileID: 1625386229} + - {fileID: 181840064} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1533777688 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1533777692} + - component: {fileID: 1533777691} + - component: {fileID: 1533777690} + - component: {fileID: 1533777689} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &1533777689 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1533777688} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &1533777690 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1533777688} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1533777691 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1533777688} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1533777692 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1533777688} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.13052633, z: 0, w: -0.9914449} + m_LocalPosition: {x: 3.100965, y: -2.5, z: 0.3603902} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 176749294} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1547569611 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1547569612} + - component: {fileID: 1547569615} + - component: {fileID: 1547569614} + - component: {fileID: 1547569613} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1547569612 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1547569611} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: -0.17020881, z: 0, w: 0.98540807} + m_LocalPosition: {x: 0.067751884, y: 2.5291405, z: -0.13494396} + m_LocalScale: {x: 5, y: 5, z: 5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1198835735} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &1547569613 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1547569611} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3b5cc91c3bf8cf74391252247f52fb59, 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 &1547569614 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1547569611} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1547569615 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1547569611} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1625386226 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1625386229} + - component: {fileID: 1625386228} + - component: {fileID: 1625386227} + - component: {fileID: 1625386230} + m_Layer: 0 + m_Name: Point Light - Green + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1625386227 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1625386226} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 2 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 1.5 + RotationRange: 30 +--- !u!108 &1625386228 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1625386226} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 2 + m_Color: {r: 0, g: 1, b: 0, a: 1} + m_Intensity: 300 + m_Range: 30 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1625386229 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1625386226} + 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: 1423076965} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1625386230 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1625386226} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &1743864370 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1743864372} + - component: {fileID: 1743864371} + - component: {fileID: 1743864373} + - component: {fileID: 1743864374} + m_Layer: 0 + m_Name: Spotlight - Backlight + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1743864371 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743864370} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 0 + m_Color: {r: 0, g: 0.5862069, b: 1, a: 1} + m_Intensity: 300 + m_Range: 80 + m_SpotAngle: 45 + m_InnerSpotAngle: 33.15822 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1743864372 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743864370} + serializedVersion: 2 + m_LocalRotation: {x: 0.041116327, y: 0.8697486, z: -0.07354433, w: 0.4862491} + m_LocalPosition: {x: -39.42447, y: 21.20903, z: 24.45694} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1743864373 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743864370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 1 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 2 + RotationRange: 45 +--- !u!114 &1743864374 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743864370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 3 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!1 &1746165346 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1746165351} + - component: {fileID: 1746165349} + - component: {fileID: 1746165347} + m_Layer: 0 + m_Name: TextMesh Pro - Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1746165347 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1746165346} + 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: TextMesh <#50aaff>PRO! + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 6751ce1a4611b3940812c13a6847d94f, 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: 72 + m_fontSizeBase: 72 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 24 + m_fontSizeMax: 96 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 7 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: -10 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + 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: 1746165349} + m_maskType: 0 +--- !u!23 &1746165349 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1746165346} + m_Enabled: 1 + m_CastShadows: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 6751ce1a4611b3940812c13a6847d94f, 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!224 &1746165351 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1746165346} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 1.65} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 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, y: 14.47} + m_SizeDelta: {x: 40, y: 9.007265} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1888380058 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1888380059} + m_Layer: 0 + m_Name: Spotlight - Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &1888380059 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1888380058} + serializedVersion: 2 + m_LocalRotation: {x: 0.16051155, y: 0, z: 0, w: 0.98703396} + m_LocalPosition: {x: 0, y: 25, z: -50} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1041320350} + - {fileID: 1142730611} + - {fileID: 1328606987} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 914799696} + - {fileID: 176749294} + - {fileID: 551637154} + - {fileID: 1198835735} + - {fileID: 1097136442} + - {fileID: 130188545} + - {fileID: 280649738} + - {fileID: 1423076965} + - {fileID: 1743864372} + - {fileID: 1888380059} + - {fileID: 1185126718} + - {fileID: 151148673} + - {fileID: 1746165351} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example URP.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example URP.unity.meta new file mode 100644 index 0000000..34705b1 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example URP.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 57694ed9d1cd1e340a4924c0f2eac8e3 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example.unity new file mode 100644 index 0000000..77769b7 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example.unity @@ -0,0 +1,2687 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 1 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 1 + m_FogColor: {r: 0.2784314, g: 0.2784314, b: 0.2784314, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 200 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 92bb8874fcf329247bea65570fd7532a, + type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &45386653 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 45386654} + - component: {fileID: 45386657} + - component: {fileID: 45386656} + - component: {fileID: 45386655} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &45386654 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45386653} + m_LocalRotation: {x: 0, y: 0.13052633, z: 0, w: -0.9914449} + m_LocalPosition: {x: 3.100965, y: -2.5, z: 0.3603902} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 1198835735} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &45386655 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45386653} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &45386656 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45386653} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &45386657 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45386653} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &88657228 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 88657232} + - component: {fileID: 88657231} + - component: {fileID: 88657230} + - component: {fileID: 88657229} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &88657229 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88657228} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &88657230 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88657228} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &88657231 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88657228} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &88657232 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88657228} + m_LocalRotation: {x: 0, y: 0.13052633, z: 0, w: -0.9914449} + m_LocalPosition: {x: 3.100965, y: -2.5, z: 0.3603902} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 551637154} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &130188541 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 130188545} + - component: {fileID: 130188544} + - component: {fileID: 130188542} + m_Layer: 0 + m_Name: Ground + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &130188542 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 130188541} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: aadd5a709a48466c887296bb5b1b8110, 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!33 &130188544 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 130188541} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &130188545 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 130188541} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 20, y: 1, z: 20} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &151148667 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 151148673} + - component: {fileID: 151148671} + - component: {fileID: 151148668} + m_Layer: 10 + m_Name: TextMesh Pro - Caption + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &151148668 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151148667} + 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: The Ultimate Text Solution for Unity + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 5302535af1044152a457ed104f1f4b91, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: e6b276ec991f467aa14ef1f3cc665993, 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: 22 + m_fontSizeBase: 22 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 24 + m_fontSizeMax: 96 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 2.7 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: -10 + 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.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 151148671} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &151148671 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151148667} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b276ec991f467aa14ef1f3cc665993, 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!224 &151148673 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151148667} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 1.65} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 11 + 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: 7.69} + m_SizeDelta: {x: 40, y: 5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &176749293 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 176749294} + m_Layer: 0 + m_Name: Crate Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &176749294 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 176749293} + m_LocalRotation: {x: 0, y: -0.8657618, z: 0, w: 0.5004564} + m_LocalPosition: {x: 24.020954, y: 5, z: 9.024419} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1533777692} + - {fileID: 727433510} + - {fileID: 1109394275} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &181840061 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 181840064} + - component: {fileID: 181840063} + - component: {fileID: 181840062} + m_Layer: 0 + m_Name: Point Light - Red + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &181840062 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181840061} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + SpinSpeed: 1.25 + RotationRange: 20 + Motion: 2 +--- !u!108 &181840063 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181840061} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 2 + m_Shape: 0 + m_Color: {r: 1, g: 0, b: 0, a: 1} + m_Intensity: 2.2579021 + m_Range: 30 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &181840064 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 181840061} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 10, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1423076965} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &185619762 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 185619763} + - component: {fileID: 185619766} + - component: {fileID: 185619765} + - component: {fileID: 185619764} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &185619763 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 185619762} + m_LocalRotation: {x: 0, y: 0.08776625, z: 0, w: 0.99614114} + m_LocalPosition: {x: -3.4550133, y: -2.5, z: 0.58618975} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 551637154} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &185619764 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 185619762} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &185619765 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 185619762} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &185619766 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 185619762} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &280649733 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 280649738} + - component: {fileID: 280649737} + - component: {fileID: 280649734} + - component: {fileID: 280649740} + - component: {fileID: 280649739} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &280649734 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 +--- !u!20 &280649737 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.2784314, g: 0.2784314, b: 0.2784314, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 54 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &280649738 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_LocalRotation: {x: -0.14296447, y: -0.27517763, z: 0.04141913, w: -0.94980156} + m_LocalPosition: {x: -83.26071, y: 35.23844, z: -101.45492} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &280649739 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2d687537154440a3913a9a3c7977978c, type: 3} + m_Name: + m_EditorClassIdentifier: + CameraTarget: {fileID: 914799696} + FollowDistance: 45 + MaxFollowDistance: 500 + MinFollowDistance: 2 + ElevationAngle: 10 + MaxElevationAngle: 85 + MinElevationAngle: 0 + OrbitalAngle: 0 + CameraMode: 0 + MovementSmoothing: 1 + RotationSmoothing: 0 + MovementSmoothingValue: 25 + RotationSmoothingValue: 5 + MoveSensitivity: 2 +--- !u!114 &280649740 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 686ec78b56aa445795335fbadafcfaa4, type: 3} + m_Name: + m_EditorClassIdentifier: + UpdateInterval: 1 + AnchorPosition: 2 +--- !u!1 &551637153 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 551637154} + m_Layer: 0 + m_Name: Crate Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &551637154 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 551637153} + m_LocalRotation: {x: 0, y: -0.8657618, z: 0, w: 0.5004564} + m_LocalPosition: {x: -2.9828825, y: 5, z: 37.440086} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 88657232} + - {fileID: 185619763} + - {fileID: 1231649826} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &727433509 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 727433510} + - component: {fileID: 727433513} + - component: {fileID: 727433512} + - component: {fileID: 727433511} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &727433510 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727433509} + m_LocalRotation: {x: 0, y: 0.08776625, z: 0, w: 0.99614114} + m_LocalPosition: {x: -3.4550133, y: -2.5, z: 0.58618975} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 176749294} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &727433511 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727433509} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &727433512 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727433509} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &727433513 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 727433509} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &914799695 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 914799696} + m_Layer: 0 + m_Name: Camera Anchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &914799696 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 914799695} + 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} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1041320347 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1041320350} + - component: {fileID: 1041320349} + - component: {fileID: 1041320348} + m_Layer: 0 + m_Name: Spotlight - Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1041320348 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1041320347} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + SpinSpeed: 1.5 + RotationRange: 25 + Motion: 1 +--- !u!108 &1041320349 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1041320347} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 0 + m_Shape: 0 + m_Color: {r: 0, g: 0, b: 1, a: 1} + m_Intensity: 2.078326 + m_Range: 100 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1041320350 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1041320347} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 25, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1888380059} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1079961348 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079961351} + - component: {fileID: 1079961350} + - component: {fileID: 1079961349} + m_Layer: 0 + m_Name: Point Light - Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1079961349 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079961348} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + SpinSpeed: 1 + RotationRange: 20 + Motion: 2 +--- !u!108 &1079961350 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079961348} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 2 + m_Shape: 0 + m_Color: {r: 0, g: 0, b: 1, a: 1} + m_Intensity: 2.2579021 + m_Range: 30 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1079961351 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079961348} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -10, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1423076965} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1097136440 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1097136442} + - component: {fileID: 1097136441} + m_Layer: 0 + m_Name: Directional light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1097136441 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097136440} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 0.48453492 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.107 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1097136442 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097136440} + m_LocalRotation: {x: 0.2677142, y: 0.16857424, z: -0.04763104, w: 0.9474403} + m_LocalPosition: {x: -1.5021362, y: 36.79033, z: -19.266798} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1109394274 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1109394275} + - component: {fileID: 1109394278} + - component: {fileID: 1109394277} + - component: {fileID: 1109394276} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1109394275 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1109394274} + m_LocalRotation: {x: 0, y: -0.17020881, z: 0, w: 0.98540807} + m_LocalPosition: {x: 0.067751884, y: 2.5291405, z: -0.13494396} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 176749294} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &1109394276 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1109394274} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &1109394277 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1109394274} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1109394278 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1109394274} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1139141065 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1139141069} + - component: {fileID: 1139141068} + - component: {fileID: 1139141067} + - component: {fileID: 1139141066} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &1139141066 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139141065} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &1139141067 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139141065} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1139141068 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139141065} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1139141069 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1139141065} + m_LocalRotation: {x: 0, y: 0.08776625, z: 0, w: 0.99614114} + m_LocalPosition: {x: -3.4550133, y: -2.5, z: 0.58618975} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 1198835735} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1142730609 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1142730611} + - component: {fileID: 1142730610} + - component: {fileID: 1142730612} + m_Layer: 0 + m_Name: Spotlight - Green + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1142730610 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1142730609} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 0 + m_Shape: 0 + m_Color: {r: 0, g: 1, b: 0, a: 1} + m_Intensity: 2.078326 + m_Range: 100 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1142730611 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1142730609} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1888380059} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1142730612 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1142730609} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + SpinSpeed: 2 + RotationRange: 25 + Motion: 1 +--- !u!1 &1185126715 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1185126718} + - component: {fileID: 1185126717} + - component: {fileID: 1185126716} + m_Layer: 0 + m_Name: Spotlight - White + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!114 &1185126716 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1185126715} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + SpinSpeed: 0 + RotationRange: 30 + Motion: 1 +--- !u!108 &1185126717 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1185126715} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 0 + m_Shape: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 1.8778619 + m_Range: 100 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1185126718 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1185126715} + m_LocalRotation: {x: 0.17453936, y: 0, z: 0, w: 0.98465025} + m_LocalPosition: {x: 0.22756672, y: 25, z: -50} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 10 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1198835734 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1198835735} + m_Layer: 0 + m_Name: Crate Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1198835735 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1198835734} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -22.891533, y: 5, z: -4.165652} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 45386654} + - {fileID: 1139141069} + - {fileID: 1547569612} + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1231649825 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1231649826} + - component: {fileID: 1231649829} + - component: {fileID: 1231649828} + - component: {fileID: 1231649827} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1231649826 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231649825} + m_LocalRotation: {x: 0, y: -0.17020881, z: 0, w: 0.98540807} + m_LocalPosition: {x: 0.067751884, y: 2.5291405, z: -0.13494396} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 551637154} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &1231649827 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231649825} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &1231649828 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231649825} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1231649829 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231649825} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1328606984 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1328606987} + - component: {fileID: 1328606986} + - component: {fileID: 1328606985} + m_Layer: 0 + m_Name: Spotlight - Red + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1328606985 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328606984} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + SpinSpeed: 2.5 + RotationRange: 25 + Motion: 1 +--- !u!108 &1328606986 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328606984} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 0 + m_Shape: 0 + m_Color: {r: 1, g: 0, b: 0, a: 1} + m_Intensity: 2.078326 + m_Range: 100 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1328606987 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328606984} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -25, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1888380059} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1423076964 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1423076965} + m_Layer: 0 + m_Name: Pointlight - Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1423076965 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1423076964} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 10, z: -15} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1079961351} + - {fileID: 1625386229} + - {fileID: 181840064} + m_Father: {fileID: 0} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1533777688 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1533777692} + - component: {fileID: 1533777691} + - component: {fileID: 1533777690} + - component: {fileID: 1533777689} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &1533777689 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1533777688} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &1533777690 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1533777688} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1533777691 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1533777688} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1533777692 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1533777688} + m_LocalRotation: {x: 0, y: 0.13052633, z: 0, w: -0.9914449} + m_LocalPosition: {x: 3.100965, y: -2.5, z: 0.3603902} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 176749294} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1547569611 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1547569612} + - component: {fileID: 1547569615} + - component: {fileID: 1547569614} + - component: {fileID: 1547569613} + m_Layer: 0 + m_Name: Crate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1547569612 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1547569611} + m_LocalRotation: {x: 0, y: -0.17020881, z: 0, w: 0.98540807} + m_LocalPosition: {x: 0.067751884, y: 2.5291405, z: -0.13494396} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: [] + m_Father: {fileID: 1198835735} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &1547569613 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1547569611} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e6b9b44320f4448d9d5e0ee634259966, 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 &1547569614 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1547569611} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1547569615 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1547569611} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1625386226 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1625386229} + - component: {fileID: 1625386228} + - component: {fileID: 1625386227} + m_Layer: 0 + m_Name: Point Light - Green + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1625386227 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1625386226} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + SpinSpeed: 1.5 + RotationRange: 30 + Motion: 2 +--- !u!108 &1625386228 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1625386226} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 2 + m_Shape: 0 + m_Color: {r: 0, g: 1, b: 0, a: 1} + m_Intensity: 2.2579021 + m_Range: 30 + m_SpotAngle: 60 + m_InnerSpotAngle: 45.074013 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1625386229 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1625386226} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1423076965} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1743864370 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1743864372} + - component: {fileID: 1743864371} + - component: {fileID: 1743864373} + m_Layer: 0 + m_Name: Spotlight - Backlight + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1743864371 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743864370} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 0 + m_Shape: 0 + m_Color: {r: 0, g: 0.5862069, b: 1, a: 1} + m_Intensity: 2.2579021 + m_Range: 80 + m_SpotAngle: 45 + m_InnerSpotAngle: 33.15822 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1743864372 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743864370} + m_LocalRotation: {x: 0.041116327, y: 0.8697486, z: -0.07354433, w: 0.4862491} + m_LocalPosition: {x: -39.42447, y: 21.20903, z: 24.45694} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 8 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1743864373 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1743864370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + SpinSpeed: 2 + RotationRange: 45 + Motion: 1 +--- !u!1 &1746165346 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1746165351} + - component: {fileID: 1746165349} + - component: {fileID: 1746165347} + m_Layer: 10 + m_Name: TextMesh Pro - Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1746165347 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1746165346} + 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: TextMesh <#50aaff>PRO! + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: f4e195ac1e204eff960149d1cb34e18c, 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: 72 + m_fontSizeBase: 72 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 24 + m_fontSizeMax: 96 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 7 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: -10 + 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.3 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 0 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1746165349} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1746165349 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1746165346} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: f4e195ac1e204eff960149d1cb34e18c, 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!224 &1746165351 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1746165346} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 1.65} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 12 + 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: 14.47} + m_SizeDelta: {x: 40, y: 9.007265} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1888380058 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1888380059} + m_Layer: 0 + m_Name: Spotlight - Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &1888380059 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1888380058} + m_LocalRotation: {x: 0.16051155, y: 0, z: 0, w: 0.98703396} + m_LocalPosition: {x: 0, y: 25, z: -50} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1041320350} + - {fileID: 1142730611} + - {fileID: 1328606987} + m_Father: {fileID: 0} + m_RootOrder: 9 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example.unity.meta new file mode 100644 index 0000000..739fe62 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/24 - Surface Shader Example.unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 8c4969fd8ba94a68b07cf11f3e7a5137 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/25 - Sunny Days Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/25 - Sunny Days Example.unity new file mode 100644 index 0000000..fc579bc --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/25 - Sunny Days Example.unity @@ -0,0 +1,615 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &754594204 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 754594209} + - component: {fileID: 754594208} + - component: {fileID: 754594205} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &754594205 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 754594204} + m_Enabled: 1 +--- !u!20 &754594208 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 754594204} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &754594209 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 754594204} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1027572109 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1027572110} + - component: {fileID: 1027572112} + - component: {fileID: 1027572111} + - component: {fileID: 1027572113} + m_Layer: 0 + m_Name: TextMeshPro Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1027572110 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027572109} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1945473988} + m_Father: {fileID: 1098613607} + 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, y: 0} + m_SizeDelta: {x: 1086, y: 718} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1027572111 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027572109} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Sunny Days! + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8a89fa14b10d46a99122fd4f73fca9a2, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 6522f30e342599e4e9dd4cc2cc03c830, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 326.41 + m_fontSizeBase: 326.41 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 32 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_isAlignmentEnumConverted: 0 + m_characterSpacing: 0.57 + m_wordSpacing: 0 + m_lineSpacing: -34.82 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: 6 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 1 + m_verticalMapping: 1 + m_uvLineOffset: 0.5 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1027572111} + characterCount: 11 + spriteCount: 0 + spaceCount: 1 + wordCount: 2 + linkCount: 0 + lineCount: 2 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1027572112 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027572109} + m_CullTransparentMesh: 0 +--- !u!114 &1027572113 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027572109} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 790744c462254b7ba8038e6ed28b3db2, type: 3} + m_Name: + m_EditorClassIdentifier: + VertexCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 10.12177 + outSlope: 10.12177 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.5 + value: 2 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: -10.837328 + outSlope: -10.837328 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + AngleMultiplier: 1 + SpeedMultiplier: 1 + CurveScale: 2 +--- !u!1 &1098613604 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1098613607} + - component: {fileID: 1098613606} + - component: {fileID: 1098613605} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1098613605 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1098613604} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &1098613606 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1098613604} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &1098613607 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1098613604} + 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_Children: + - {fileID: 1027572110} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &1493960016 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1493960019} + - component: {fileID: 1493960018} + - component: {fileID: 1493960017} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1493960017 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1493960016} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1493960018 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1493960016} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1493960019 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1493960016} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1945473987 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1945473988} + - component: {fileID: 1945473990} + - component: {fileID: 1945473989} + m_Layer: 0 + m_Name: TMP SubMeshUI [IMPACT SDF - Sunny Days + LiberationSans SDF Atlas] + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1945473988 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1945473987} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1027572110} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1945473989 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1945473987} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 058cba836c1846c3aa1c5fd2e28aea77, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_spriteAsset: {fileID: 0} + m_material: {fileID: 0} + m_sharedMaterial: {fileID: 0} + m_isDefaultMaterial: 0 + m_padding: 0 + m_canvasRenderer: {fileID: 1945473990} + m_TextComponent: {fileID: 1027572111} + m_materialReferenceIndex: 1 +--- !u!222 &1945473990 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1945473987} + m_CullTransparentMesh: 0 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/25 - Sunny Days Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/25 - Sunny Days Example.unity.meta new file mode 100644 index 0000000..9e7516e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/25 - Sunny Days Example.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f9b4c22e15cff344ba9fc6542a58dd07 +timeCreated: 1472854817 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/26 - Dropdown Placeholder Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/26 - Dropdown Placeholder Example.unity new file mode 100644 index 0000000..1028483 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/26 - Dropdown Placeholder Example.unity @@ -0,0 +1,3418 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 2 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &101488131 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 101488132} + - component: {fileID: 101488134} + - component: {fileID: 101488133} + m_Layer: 5 + m_Name: Placeholder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &101488132 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 101488131} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1319632886} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -45, y: -0.5} + m_SizeDelta: {x: -110, y: -13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &101488133 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 101488131} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Please make a selection + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4285427310 + m_fontColor: {r: 0.4339623, g: 0.4339623, b: 0.4339623, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 50 + m_fontSizeBase: 50 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 513 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 101488133} + characterCount: 23 + spriteCount: 0 + spaceCount: 3 + wordCount: 4 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &101488134 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 101488131} + m_CullTransparentMesh: 0 +--- !u!1 &139435177 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 139435180} + - component: {fileID: 139435179} + - component: {fileID: 139435178} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &139435178 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 139435177} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 60 + m_fontSizeBase: 60 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 139435178} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &139435179 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 139435177} + m_CullTransparentMesh: 0 +--- !u!224 &139435180 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 139435177} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2013243556} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -460} + m_SizeDelta: {x: -70, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &145152783 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 145152784} + - component: {fileID: 145152787} + - component: {fileID: 145152786} + - component: {fileID: 145152785} + m_Layer: 5 + m_Name: Template + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &145152784 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 145152783} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 787873729} + - {fileID: 1847835227} + m_Father: {fileID: 1918656514} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 2} + m_SizeDelta: {x: 0, y: 150} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &145152785 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 145152783} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 1046762071} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 2 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 787873729} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 1847835228} + m_HorizontalScrollbarVisibility: 0 + m_VerticalScrollbarVisibility: 2 + m_HorizontalScrollbarSpacing: 0 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &145152786 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 145152783} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &145152787 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 145152783} + m_CullTransparentMesh: 0 +--- !u!1 &176217954 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 176217955} + - component: {fileID: 176217957} + - component: {fileID: 176217956} + m_Layer: 5 + m_Name: Item Checkmark + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &176217955 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 176217954} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1661359791} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 25, y: 0} + m_SizeDelta: {x: 50, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &176217956 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 176217954} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &176217957 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 176217954} + m_CullTransparentMesh: 0 +--- !u!1 &201383588 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 201383591} + - component: {fileID: 201383590} + - component: {fileID: 201383589} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &201383589 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 201383588} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Option A + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 50 + m_fontSizeBase: 50 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 0 + m_fontSizeMax: 0 + m_fontStyle: 0 + m_textAlignment: 513 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 0 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 201383589} + characterCount: 8 + spriteCount: 0 + spaceCount: 1 + wordCount: 2 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &201383590 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 201383588} + m_CullTransparentMesh: 0 +--- !u!224 &201383591 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 201383588} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1918656514} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -45, y: -0.5} + m_SizeDelta: {x: -110, y: -13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &380548278 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 380548279} + - component: {fileID: 380548281} + - component: {fileID: 380548280} + m_Layer: 5 + m_Name: Item Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &380548279 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 380548278} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1082780498} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &380548280 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 380548278} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &380548281 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 380548278} + m_CullTransparentMesh: 0 +--- !u!1 &478722736 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 478722737} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &478722737 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 478722736} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1986362754} + m_Father: {fileID: 1847835227} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &519374738 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 519374739} + - component: {fileID: 519374742} + - component: {fileID: 519374741} + - component: {fileID: 519374740} + m_Layer: 5 + m_Name: Scrollbar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &519374739 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519374738} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1769210906} + m_Father: {fileID: 1816501795} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 0} + m_Pivot: {x: 1, y: 1} +--- !u!114 &519374740 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519374738} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -2061169968, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 2028609999} + m_HandleRect: {fileID: 2028609998} + m_Direction: 2 + m_Value: 0 + m_Size: 0.81333333 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Scrollbar+ScrollEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &519374741 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519374738} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &519374742 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519374738} + m_CullTransparentMesh: 0 +--- !u!1 &519420028 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 519420032} + - component: {fileID: 519420031} + - component: {fileID: 519420029} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &519420029 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519420028} + m_Enabled: 1 +--- !u!20 &519420031 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519420028} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 0 + m_HDR: 1 + m_AllowMSAA: 0 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 0 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &519420032 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 519420028} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &701619567 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 701619568} + - component: {fileID: 701619570} + - component: {fileID: 701619569} + m_Layer: 5 + m_Name: Arrow + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &701619568 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 701619567} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1319632886} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: -50, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &701619569 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 701619567} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10915, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &701619570 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 701619567} + m_CullTransparentMesh: 0 +--- !u!1 &787873728 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 787873729} + - component: {fileID: 787873732} + - component: {fileID: 787873731} + - component: {fileID: 787873730} + m_Layer: 5 + m_Name: Viewport + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &787873729 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787873728} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1046762071} + m_Father: {fileID: 145152784} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -17, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &787873730 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787873728} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10917, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &787873731 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787873728} + m_CullTransparentMesh: 0 +--- !u!114 &787873732 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787873728} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1200242548, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 0 +--- !u!1 &790700615 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 790700616} + - component: {fileID: 790700618} + - component: {fileID: 790700617} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &790700616 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 790700615} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1319632886} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -45, y: -0.5} + m_SizeDelta: {x: -110, y: -13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &790700617 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 790700615} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 50 + m_fontSizeBase: 50 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 0 + m_fontSizeMax: 0 + m_fontStyle: 0 + m_textAlignment: 513 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 0 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 790700617} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &790700618 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 790700615} + m_CullTransparentMesh: 0 +--- !u!1 &796521516 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 796521517} + - component: {fileID: 796521519} + - component: {fileID: 796521518} + m_Layer: 5 + m_Name: Item Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &796521517 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796521516} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1661359791} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &796521518 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796521516} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &796521519 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 796521516} + m_CullTransparentMesh: 0 +--- !u!1 &1046762070 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1046762071} + m_Layer: 5 + m_Name: Content + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1046762071 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1046762070} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1082780498} + m_Father: {fileID: 787873729} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 50} + m_Pivot: {x: 0.5, y: 1} +--- !u!1 &1082780497 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1082780498} + - component: {fileID: 1082780499} + m_Layer: 5 + m_Name: Item + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1082780498 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1082780497} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 380548279} + - {fileID: 1530403189} + - {fileID: 1426913341} + m_Father: {fileID: 1046762071} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1082780499 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1082780497} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 2109663825, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 380548280} + toggleTransition: 1 + graphic: {fileID: 1530403190} + m_Group: {fileID: 0} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null + m_IsOn: 1 +--- !u!1 &1224163520 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1224163523} + - component: {fileID: 1224163522} + - component: {fileID: 1224163521} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1224163521 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1224163520} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1224163522 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1224163520} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1224163523 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1224163520} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1314055271 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1314055272} + - component: {fileID: 1314055274} + - component: {fileID: 1314055273} + m_Layer: 5 + m_Name: Item Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1314055272 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1314055271} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1661359791} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 25, y: 0} + m_SizeDelta: {x: -50, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1314055273 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1314055271} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Option A + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 513 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1314055273} + characterCount: 8 + spriteCount: 0 + spaceCount: 1 + wordCount: 2 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1314055274 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1314055271} + m_CullTransparentMesh: 0 +--- !u!1 &1319489945 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1319489946} + - component: {fileID: 1319489949} + - component: {fileID: 1319489948} + - component: {fileID: 1319489947} + m_Layer: 5 + m_Name: Viewport + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1319489946 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319489945} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2133414391} + m_Father: {fileID: 1816501795} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -17, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &1319489947 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319489945} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10917, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1319489948 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319489945} + m_CullTransparentMesh: 0 +--- !u!114 &1319489949 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319489945} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1200242548, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 0 +--- !u!1 &1319632885 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1319632886} + - component: {fileID: 1319632889} + - component: {fileID: 1319632888} + - component: {fileID: 1319632887} + m_Layer: 5 + m_Name: DropdownWithPlaceholder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1319632886 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319632885} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 790700616} + - {fileID: 101488132} + - {fileID: 701619568} + - {fileID: 1816501795} + m_Father: {fileID: 2013243556} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 80} + m_SizeDelta: {x: -70, y: 120} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1319632887 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319632885} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7b743370ac3e4ec2a1668f5455a8ef8a, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1319632888} + m_Template: {fileID: 1816501795} + m_CaptionText: {fileID: 790700617} + m_CaptionImage: {fileID: 0} + m_Placeholder: {fileID: 101488133} + m_ItemText: {fileID: 1314055273} + m_ItemImage: {fileID: 0} + m_Value: -1 + m_Options: + m_Options: + - m_Text: Option A + m_Image: {fileID: 0} + - m_Text: Option B + m_Image: {fileID: 0} + - m_Text: Option C + m_Image: {fileID: 0} + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: TMPro.TMP_Dropdown+DropdownEvent, Unity.TextMeshPro, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1319632888 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319632885} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1319632889 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1319632885} + m_CullTransparentMesh: 0 +--- !u!1 &1426913338 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1426913341} + - component: {fileID: 1426913340} + - component: {fileID: 1426913339} + m_Layer: 5 + m_Name: Item Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1426913339 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1426913338} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Option A + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 513 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1426913339} + characterCount: 8 + spriteCount: 0 + spaceCount: 1 + wordCount: 2 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1426913340 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1426913338} + m_CullTransparentMesh: 0 +--- !u!224 &1426913341 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1426913338} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1082780498} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 25, y: 0} + m_SizeDelta: {x: -50, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1430059152 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1430059153} + - component: {fileID: 1430059155} + - component: {fileID: 1430059154} + m_Layer: 5 + m_Name: Arrow + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1430059153 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1430059152} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1918656514} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: -50, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1430059154 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1430059152} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10915, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1430059155 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1430059152} + m_CullTransparentMesh: 0 +--- !u!1 &1473329902 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1473329903} + - component: {fileID: 1473329906} + - component: {fileID: 1473329905} + - component: {fileID: 1473329904} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1473329903 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1473329902} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1878170544} + m_Father: {fileID: 2013243556} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 80} + m_SizeDelta: {x: -70, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1473329904 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1473329902} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1473329905} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 2013243557} + m_MethodName: OnButtonClick + 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 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1473329905 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1473329902} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1473329906 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1473329902} + m_CullTransparentMesh: 0 +--- !u!1 &1530403188 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1530403189} + - component: {fileID: 1530403191} + - component: {fileID: 1530403190} + m_Layer: 5 + m_Name: Item Checkmark + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1530403189 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1530403188} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1082780498} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 25, y: 0} + m_SizeDelta: {x: 50, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1530403190 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1530403188} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1530403191 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1530403188} + m_CullTransparentMesh: 0 +--- !u!1 &1661359790 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1661359791} + - component: {fileID: 1661359792} + m_Layer: 5 + m_Name: Item + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1661359791 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1661359790} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 796521517} + - {fileID: 176217955} + - {fileID: 1314055272} + m_Father: {fileID: 2133414391} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1661359792 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1661359790} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 2109663825, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 796521518} + toggleTransition: 1 + graphic: {fileID: 176217956} + m_Group: {fileID: 0} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null + m_IsOn: 1 +--- !u!1 &1769210905 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1769210906} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1769210906 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1769210905} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2028609998} + m_Father: {fileID: 519374739} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1816501794 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1816501795} + - component: {fileID: 1816501798} + - component: {fileID: 1816501797} + - component: {fileID: 1816501796} + m_Layer: 5 + m_Name: Template + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1816501795 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1816501794} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1319489946} + - {fileID: 519374739} + m_Father: {fileID: 1319632886} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 2} + m_SizeDelta: {x: 0, y: 150} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &1816501796 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1816501794} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 2133414391} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 2 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 1319489946} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 519374740} + m_HorizontalScrollbarVisibility: 0 + m_VerticalScrollbarVisibility: 2 + m_HorizontalScrollbarSpacing: 0 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1816501797 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1816501794} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1816501798 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1816501794} + m_CullTransparentMesh: 0 +--- !u!1 &1847835226 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1847835227} + - component: {fileID: 1847835230} + - component: {fileID: 1847835229} + - component: {fileID: 1847835228} + m_Layer: 5 + m_Name: Scrollbar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1847835227 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1847835226} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 478722737} + m_Father: {fileID: 145152784} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 0} + m_Pivot: {x: 1, y: 1} +--- !u!114 &1847835228 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1847835226} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -2061169968, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1986362755} + m_HandleRect: {fileID: 1986362754} + m_Direction: 2 + m_Value: 0 + m_Size: 0.81333333 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Scrollbar+ScrollEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1847835229 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1847835226} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1847835230 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1847835226} + m_CullTransparentMesh: 0 +--- !u!1 &1878170543 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1878170544} + - component: {fileID: 1878170546} + - component: {fileID: 1878170545} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1878170544 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1878170543} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1473329903} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1878170545 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1878170543} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Done + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 50 + m_fontSizeBase: 50 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + 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_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1878170545} + characterCount: 4 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1878170546 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1878170543} + m_CullTransparentMesh: 0 +--- !u!1 &1918656512 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1918656514} + - component: {fileID: 1918656516} + - component: {fileID: 1918656515} + - component: {fileID: 1918656513} + m_Layer: 5 + m_Name: DropdownWithoutPlaceholder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1918656513 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1918656512} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7b743370ac3e4ec2a1668f5455a8ef8a, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1918656515} + m_Template: {fileID: 145152784} + m_CaptionText: {fileID: 201383589} + m_CaptionImage: {fileID: 0} + m_Placeholder: {fileID: 0} + m_ItemText: {fileID: 1426913339} + m_ItemImage: {fileID: 0} + m_Value: 0 + m_Options: + m_Options: + - m_Text: Option A + m_Image: {fileID: 0} + - m_Text: Option B + m_Image: {fileID: 0} + - m_Text: Option C + m_Image: {fileID: 0} + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: TMPro.TMP_Dropdown+DropdownEvent, Unity.TextMeshPro, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!224 &1918656514 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1918656512} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 201383591} + - {fileID: 1430059153} + - {fileID: 145152784} + m_Father: {fileID: 2013243556} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 240} + m_SizeDelta: {x: -70, y: 120} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1918656515 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1918656512} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1918656516 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1918656512} + m_CullTransparentMesh: 0 +--- !u!1 &1986362753 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1986362754} + - component: {fileID: 1986362756} + - component: {fileID: 1986362755} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1986362754 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1986362753} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 478722737} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0.81333333} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1986362755 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1986362753} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &1986362756 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1986362753} + m_CullTransparentMesh: 0 +--- !u!1 &2013243552 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2013243556} + - component: {fileID: 2013243555} + - component: {fileID: 2013243553} + - component: {fileID: 2013243557} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2013243553 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2013243552} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &2013243555 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2013243552} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &2013243556 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2013243552} + 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_Children: + - {fileID: 1918656514} + - {fileID: 1319632886} + - {fileID: 139435180} + - {fileID: 1473329903} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &2013243557 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2013243552} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ac1eb05af6d391b4eb0f4c070a99f1d0, type: 3} + m_Name: + m_EditorClassIdentifier: + text: {fileID: 139435178} + dropdownWithoutPlaceholder: {fileID: 1918656513} + dropdownWithPlaceholder: {fileID: 1319632887} +--- !u!1 &2028609997 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2028609998} + - component: {fileID: 2028610000} + - component: {fileID: 2028609999} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2028609998 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2028609997} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1769210906} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0.81333333} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2028609999 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2028609997} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!222 &2028610000 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2028609997} + m_CullTransparentMesh: 0 +--- !u!1 &2133414390 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2133414391} + m_Layer: 5 + m_Name: Content + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2133414391 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2133414390} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1661359791} + m_Father: {fileID: 1319489946} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 50} + m_Pivot: {x: 0.5, y: 1} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/26 - Dropdown Placeholder Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/26 - Dropdown Placeholder Example.unity.meta new file mode 100644 index 0000000..04121ac --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/26 - Dropdown Placeholder Example.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0851605490a599b46b6ac5cb681d93ea +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/27 - Double Pass Shader Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/27 - Double Pass Shader Example.unity new file mode 100644 index 0000000..a428f23 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/27 - Double Pass Shader Example.unity @@ -0,0 +1,550 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1840652445 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1840652448} + - component: {fileID: 1840652447} + - component: {fileID: 1840652446} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1840652446 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1840652445} + m_Enabled: 1 +--- !u!20 &1840652447 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1840652445} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1840652448 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1840652445} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1889734829 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1889734832} + - component: {fileID: 1889734831} + - component: {fileID: 1889734830} + m_Layer: 0 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1889734830 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1889734829} + 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: Single Pass + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: f2dcf029949142e28b974630369c8b4e, 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: 36 + m_fontSizeBase: 36 + 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: -7 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 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_EmojiFallbackSupport: 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 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1889734831} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1889734831 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1889734829} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: f2dcf029949142e28b974630369c8b4e, 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!224 &1889734832 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1889734829} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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: 2.5} + m_SizeDelta: {x: 20, y: 5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1955989943 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1955989946} + - component: {fileID: 1955989945} + - component: {fileID: 1955989944} + m_Layer: 0 + m_Name: Text (TMP) (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1955989944 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1955989943} + 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: Double Pass + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 125cb55b44b24c4393181402bc6200e6, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 947a44964e53bf0448ff698b2a2219c0, 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: 36 + m_fontSizeBase: 36 + 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: -7 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 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_EmojiFallbackSupport: 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 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1955989945} + m_maskType: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 +--- !u!23 &1955989945 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1955989943} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 947a44964e53bf0448ff698b2a2219c0, 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!224 &1955989946 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1955989943} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 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} + m_AnchoredPosition: {x: 0, y: -2.5} + m_SizeDelta: {x: 20, y: 5} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/27 - Double Pass Shader Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/27 - Double Pass Shader Example.unity.meta new file mode 100644 index 0000000..3b57115 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/27 - Double Pass Shader Example.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3b38a6ba32b869f48812e595baf39746 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.meta new file mode 100644 index 0000000..ab511cf --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a7eaeb4188c60454faf0a41c253b505c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.unity new file mode 100644 index 0000000..58438e4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.unity @@ -0,0 +1,2262 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &140582583 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 140582587} + - component: {fileID: 140582586} + - component: {fileID: 140582585} + - component: {fileID: 140582584} + m_Layer: 0 + m_Name: Ground Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!64 &140582584 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 140582583} + 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: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &140582585 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 140582583} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 73c176f402d2c2f4d929aa5da7585d17, 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!33 &140582586 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 140582583} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &140582587 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 140582583} + 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: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &267765522 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 267765526} + - component: {fileID: 267765525} + - component: {fileID: 267765524} + - component: {fileID: 267765523} + - component: {fileID: 267765527} + m_Layer: 0 + m_Name: Unity Flat Logo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &267765523 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 267765522} + 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: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &267765524 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 267765522} + m_Enabled: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 73c176f402d2c2f4d929aa5da7585d17, 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!33 &267765525 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 267765522} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &267765526 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 267765522} + serializedVersion: 2 + m_LocalRotation: {x: 0.2588191, y: 0, z: 0, w: 0.9659258} + m_LocalPosition: {x: 0, y: 0.202, z: 1.7} + m_LocalScale: {x: 2.75, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 842134343} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 30, y: 0, z: 0} +--- !u!114 &267765527 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 267765522} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 2 + TranslationDistance: {x: 3.5, y: 0, z: 0} + TranslationSpeed: 0.5 + SpinSpeed: 0 + RotationRange: 0 +--- !u!1 &437800966 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 437800969} + - component: {fileID: 437800968} + - component: {fileID: 437800967} + - component: {fileID: 437800970} + m_Layer: 0 + m_Name: Point Light - Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &437800967 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 437800966} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3} + m_Name: + m_EditorClassIdentifier: + m_PointlightHDType: 0 + m_SpotLightShape: 0 + m_AreaLightShape: 0 + m_EnableSpotReflector: 1 + m_LightUnit: 0 + m_LuxAtDistance: 1 + m_Intensity: 200 + m_InnerSpotPercent: 0 + m_SpotIESCutoffPercent: 100 + m_LightDimmer: 1 + m_VolumetricDimmer: 1 + m_FadeDistance: 10000 + m_VolumetricFadeDistance: 10000 + m_AffectDiffuse: 1 + m_AffectSpecular: 1 + m_NonLightmappedOnly: 0 + m_ShapeWidth: 0.5 + m_ShapeHeight: 0.5 + m_AspectRatio: 1 + m_ShapeRadius: 0.025 + m_SoftnessScale: 1 + m_UseCustomSpotLightShadowCone: 0 + m_CustomSpotLightShadowCone: 30 + m_MaxSmoothness: 0.99 + m_ApplyRangeAttenuation: 1 + m_DisplayAreaLightEmissiveMesh: 0 + m_AreaLightCookie: {fileID: 0} + m_IESPoint: {fileID: 0} + m_IESSpot: {fileID: 0} + m_IncludeForRayTracing: 1 + m_IncludeForPathTracing: 1 + m_AreaLightShadowCone: 120 + m_UseScreenSpaceShadows: 0 + m_InteractsWithSky: 1 + m_AngularDiameter: 0.5 + diameterMultiplerMode: 0 + diameterMultiplier: 1 + diameterOverride: 0.5 + celestialBodyShadingSource: 1 + sunLightOverride: {fileID: 0} + sunColor: {r: 1, g: 1, b: 1, a: 1} + sunIntensity: 130000 + moonPhase: 0.2 + moonPhaseRotation: 0 + earthshine: 1 + flareSize: 2 + flareTint: {r: 1, g: 1, b: 1, a: 1} + flareFalloff: 4 + flareMultiplier: 1 + surfaceTexture: {fileID: 0} + surfaceTint: {r: 1, g: 1, b: 1, a: 1} + m_Distance: 1.5e+11 + m_UseRayTracedShadows: 0 + m_NumRayTracingSamples: 4 + m_FilterTracedShadow: 1 + m_FilterSizeTraced: 16 + m_SunLightConeAngle: 0.5 + m_LightShadowRadius: 0.5 + m_SemiTransparentShadow: 0 + m_ColorShadow: 1 + m_DistanceBasedFiltering: 0 + m_EvsmExponent: 15 + m_EvsmLightLeakBias: 0 + m_EvsmVarianceBias: 0.00001 + m_EvsmBlurPasses: 0 + m_LightlayersMask: 1 + m_LinkShadowLayers: 1 + m_ShadowNearPlane: 0.1 + m_BlockerSampleCount: 24 + m_FilterSampleCount: 16 + m_MinFilterSize: 0.1 + m_DirLightPCSSBlockerSampleCount: 24 + m_DirLightPCSSFilterSampleCount: 16 + m_DirLightPCSSMaxPenumbraSize: 0.56 + m_DirLightPCSSMaxSamplingDistance: 0.5 + m_DirLightPCSSMinFilterSizeTexels: 1.5 + m_DirLightPCSSMinFilterMaxAngularDiameter: 10 + m_DirLightPCSSBlockerSearchAngularDiameter: 12 + m_DirLightPCSSBlockerSamplingClumpExponent: 2 + m_KernelSize: 5 + m_LightAngle: 1 + m_MaxDepthBias: 0.001 + m_ShadowResolution: + m_Override: 512 + m_UseOverride: 1 + m_Level: 0 + m_ShadowDimmer: 1 + m_VolumetricShadowDimmer: 1 + m_ShadowFadeDistance: 10000 + m_UseContactShadow: + m_Override: 0 + m_UseOverride: 1 + m_Level: 0 + m_RayTracedContactShadow: 0 + m_ShadowTint: {r: 0, g: 0, b: 0, a: 1} + m_PenumbraTint: 0 + m_NormalBias: 0.75 + m_SlopeBias: 0.5 + m_ShadowUpdateMode: 0 + m_AlwaysDrawDynamicShadows: 0 + m_UpdateShadowOnLightMovement: 0 + m_CachedShadowTranslationThreshold: 0.01 + m_CachedShadowAngularThreshold: 0.5 + m_BarnDoorAngle: 90 + m_BarnDoorLength: 0.05 + m_preserveCachedShadow: 0 + m_OnDemandShadowRenderOnPlacement: 1 + m_ShadowCascadeRatios: + - 0.05 + - 0.2 + - 0.3 + m_ShadowCascadeBorders: + - 0.2 + - 0.2 + - 0.2 + - 0.2 + m_ShadowAlgorithm: 0 + m_ShadowVariant: 0 + m_ShadowPrecision: 0 + useOldInspector: 0 + useVolumetric: 1 + featuresFoldout: 1 + m_AreaLightEmissiveMeshShadowCastingMode: 0 + m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0 + m_AreaLightEmissiveMeshLayer: -1 + m_Version: 13 + m_ObsoleteShadowResolutionTier: 1 + m_ObsoleteUseShadowQualitySettings: 0 + m_ObsoleteCustomShadowResolution: 512 + m_ObsoleteContactShadows: 0 +--- !u!108 &437800968 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 437800966} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 2 + m_Color: {r: 0, g: 0.5592723, b: 1, a: 1} + m_Intensity: 79.57747 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 1 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 2 + m_AreaSize: {x: 0.5, y: 0.5} + m_BounceIntensity: 1 + m_ColorTemperature: 4648 + m_UseColorTemperature: 1 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 0 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &437800969 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 437800966} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1.967, z: -3.229} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 574041790} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &437800970 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 437800966} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 2 + TranslationDistance: {x: 5, y: 0, z: 1} + TranslationSpeed: 0.75 + SpinSpeed: 1 + RotationRange: 5 +--- !u!1 &572775507 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 572775511} + - component: {fileID: 572775510} + - component: {fileID: 572775509} + - component: {fileID: 572775508} + m_Layer: 0 + m_Name: Point Light - Red + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &572775508 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 572775507} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 2 + TranslationDistance: {x: 5, y: 0, z: 1} + TranslationSpeed: 1.25 + SpinSpeed: 0.75 + RotationRange: 5 +--- !u!114 &572775509 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 572775507} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3} + m_Name: + m_EditorClassIdentifier: + m_PointlightHDType: 0 + m_SpotLightShape: 0 + m_AreaLightShape: 0 + m_EnableSpotReflector: 1 + m_LightUnit: 0 + m_LuxAtDistance: 1 + m_Intensity: 200 + m_InnerSpotPercent: 0 + m_SpotIESCutoffPercent: 100 + m_LightDimmer: 1 + m_VolumetricDimmer: 1 + m_FadeDistance: 10000 + m_VolumetricFadeDistance: 10000 + m_AffectDiffuse: 1 + m_AffectSpecular: 1 + m_NonLightmappedOnly: 0 + m_ShapeWidth: 0.5 + m_ShapeHeight: 0.5 + m_AspectRatio: 1 + m_ShapeRadius: 0.025 + m_SoftnessScale: 1 + m_UseCustomSpotLightShadowCone: 0 + m_CustomSpotLightShadowCone: 30 + m_MaxSmoothness: 0.99 + m_ApplyRangeAttenuation: 1 + m_DisplayAreaLightEmissiveMesh: 0 + m_AreaLightCookie: {fileID: 0} + m_IESPoint: {fileID: 0} + m_IESSpot: {fileID: 0} + m_IncludeForRayTracing: 1 + m_IncludeForPathTracing: 1 + m_AreaLightShadowCone: 120 + m_UseScreenSpaceShadows: 0 + m_InteractsWithSky: 1 + m_AngularDiameter: 0.5 + diameterMultiplerMode: 0 + diameterMultiplier: 1 + diameterOverride: 0.5 + celestialBodyShadingSource: 1 + sunLightOverride: {fileID: 0} + sunColor: {r: 1, g: 1, b: 1, a: 1} + sunIntensity: 130000 + moonPhase: 0.2 + moonPhaseRotation: 0 + earthshine: 1 + flareSize: 2 + flareTint: {r: 1, g: 1, b: 1, a: 1} + flareFalloff: 4 + flareMultiplier: 1 + surfaceTexture: {fileID: 0} + surfaceTint: {r: 1, g: 1, b: 1, a: 1} + m_Distance: 1.5e+11 + m_UseRayTracedShadows: 0 + m_NumRayTracingSamples: 4 + m_FilterTracedShadow: 1 + m_FilterSizeTraced: 16 + m_SunLightConeAngle: 0.5 + m_LightShadowRadius: 0.5 + m_SemiTransparentShadow: 0 + m_ColorShadow: 1 + m_DistanceBasedFiltering: 0 + m_EvsmExponent: 15 + m_EvsmLightLeakBias: 0 + m_EvsmVarianceBias: 0.00001 + m_EvsmBlurPasses: 0 + m_LightlayersMask: 1 + m_LinkShadowLayers: 1 + m_ShadowNearPlane: 0.1 + m_BlockerSampleCount: 24 + m_FilterSampleCount: 16 + m_MinFilterSize: 0.1 + m_DirLightPCSSBlockerSampleCount: 24 + m_DirLightPCSSFilterSampleCount: 16 + m_DirLightPCSSMaxPenumbraSize: 0.56 + m_DirLightPCSSMaxSamplingDistance: 0.5 + m_DirLightPCSSMinFilterSizeTexels: 1.5 + m_DirLightPCSSMinFilterMaxAngularDiameter: 10 + m_DirLightPCSSBlockerSearchAngularDiameter: 12 + m_DirLightPCSSBlockerSamplingClumpExponent: 2 + m_KernelSize: 5 + m_LightAngle: 1 + m_MaxDepthBias: 0.001 + m_ShadowResolution: + m_Override: 512 + m_UseOverride: 1 + m_Level: 0 + m_ShadowDimmer: 1 + m_VolumetricShadowDimmer: 1 + m_ShadowFadeDistance: 10000 + m_UseContactShadow: + m_Override: 0 + m_UseOverride: 1 + m_Level: 0 + m_RayTracedContactShadow: 0 + m_ShadowTint: {r: 0, g: 0, b: 0, a: 1} + m_PenumbraTint: 0 + m_NormalBias: 0.75 + m_SlopeBias: 0.5 + m_ShadowUpdateMode: 0 + m_AlwaysDrawDynamicShadows: 0 + m_UpdateShadowOnLightMovement: 0 + m_CachedShadowTranslationThreshold: 0.01 + m_CachedShadowAngularThreshold: 0.5 + m_BarnDoorAngle: 90 + m_BarnDoorLength: 0.05 + m_preserveCachedShadow: 0 + m_OnDemandShadowRenderOnPlacement: 1 + m_ShadowCascadeRatios: + - 0.05 + - 0.2 + - 0.3 + m_ShadowCascadeBorders: + - 0.2 + - 0.2 + - 0.2 + - 0.2 + m_ShadowAlgorithm: 0 + m_ShadowVariant: 0 + m_ShadowPrecision: 0 + useOldInspector: 0 + useVolumetric: 1 + featuresFoldout: 1 + m_AreaLightEmissiveMeshShadowCastingMode: 0 + m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0 + m_AreaLightEmissiveMeshLayer: -1 + m_Version: 13 + m_ObsoleteShadowResolutionTier: 1 + m_ObsoleteUseShadowQualitySettings: 0 + m_ObsoleteCustomShadowResolution: 512 + m_ObsoleteContactShadows: 0 +--- !u!108 &572775510 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 572775507} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 2 + m_Color: {r: 1, g: 0.4575472, b: 0.4575472, a: 1} + m_Intensity: 79.57747 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 1 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 2 + m_AreaSize: {x: 0.5, y: 0.5} + m_BounceIntensity: 1 + m_ColorTemperature: 4648 + m_UseColorTemperature: 1 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 0 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &572775511 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 572775507} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 2.5, y: 1.967, z: -3.229} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 574041790} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &574041789 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 574041790} + m_Layer: 0 + m_Name: Lights + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &574041790 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 574041789} + 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: 437800969} + - {fileID: 1179778785} + - {fileID: 572775511} + - {fileID: 1020283464} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &842134340 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 842134343} + - component: {fileID: 842134342} + - component: {fileID: 842134341} + m_Layer: 0 + m_Name: Text (TMP) - Lit Plain + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &842134341 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 842134340} + 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: \uE347 + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: c9adb1f542a93ae489bacfeae21e8394, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 967f61bb1e3e28645a39e0cb647cc79e, 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: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 32 + m_HorizontalAlignment: 2 + 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_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 1 + 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: 842134342} + m_maskType: 0 +--- !u!23 &842134342 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 842134340} + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 967f61bb1e3e28645a39e0cb647cc79e, 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: 1 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!224 &842134343 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 842134340} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.509} + m_LocalScale: {x: 0.090909086, y: 0.25, z: 0.25} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 267765526} + 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.001, y: -0.191} + m_SizeDelta: {x: 10, y: 5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1020283460 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1020283464} + - component: {fileID: 1020283463} + - component: {fileID: 1020283462} + - component: {fileID: 1020283461} + m_Layer: 0 + m_Name: Spot Light - Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1020283461 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1020283460} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 1 + TranslationDistance: {x: 5, y: 0, z: 0} + TranslationSpeed: 1 + SpinSpeed: 3 + RotationRange: 20 +--- !u!114 &1020283462 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1020283460} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3} + m_Name: + m_EditorClassIdentifier: + m_PointlightHDType: 0 + m_SpotLightShape: 0 + m_AreaLightShape: 0 + m_EnableSpotReflector: 0 + m_LightUnit: 0 + m_LuxAtDistance: 1 + m_Intensity: 800 + m_InnerSpotPercent: 30 + m_SpotIESCutoffPercent: 100 + m_LightDimmer: 1 + m_VolumetricDimmer: 1 + m_FadeDistance: 10000 + m_VolumetricFadeDistance: 10000 + m_AffectDiffuse: 1 + m_AffectSpecular: 1 + m_NonLightmappedOnly: 0 + m_ShapeWidth: 0.5 + m_ShapeHeight: 0.5 + m_AspectRatio: 1 + m_ShapeRadius: 0.05 + m_SoftnessScale: 1 + m_UseCustomSpotLightShadowCone: 0 + m_CustomSpotLightShadowCone: 6 + m_MaxSmoothness: 0.99 + m_ApplyRangeAttenuation: 1 + m_DisplayAreaLightEmissiveMesh: 0 + m_AreaLightCookie: {fileID: 0} + m_IESPoint: {fileID: 0} + m_IESSpot: {fileID: 0} + m_IncludeForRayTracing: 1 + m_IncludeForPathTracing: 1 + m_AreaLightShadowCone: 120 + m_UseScreenSpaceShadows: 0 + m_InteractsWithSky: 1 + m_AngularDiameter: 0.5 + diameterMultiplerMode: 0 + diameterMultiplier: 1 + diameterOverride: 0.5 + celestialBodyShadingSource: 1 + sunLightOverride: {fileID: 0} + sunColor: {r: 1, g: 1, b: 1, a: 1} + sunIntensity: 130000 + moonPhase: 0.2 + moonPhaseRotation: 0 + earthshine: 1 + flareSize: 2 + flareTint: {r: 1, g: 1, b: 1, a: 1} + flareFalloff: 4 + flareMultiplier: 1 + surfaceTexture: {fileID: 0} + surfaceTint: {r: 1, g: 1, b: 1, a: 1} + m_Distance: 1.5e+11 + m_UseRayTracedShadows: 0 + m_NumRayTracingSamples: 4 + m_FilterTracedShadow: 1 + m_FilterSizeTraced: 16 + m_SunLightConeAngle: 0.5 + m_LightShadowRadius: 0.5 + m_SemiTransparentShadow: 0 + m_ColorShadow: 1 + m_DistanceBasedFiltering: 0 + m_EvsmExponent: 15 + m_EvsmLightLeakBias: 0 + m_EvsmVarianceBias: 0.00001 + m_EvsmBlurPasses: 0 + m_LightlayersMask: 1 + m_LinkShadowLayers: 1 + m_ShadowNearPlane: 0.1 + m_BlockerSampleCount: 24 + m_FilterSampleCount: 16 + m_MinFilterSize: 0.1 + m_DirLightPCSSBlockerSampleCount: 24 + m_DirLightPCSSFilterSampleCount: 16 + m_DirLightPCSSMaxPenumbraSize: 0.56 + m_DirLightPCSSMaxSamplingDistance: 0.5 + m_DirLightPCSSMinFilterSizeTexels: 1.5 + m_DirLightPCSSMinFilterMaxAngularDiameter: 10 + m_DirLightPCSSBlockerSearchAngularDiameter: 12 + m_DirLightPCSSBlockerSamplingClumpExponent: 2 + m_KernelSize: 5 + m_LightAngle: 1 + m_MaxDepthBias: 0.001 + m_ShadowResolution: + m_Override: 512 + m_UseOverride: 0 + m_Level: 2 + m_ShadowDimmer: 1 + m_VolumetricShadowDimmer: 1 + m_ShadowFadeDistance: 10000 + m_UseContactShadow: + m_Override: 0 + m_UseOverride: 1 + m_Level: 0 + m_RayTracedContactShadow: 0 + m_ShadowTint: {r: 0, g: 0, b: 0, a: 1} + m_PenumbraTint: 0 + m_NormalBias: 0.75 + m_SlopeBias: 0.5 + m_ShadowUpdateMode: 0 + m_AlwaysDrawDynamicShadows: 0 + m_UpdateShadowOnLightMovement: 0 + m_CachedShadowTranslationThreshold: 0.01 + m_CachedShadowAngularThreshold: 0.5 + m_BarnDoorAngle: 90 + m_BarnDoorLength: 0.05 + m_preserveCachedShadow: 0 + m_OnDemandShadowRenderOnPlacement: 1 + m_ShadowCascadeRatios: + - 0.05 + - 0.2 + - 0.3 + m_ShadowCascadeBorders: + - 0.2 + - 0.2 + - 0.2 + - 0.2 + m_ShadowAlgorithm: 0 + m_ShadowVariant: 0 + m_ShadowPrecision: 0 + useOldInspector: 0 + useVolumetric: 1 + featuresFoldout: 1 + m_AreaLightEmissiveMeshShadowCastingMode: 0 + m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0 + m_AreaLightEmissiveMeshLayer: -1 + m_Version: 13 + m_ObsoleteShadowResolutionTier: 1 + m_ObsoleteUseShadowQualitySettings: 0 + m_ObsoleteCustomShadowResolution: 512 + m_ObsoleteContactShadows: 0 +--- !u!108 &1020283463 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1020283460} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 0 + m_Color: {r: 0, g: 0.96415067, b: 1, a: 1} + m_Intensity: 79.57747 + m_Range: 10 + m_SpotAngle: 60 + m_InnerSpotAngle: 6 + m_CookieSize: 10 + m_Shadows: + m_Type: 1 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 2 + m_AreaSize: {x: 0.5, y: 0.5} + m_BounceIntensity: 1 + m_ColorTemperature: 4700 + m_UseColorTemperature: 1 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0.05 + m_ShadowAngle: 0 + m_LightUnit: 0 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 0 +--- !u!4 &1020283464 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1020283460} + serializedVersion: 2 + m_LocalRotation: {x: 0.07528914, y: 0.9389838, z: -0.077044755, w: 0.3266576} + m_LocalPosition: {x: -3.681, y: 3, z: 3.614} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 574041790} + m_LocalEulerAnglesHint: {x: 11.179, y: 142.158, z: 5.326} +--- !u!1 &1179778781 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1179778785} + - component: {fileID: 1179778784} + - component: {fileID: 1179778783} + - component: {fileID: 1179778782} + m_Layer: 0 + m_Name: Point Light - Green + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1179778782 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1179778781} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f19c7f94c794c5097d8bd11e39c750d, type: 3} + m_Name: + m_EditorClassIdentifier: + Motion: 2 + TranslationDistance: {x: 5, y: 0, z: 1} + TranslationSpeed: 1 + SpinSpeed: 1.25 + RotationRange: 5 +--- !u!114 &1179778783 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1179778781} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3} + m_Name: + m_EditorClassIdentifier: + m_PointlightHDType: 0 + m_SpotLightShape: 0 + m_AreaLightShape: 0 + m_EnableSpotReflector: 1 + m_LightUnit: 0 + m_LuxAtDistance: 1 + m_Intensity: 200 + m_InnerSpotPercent: 0 + m_SpotIESCutoffPercent: 100 + m_LightDimmer: 1 + m_VolumetricDimmer: 1 + m_FadeDistance: 10000 + m_VolumetricFadeDistance: 10000 + m_AffectDiffuse: 1 + m_AffectSpecular: 1 + m_NonLightmappedOnly: 0 + m_ShapeWidth: 0.5 + m_ShapeHeight: 0.5 + m_AspectRatio: 1 + m_ShapeRadius: 0.025 + m_SoftnessScale: 1 + m_UseCustomSpotLightShadowCone: 0 + m_CustomSpotLightShadowCone: 30 + m_MaxSmoothness: 0.99 + m_ApplyRangeAttenuation: 1 + m_DisplayAreaLightEmissiveMesh: 0 + m_AreaLightCookie: {fileID: 0} + m_IESPoint: {fileID: 0} + m_IESSpot: {fileID: 0} + m_IncludeForRayTracing: 1 + m_IncludeForPathTracing: 1 + m_AreaLightShadowCone: 120 + m_UseScreenSpaceShadows: 0 + m_InteractsWithSky: 1 + m_AngularDiameter: 0.5 + diameterMultiplerMode: 0 + diameterMultiplier: 1 + diameterOverride: 0.5 + celestialBodyShadingSource: 1 + sunLightOverride: {fileID: 0} + sunColor: {r: 1, g: 1, b: 1, a: 1} + sunIntensity: 130000 + moonPhase: 0.2 + moonPhaseRotation: 0 + earthshine: 1 + flareSize: 2 + flareTint: {r: 1, g: 1, b: 1, a: 1} + flareFalloff: 4 + flareMultiplier: 1 + surfaceTexture: {fileID: 0} + surfaceTint: {r: 1, g: 1, b: 1, a: 1} + m_Distance: 1.5e+11 + m_UseRayTracedShadows: 0 + m_NumRayTracingSamples: 4 + m_FilterTracedShadow: 1 + m_FilterSizeTraced: 16 + m_SunLightConeAngle: 0.5 + m_LightShadowRadius: 0.5 + m_SemiTransparentShadow: 0 + m_ColorShadow: 1 + m_DistanceBasedFiltering: 0 + m_EvsmExponent: 15 + m_EvsmLightLeakBias: 0 + m_EvsmVarianceBias: 0.00001 + m_EvsmBlurPasses: 0 + m_LightlayersMask: 1 + m_LinkShadowLayers: 1 + m_ShadowNearPlane: 0.1 + m_BlockerSampleCount: 24 + m_FilterSampleCount: 16 + m_MinFilterSize: 0.1 + m_DirLightPCSSBlockerSampleCount: 24 + m_DirLightPCSSFilterSampleCount: 16 + m_DirLightPCSSMaxPenumbraSize: 0.56 + m_DirLightPCSSMaxSamplingDistance: 0.5 + m_DirLightPCSSMinFilterSizeTexels: 1.5 + m_DirLightPCSSMinFilterMaxAngularDiameter: 10 + m_DirLightPCSSBlockerSearchAngularDiameter: 12 + m_DirLightPCSSBlockerSamplingClumpExponent: 2 + m_KernelSize: 5 + m_LightAngle: 1 + m_MaxDepthBias: 0.001 + m_ShadowResolution: + m_Override: 512 + m_UseOverride: 1 + m_Level: 0 + m_ShadowDimmer: 1 + m_VolumetricShadowDimmer: 1 + m_ShadowFadeDistance: 10000 + m_UseContactShadow: + m_Override: 0 + m_UseOverride: 1 + m_Level: 0 + m_RayTracedContactShadow: 0 + m_ShadowTint: {r: 0, g: 0, b: 0, a: 1} + m_PenumbraTint: 0 + m_NormalBias: 0.75 + m_SlopeBias: 0.5 + m_ShadowUpdateMode: 0 + m_AlwaysDrawDynamicShadows: 0 + m_UpdateShadowOnLightMovement: 0 + m_CachedShadowTranslationThreshold: 0.01 + m_CachedShadowAngularThreshold: 0.5 + m_BarnDoorAngle: 90 + m_BarnDoorLength: 0.05 + m_preserveCachedShadow: 0 + m_OnDemandShadowRenderOnPlacement: 1 + m_ShadowCascadeRatios: + - 0.05 + - 0.2 + - 0.3 + m_ShadowCascadeBorders: + - 0.2 + - 0.2 + - 0.2 + - 0.2 + m_ShadowAlgorithm: 0 + m_ShadowVariant: 0 + m_ShadowPrecision: 0 + useOldInspector: 0 + useVolumetric: 1 + featuresFoldout: 1 + m_AreaLightEmissiveMeshShadowCastingMode: 0 + m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0 + m_AreaLightEmissiveMeshLayer: -1 + m_Version: 13 + m_ObsoleteShadowResolutionTier: 1 + m_ObsoleteUseShadowQualitySettings: 0 + m_ObsoleteCustomShadowResolution: 512 + m_ObsoleteContactShadows: 0 +--- !u!108 &1179778784 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1179778781} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 2 + m_Color: {r: 0.3254717, g: 1, b: 0.3254717, a: 1} + m_Intensity: 79.57747 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 1 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 2 + m_AreaSize: {x: 0.5, y: 0.5} + m_BounceIntensity: 1 + m_ColorTemperature: 4648 + m_UseColorTemperature: 1 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 0 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1179778785 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1179778781} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -2.5, y: 1.967, z: -3.229} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 574041790} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1381285413 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1381285416} + - component: {fileID: 1381285415} + - component: {fileID: 1381285414} + - component: {fileID: 1381285417} + m_Layer: 0 + m_Name: Text (TMP) - Lit Bloom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1381285414 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1381285413} + 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: \uE347 + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: c9adb1f542a93ae489bacfeae21e8394, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 8d176c01131de8f46ad61094e29d79b2, 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: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 32 + m_HorizontalAlignment: 2 + 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_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 1 + 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: 1381285415} + m_maskType: 0 +--- !u!23 &1381285415 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1381285413} + m_Enabled: 1 + m_CastShadows: 1 + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 8d176c01131de8f46ad61094e29d79b2, 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: 1 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!224 &1381285416 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1381285413} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -1.25} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 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, y: 1.726} + m_SizeDelta: {x: 20, y: 5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1381285417 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1381285413} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IsGlobal: 1 + priority: 0 + blendDistance: 0 + weight: 1 + sharedProfile: {fileID: 11400000, guid: e31164aa529c1144b9f1820dbd4d2aca, type: 2} +--- !u!1 &1509821796 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1509821798} + - component: {fileID: 1509821797} + m_Layer: 0 + m_Name: Sky and Fog Volume + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1509821797 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1509821796} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IsGlobal: 1 + priority: 0 + blendDistance: 0 + weight: 1 + sharedProfile: {fileID: 11400000, guid: 83ba2e375bed45f48bce43e5a5f7c88a, type: 2} +--- !u!4 &1509821798 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1509821796} + 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: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1611878831 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1611878834} + - component: {fileID: 1611878833} + - component: {fileID: 1611878832} + m_Layer: 0 + m_Name: Text (TMP) - Unlit + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1611878832 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1611878831} + 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: Unlit Shader + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 5302535af1044152a457ed104f1f4b91, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 2ddca8f46aa0838419d568affb0ca6b4, 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: 18 + m_fontSizeBase: 18 + 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: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 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: 1611878833} + m_maskType: 0 +--- !u!23 &1611878833 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1611878831} + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2ddca8f46aa0838419d568affb0ca6b4, 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!224 &1611878834 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1611878831} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -4.925} + m_LocalScale: {x: 0.25, y: 0.25, z: 0.25} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 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: 3.522, y: -0.139} + m_SizeDelta: {x: 20, y: 5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &2059096375 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2059096378} + - component: {fileID: 2059096377} + - component: {fileID: 2059096376} + - component: {fileID: 2059096379} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &2059096376 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2059096375} + m_Enabled: 1 +--- !u!20 &2059096377 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2059096375} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 0 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &2059096378 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2059096375} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -6.15} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2059096379 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2059096375} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 23c1ce4fb46143f46bc5cb5224c934f6, type: 3} + m_Name: + m_EditorClassIdentifier: + clearColorMode: 0 + backgroundColorHDR: {r: 0.025, g: 0.07, b: 0.19, a: 0} + clearDepth: 1 + volumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + volumeAnchorOverride: {fileID: 0} + antialiasing: 0 + SMAAQuality: 2 + dithering: 1 + stopNaNs: 0 + taaSharpenStrength: 0.5 + TAAQuality: 1 + taaSharpenMode: 0 + taaRingingReduction: 0 + taaHistorySharpening: 0.35 + taaAntiFlicker: 0.5 + taaMotionVectorRejection: 0 + taaAntiHistoryRinging: 0 + taaBaseBlendFactor: 0.875 + taaJitterScale: 1 + physicalParameters: + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + flipYMode: 0 + xrRendering: 1 + fullscreenPassthrough: 0 + allowDynamicResolution: 0 + customRenderingSettings: 0 + invertFaceCulling: 0 + probeLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + hasPersistentHistory: 0 + screenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + screenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + allowDeepLearningSuperSampling: 1 + deepLearningSuperSamplingUseCustomQualitySettings: 0 + deepLearningSuperSamplingQuality: 0 + deepLearningSuperSamplingUseCustomAttributes: 0 + deepLearningSuperSamplingUseOptimalSettings: 1 + deepLearningSuperSamplingSharpening: 0 + allowFidelityFX2SuperResolution: 1 + fidelityFX2SuperResolutionUseCustomQualitySettings: 0 + fidelityFX2SuperResolutionQuality: 0 + fidelityFX2SuperResolutionUseCustomAttributes: 0 + fidelityFX2SuperResolutionUseOptimalSettings: 1 + fidelityFX2SuperResolutionEnableSharpening: 0 + fidelityFX2SuperResolutionSharpening: 0 + fsrOverrideSharpness: 0 + fsrSharpness: 0.92 + exposureTarget: {fileID: 0} + materialMipBias: 0 + m_RenderingPathCustomFrameSettings: + bitDatas: + data1: 72198262773251917 + data2: 13763000464465395712 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 9 + materialQuality: 0 + renderingPathCustomFrameSettingsOverrideMask: + mask: + data1: 0 + data2: 0 + defaultFrameSettings: 0 + m_Version: 9 + m_ObsoleteRenderingPath: 0 + m_ObsoleteFrameSettings: + overrides: 0 + enableShadow: 0 + enableContactShadows: 0 + enableShadowMask: 0 + enableSSR: 0 + enableSSAO: 0 + enableSubsurfaceScattering: 0 + enableTransmission: 0 + enableAtmosphericScattering: 0 + enableVolumetrics: 0 + enableReprojectionForVolumetrics: 0 + enableLightLayers: 0 + enableExposureControl: 1 + diffuseGlobalDimmer: 0 + specularGlobalDimmer: 0 + shaderLitMode: 0 + enableDepthPrepassWithDeferredRendering: 0 + enableTransparentPrepass: 0 + enableMotionVectors: 0 + enableObjectMotionVectors: 0 + enableDecals: 0 + enableRoughRefraction: 0 + enableTransparentPostpass: 0 + enableDistortion: 0 + enablePostprocess: 0 + enableOpaqueObjects: 0 + enableTransparentObjects: 0 + enableRealtimePlanarReflection: 0 + enableMSAA: 0 + enableAsyncCompute: 0 + runLightListAsync: 0 + runSSRAsync: 0 + runSSAOAsync: 0 + runContactShadowsAsync: 0 + runVolumeVoxelizationAsync: 0 + lightLoopSettings: + overrides: 0 + enableDeferredTileAndCluster: 0 + enableComputeLightEvaluation: 0 + enableComputeLightVariants: 0 + enableComputeMaterialVariants: 0 + enableFptlForForwardOpaque: 0 + enableBigTilePrepass: 0 + isFptlEnabled: 0 +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 2059096378} + - {fileID: 1509821798} + - {fileID: 140582587} + - {fileID: 1381285416} + - {fileID: 1611878834} + - {fileID: 267765526} + - {fileID: 574041790} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.unity.meta new file mode 100644 index 0000000..5f2ce65 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: eea2b7206368b444e84fbec4ec32b64a +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example/Sky and Fog Volume Profile.asset b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example/Sky and Fog Volume Profile.asset new file mode 100644 index 0000000..e7d3a5f --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example/Sky and Fog Volume Profile.asset @@ -0,0 +1,60 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: Sky and Fog Volume Profile + m_EditorClassIdentifier: + components: + - {fileID: 6704987263078244684} +--- !u!114 &6704987263078244684 +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: 0d7593b3a9277ac4696b20006c21dde2, type: 3} + m_Name: VisualEnvironment + m_EditorClassIdentifier: + active: 1 + skyType: + m_OverrideState: 1 + m_Value: 4 + cloudType: + m_OverrideState: 1 + m_Value: 0 + skyAmbientMode: + m_OverrideState: 0 + m_Value: 1 + planetRadius: + m_OverrideState: 1 + m_Value: 6378.1 + renderingSpace: + m_OverrideState: 1 + m_Value: 1 + centerMode: + m_OverrideState: 1 + m_Value: 0 + planetCenter: + m_OverrideState: 0 + m_Value: {x: 0, y: -6378.1, z: 0} + windOrientation: + m_OverrideState: 0 + m_Value: 0 + windSpeed: + m_OverrideState: 0 + m_Value: 0 + fogType: + m_OverrideState: 0 + m_Value: 0 + m_Version: 1 diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example/Sky and Fog Volume Profile.asset.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example/Sky and Fog Volume Profile.asset.meta new file mode 100644 index 0000000..029bcce --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/28 - HDRP Shader Example/Sky and Fog Volume Profile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 83ba2e375bed45f48bce43e5a5f7c88a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/Benchmark (Floating Text).unity b/Assets/TextMesh Pro/Examples & Extras/Scenes/Benchmark (Floating Text).unity new file mode 100644 index 0000000..6cf6f77 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/Benchmark (Floating Text).unity @@ -0,0 +1,429 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 1 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &182159562 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 182159566} + - component: {fileID: 182159565} + - component: {fileID: 182159563} + m_Layer: 0 + m_Name: Ground + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &182159563 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 182159562} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: aadd5a709a48466c887296bb5b1b8110, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &182159565 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 182159562} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &182159566 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 182159562} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 20, y: 1, z: 20} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &280649733 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 280649738} + - component: {fileID: 280649737} + - component: {fileID: 280649734} + - component: {fileID: 280649740} + - component: {fileID: 280649739} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &280649734 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 +--- !u!20 &280649737 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 38.4 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &280649738 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -107.936806} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &280649739 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2d687537154440a3913a9a3c7977978c, type: 3} + m_Name: + m_EditorClassIdentifier: + CameraTarget: {fileID: 0} + FollowDistance: 200 + MaxFollowDistance: 500 + MinFollowDistance: 2 + ElevationAngle: 30 + MaxElevationAngle: 85 + MinElevationAngle: 0 + OrbitalAngle: 0 + CameraMode: 0 + MovementSmoothing: 1 + RotationSmoothing: 0 + MovementSmoothingValue: 25 + RotationSmoothingValue: 5 + MoveSensitivity: 2 +--- !u!114 &280649740 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 280649733} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 686ec78b56aa445795335fbadafcfaa4, type: 3} + m_Name: + m_EditorClassIdentifier: + UpdateInterval: 5 + AnchorPosition: 2 +--- !u!1 &1097136440 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1097136442} + - component: {fileID: 1097136441} + m_Layer: 0 + m_Name: Directional light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1097136441 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097136440} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1097136442 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097136440} + m_LocalRotation: {x: 0.2677142, y: 0.16857424, z: -0.04763104, w: 0.9474403} + m_LocalPosition: {x: -1.5021362, y: 36.79033, z: -19.266798} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2142710353 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2142710355} + - component: {fileID: 2142710354} + m_Layer: 0 + m_Name: Benchmark (Shader Perf) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2142710354 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2142710353} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e8538afcddc14efbb5d9e94b7ae50197, type: 3} + m_Name: + m_EditorClassIdentifier: + SpawnType: 0 + NumberOfNPC: 250 +--- !u!4 &2142710355 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2142710353} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scenes/Benchmark (Floating Text).unity.meta b/Assets/TextMesh Pro/Examples & Extras/Scenes/Benchmark (Floating Text).unity.meta new file mode 100644 index 0000000..b64591e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/Benchmark (Floating Text).unity.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 16177da2e3254cee91944756d5f8ddd3 +labels: +- Mesh +- Text +- Rendering +- TextMesh +- TextMeshPro +- Font +- Dynamic +- Pro +- Fonts +- Advanced +- GUI +- Scene +- Styles +- Style +- Layout +- Atlas +- Kerning +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts.meta new file mode 100644 index 0000000..225345e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3979ce59e55144c89a2b3b3f8dcf7fd3 +folderAsset: yes +timeCreated: 1436068007 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01.cs new file mode 100644 index 0000000..d674384 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01.cs @@ -0,0 +1,128 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class Benchmark01 : MonoBehaviour + { + + public int BenchmarkType = 0; + + public TMP_FontAsset TMProFont; + public Font TextMeshFont; + + private TextMeshPro m_textMeshPro; + private TextContainer m_textContainer; + private TextMesh m_textMesh; + + private const string label01 = "The <#0050FF>count is: {0}"; + private const string label02 = "The count is: "; + + //private string m_string; + //private int m_frame; + + private Material m_material01; + private Material m_material02; + + + + IEnumerator Start() + { + + + + if (BenchmarkType == 0) // TextMesh Pro Component + { + m_textMeshPro = gameObject.AddComponent(); + m_textMeshPro.autoSizeTextContainer = true; + + //m_textMeshPro.anchorDampening = true; + + if (TMProFont != null) + m_textMeshPro.font = TMProFont; + + //m_textMeshPro.font = Resources.Load("Fonts & Materials/Anton SDF", typeof(TextMeshProFont)) as TextMeshProFont; // Make sure the Anton SDF exists before calling this... + //m_textMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/Anton SDF", typeof(Material)) as Material; // Same as above make sure this material exists. + + m_textMeshPro.fontSize = 48; + m_textMeshPro.alignment = TextAlignmentOptions.Center; + //m_textMeshPro.anchor = AnchorPositions.Center; + m_textMeshPro.extraPadding = true; + //m_textMeshPro.outlineWidth = 0.25f; + //m_textMeshPro.fontSharedMaterial.SetFloat("_OutlineWidth", 0.2f); + //m_textMeshPro.fontSharedMaterial.EnableKeyword("UNDERLAY_ON"); + //m_textMeshPro.lineJustification = LineJustificationTypes.Center; + m_textMeshPro.textWrappingMode = TextWrappingModes.NoWrap; + //m_textMeshPro.lineLength = 60; + //m_textMeshPro.characterSpacing = 0.2f; + //m_textMeshPro.fontColor = new Color32(255, 255, 255, 255); + + m_material01 = m_textMeshPro.font.material; + m_material02 = Resources.Load("Fonts & Materials/LiberationSans SDF - Drop Shadow"); // Make sure the LiberationSans SDF exists before calling this... + + + } + else if (BenchmarkType == 1) // TextMesh + { + m_textMesh = gameObject.AddComponent(); + + if (TextMeshFont != null) + { + m_textMesh.font = TextMeshFont; + m_textMesh.GetComponent().sharedMaterial = m_textMesh.font.material; + } + else + { + m_textMesh.font = Resources.Load("Fonts/ARIAL", typeof(Font)) as Font; + m_textMesh.GetComponent().sharedMaterial = m_textMesh.font.material; + } + + m_textMesh.fontSize = 48; + m_textMesh.anchor = TextAnchor.MiddleCenter; + + //m_textMesh.color = new Color32(255, 255, 0, 255); + } + + + + for (int i = 0; i <= 1000000; i++) + { + if (BenchmarkType == 0) + { + m_textMeshPro.SetText(label01, i % 1000); + if (i % 1000 == 999) + m_textMeshPro.fontSharedMaterial = m_textMeshPro.fontSharedMaterial == m_material01 ? m_textMeshPro.fontSharedMaterial = m_material02 : m_textMeshPro.fontSharedMaterial = m_material01; + + + + } + else if (BenchmarkType == 1) + m_textMesh.text = label02 + (i % 1000).ToString(); + + yield return null; + } + + + yield return null; + } + + + /* + void Update() + { + if (BenchmarkType == 0) + { + m_textMeshPro.text = (m_frame % 1000).ToString(); + } + else if (BenchmarkType == 1) + { + m_textMesh.text = (m_frame % 1000).ToString(); + } + + m_frame += 1; + } + */ + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01.cs.meta new file mode 100644 index 0000000..9910676 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: f970ea55f9f84bf79b05dab180b8c125 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01_UGUI.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01_UGUI.cs new file mode 100644 index 0000000..38f4a27 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01_UGUI.cs @@ -0,0 +1,135 @@ +using UnityEngine; +using System.Collections; +using UnityEngine.UI; + + +namespace TMPro.Examples +{ + + public class Benchmark01_UGUI : MonoBehaviour + { + + public int BenchmarkType = 0; + + public Canvas canvas; + public TMP_FontAsset TMProFont; + public Font TextMeshFont; + + private TextMeshProUGUI m_textMeshPro; + //private TextContainer m_textContainer; + private Text m_textMesh; + + private const string label01 = "The <#0050FF>count is: "; + private const string label02 = "The count is: "; + + //private const string label01 = "TextMesh <#0050FF>Pro! The count is: {0}"; + //private const string label02 = "Text Mesh The count is: "; + + //private string m_string; + //private int m_frame; + + private Material m_material01; + private Material m_material02; + + + + IEnumerator Start() + { + + + + if (BenchmarkType == 0) // TextMesh Pro Component + { + m_textMeshPro = gameObject.AddComponent(); + //m_textContainer = GetComponent(); + + + //m_textMeshPro.anchorDampening = true; + + if (TMProFont != null) + m_textMeshPro.font = TMProFont; + + //m_textMeshPro.font = Resources.Load("Fonts & Materials/Anton SDF", typeof(TextMeshProFont)) as TextMeshProFont; // Make sure the Anton SDF exists before calling this... + //m_textMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/Anton SDF", typeof(Material)) as Material; // Same as above make sure this material exists. + + m_textMeshPro.fontSize = 48; + m_textMeshPro.alignment = TextAlignmentOptions.Center; + //m_textMeshPro.anchor = AnchorPositions.Center; + m_textMeshPro.extraPadding = true; + //m_textMeshPro.outlineWidth = 0.25f; + //m_textMeshPro.fontSharedMaterial.SetFloat("_OutlineWidth", 0.2f); + //m_textMeshPro.fontSharedMaterial.EnableKeyword("UNDERLAY_ON"); + //m_textMeshPro.lineJustification = LineJustificationTypes.Center; + //m_textMeshPro.enableWordWrapping = true; + //m_textMeshPro.lineLength = 60; + //m_textMeshPro.characterSpacing = 0.2f; + //m_textMeshPro.fontColor = new Color32(255, 255, 255, 255); + + m_material01 = m_textMeshPro.font.material; + m_material02 = Resources.Load("Fonts & Materials/LiberationSans SDF - BEVEL"); // Make sure the LiberationSans SDF exists before calling this... + + + } + else if (BenchmarkType == 1) // TextMesh + { + m_textMesh = gameObject.AddComponent(); + + if (TextMeshFont != null) + { + m_textMesh.font = TextMeshFont; + //m_textMesh.renderer.sharedMaterial = m_textMesh.font.material; + } + else + { + //m_textMesh.font = Resources.Load("Fonts/ARIAL", typeof(Font)) as Font; + //m_textMesh.renderer.sharedMaterial = m_textMesh.font.material; + } + + m_textMesh.fontSize = 48; + m_textMesh.alignment = TextAnchor.MiddleCenter; + + //m_textMesh.color = new Color32(255, 255, 0, 255); + } + + + + for (int i = 0; i <= 1000000; i++) + { + if (BenchmarkType == 0) + { + m_textMeshPro.text = label01 + (i % 1000); + if (i % 1000 == 999) + m_textMeshPro.fontSharedMaterial = m_textMeshPro.fontSharedMaterial == m_material01 ? m_textMeshPro.fontSharedMaterial = m_material02 : m_textMeshPro.fontSharedMaterial = m_material01; + + + + } + else if (BenchmarkType == 1) + m_textMesh.text = label02 + (i % 1000).ToString(); + + yield return null; + } + + + yield return null; + } + + + /* + void Update() + { + if (BenchmarkType == 0) + { + m_textMeshPro.text = (m_frame % 1000).ToString(); + } + else if (BenchmarkType == 1) + { + m_textMesh.text = (m_frame % 1000).ToString(); + } + + m_frame += 1; + } + */ + } + +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01_UGUI.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01_UGUI.cs.meta new file mode 100644 index 0000000..5a26304 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark01_UGUI.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8ef7be1c625941f7ba8ed7cc71718c0d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark02.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark02.cs new file mode 100644 index 0000000..232df7d --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark02.cs @@ -0,0 +1,97 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class Benchmark02 : MonoBehaviour + { + + public int SpawnType = 0; + public int NumberOfNPC = 12; + + public bool IsTextObjectScaleStatic; + private TextMeshProFloatingText floatingText_Script; + + + void Start() + { + + for (int i = 0; i < NumberOfNPC; i++) + { + + + if (SpawnType == 0) + { + // TextMesh Pro Implementation + GameObject go = new GameObject(); + go.transform.position = new Vector3(Random.Range(-95f, 95f), 0.25f, Random.Range(-95f, 95f)); + + TextMeshPro textMeshPro = go.AddComponent(); + + textMeshPro.autoSizeTextContainer = true; + textMeshPro.rectTransform.pivot = new Vector2(0.5f, 0); + + textMeshPro.alignment = TextAlignmentOptions.Bottom; + textMeshPro.fontSize = 96; + textMeshPro.fontFeatures.Clear(); + + textMeshPro.color = new Color32(255, 255, 0, 255); + textMeshPro.text = "!"; + textMeshPro.isTextObjectScaleStatic = IsTextObjectScaleStatic; + + // Spawn Floating Text + floatingText_Script = go.AddComponent(); + floatingText_Script.SpawnType = 0; + floatingText_Script.IsTextObjectScaleStatic = IsTextObjectScaleStatic; + } + else if (SpawnType == 1) + { + // TextMesh Implementation + GameObject go = new GameObject(); + go.transform.position = new Vector3(Random.Range(-95f, 95f), 0.25f, Random.Range(-95f, 95f)); + + TextMesh textMesh = go.AddComponent(); + textMesh.font = Resources.Load("Fonts/ARIAL"); + textMesh.GetComponent().sharedMaterial = textMesh.font.material; + + textMesh.anchor = TextAnchor.LowerCenter; + textMesh.fontSize = 96; + + textMesh.color = new Color32(255, 255, 0, 255); + textMesh.text = "!"; + + // Spawn Floating Text + floatingText_Script = go.AddComponent(); + floatingText_Script.SpawnType = 1; + } + else if (SpawnType == 2) + { + // Canvas WorldSpace Camera + GameObject go = new GameObject(); + Canvas canvas = go.AddComponent(); + canvas.worldCamera = Camera.main; + + go.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); + go.transform.position = new Vector3(Random.Range(-95f, 95f), 5f, Random.Range(-95f, 95f)); + + TextMeshProUGUI textObject = new GameObject().AddComponent(); + textObject.rectTransform.SetParent(go.transform, false); + + textObject.color = new Color32(255, 255, 0, 255); + textObject.alignment = TextAlignmentOptions.Bottom; + textObject.fontSize = 96; + textObject.text = "!"; + + // Spawn Floating Text + floatingText_Script = go.AddComponent(); + floatingText_Script.SpawnType = 0; + } + + + + } + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark02.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark02.cs.meta new file mode 100644 index 0000000..a5d5a10 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark02.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8538afcddc14efbb5d9e94b7ae50197 +MonoImporter: + serializedVersion: 2 + defaultReferences: + - TheFont: {instanceID: 0} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark03.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark03.cs new file mode 100644 index 0000000..7a3e1b9 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark03.cs @@ -0,0 +1,92 @@ +using UnityEngine; +using System.Collections; +using UnityEngine.TextCore.LowLevel; + + +namespace TMPro.Examples +{ + + public class Benchmark03 : MonoBehaviour + { + public enum BenchmarkType { TMP_SDF_MOBILE = 0, TMP_SDF__MOBILE_SSD = 1, TMP_SDF = 2, TMP_BITMAP_MOBILE = 3, TEXTMESH_BITMAP = 4 } + + public int NumberOfSamples = 100; + public BenchmarkType Benchmark; + + public Font SourceFont; + + + void Awake() + { + + } + + + void Start() + { + TMP_FontAsset fontAsset = null; + + // Create Dynamic Font Asset for the given font file. + switch (Benchmark) + { + case BenchmarkType.TMP_SDF_MOBILE: + fontAsset = TMP_FontAsset.CreateFontAsset(SourceFont, 90, 9, GlyphRenderMode.SDFAA, 256, 256, AtlasPopulationMode.Dynamic); + break; + case BenchmarkType.TMP_SDF__MOBILE_SSD: + fontAsset = TMP_FontAsset.CreateFontAsset(SourceFont, 90, 9, GlyphRenderMode.SDFAA, 256, 256, AtlasPopulationMode.Dynamic); + fontAsset.material.shader = Shader.Find("TextMeshPro/Mobile/Distance Field SSD"); + break; + case BenchmarkType.TMP_SDF: + fontAsset = TMP_FontAsset.CreateFontAsset(SourceFont, 90, 9, GlyphRenderMode.SDFAA, 256, 256, AtlasPopulationMode.Dynamic); + fontAsset.material.shader = Shader.Find("TextMeshPro/Distance Field"); + break; + case BenchmarkType.TMP_BITMAP_MOBILE: + fontAsset = TMP_FontAsset.CreateFontAsset(SourceFont, 90, 9, GlyphRenderMode.SMOOTH, 256, 256, AtlasPopulationMode.Dynamic); + break; + } + + for (int i = 0; i < NumberOfSamples; i++) + { + switch (Benchmark) + { + case BenchmarkType.TMP_SDF_MOBILE: + case BenchmarkType.TMP_SDF__MOBILE_SSD: + case BenchmarkType.TMP_SDF: + case BenchmarkType.TMP_BITMAP_MOBILE: + { + GameObject go = new GameObject(); + go.transform.position = new Vector3(0, 1.2f, 0); + + TextMeshPro textComponent = go.AddComponent(); + textComponent.font = fontAsset; + textComponent.fontSize = 128; + textComponent.text = "@"; + textComponent.alignment = TextAlignmentOptions.Center; + textComponent.color = new Color32(255, 255, 0, 255); + + if (Benchmark == BenchmarkType.TMP_BITMAP_MOBILE) + textComponent.fontSize = 132; + + } + break; + case BenchmarkType.TEXTMESH_BITMAP: + { + GameObject go = new GameObject(); + go.transform.position = new Vector3(0, 1.2f, 0); + + TextMesh textMesh = go.AddComponent(); + textMesh.GetComponent().sharedMaterial = SourceFont.material; + textMesh.font = SourceFont; + textMesh.anchor = TextAnchor.MiddleCenter; + textMesh.fontSize = 130; + + textMesh.color = new Color32(255, 255, 0, 255); + textMesh.text = "@"; + } + break; + } + } + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark03.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark03.cs.meta new file mode 100644 index 0000000..8883bcd --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark03.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a73109742c8d47ac822895a473300c29 +MonoImporter: + serializedVersion: 2 + defaultReferences: + - TheFont: {instanceID: 0} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark04.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark04.cs new file mode 100644 index 0000000..5ff28df --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark04.cs @@ -0,0 +1,85 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class Benchmark04 : MonoBehaviour + { + + public int SpawnType = 0; + + public int MinPointSize = 12; + public int MaxPointSize = 64; + public int Steps = 4; + + private Transform m_Transform; + //private TextMeshProFloatingText floatingText_Script; + //public Material material; + + + void Start() + { + m_Transform = transform; + + float lineHeight = 0; + float orthoSize = Camera.main.orthographicSize = Screen.height / 2; + float ratio = (float)Screen.width / Screen.height; + + for (int i = MinPointSize; i <= MaxPointSize; i += Steps) + { + if (SpawnType == 0) + { + // TextMesh Pro Implementation + GameObject go = new GameObject("Text - " + i + " Pts"); + + if (lineHeight > orthoSize * 2) return; + + go.transform.position = m_Transform.position + new Vector3(ratio * -orthoSize * 0.975f, orthoSize * 0.975f - lineHeight, 0); + + TextMeshPro textMeshPro = go.AddComponent(); + + //textMeshPro.fontSharedMaterial = material; + //textMeshPro.font = Resources.Load("Fonts & Materials/LiberationSans SDF", typeof(TextMeshProFont)) as TextMeshProFont; + //textMeshPro.anchor = AnchorPositions.Left; + textMeshPro.rectTransform.pivot = new Vector2(0, 0.5f); + + textMeshPro.textWrappingMode = TextWrappingModes.NoWrap; + textMeshPro.extraPadding = true; + textMeshPro.isOrthographic = true; + textMeshPro.fontSize = i; + + textMeshPro.text = i + " pts - Lorem ipsum dolor sit..."; + textMeshPro.color = new Color32(255, 255, 255, 255); + + lineHeight += i; + } + else + { + // TextMesh Implementation + // Causes crashes since atlas needed exceeds 4096 X 4096 + /* + GameObject go = new GameObject("Arial " + i); + + //if (lineHeight > orthoSize * 2 * 0.9f) return; + + go.transform.position = m_Transform.position + new Vector3(ratio * -orthoSize * 0.975f, orthoSize * 0.975f - lineHeight, 1); + + TextMesh textMesh = go.AddComponent(); + textMesh.font = Resources.Load("Fonts/ARIAL", typeof(Font)) as Font; + textMesh.renderer.sharedMaterial = textMesh.font.material; + textMesh.anchor = TextAnchor.MiddleLeft; + textMesh.fontSize = i * 10; + + textMesh.color = new Color32(255, 255, 255, 255); + textMesh.text = i + " pts - Lorem ipsum dolor sit..."; + + lineHeight += i; + */ + } + } + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark04.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark04.cs.meta new file mode 100644 index 0000000..cc271d7 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/Benchmark04.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc20866c0d5e413ab7559440e15333ae +MonoImporter: + serializedVersion: 2 + defaultReferences: + - TheFont: {instanceID: 0} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/CameraController.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/CameraController.cs new file mode 100644 index 0000000..dad1482 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/CameraController.cs @@ -0,0 +1,292 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class CameraController : MonoBehaviour + { + public enum CameraModes { Follow, Isometric, Free } + + private Transform cameraTransform; + private Transform dummyTarget; + + public Transform CameraTarget; + + public float FollowDistance = 30.0f; + public float MaxFollowDistance = 100.0f; + public float MinFollowDistance = 2.0f; + + public float ElevationAngle = 30.0f; + public float MaxElevationAngle = 85.0f; + public float MinElevationAngle = 0f; + + public float OrbitalAngle = 0f; + + public CameraModes CameraMode = CameraModes.Follow; + + public bool MovementSmoothing = true; + public bool RotationSmoothing = false; + private bool previousSmoothing; + + public float MovementSmoothingValue = 25f; + public float RotationSmoothingValue = 5.0f; + + public float MoveSensitivity = 2.0f; + + private Vector3 currentVelocity = Vector3.zero; + private Vector3 desiredPosition; + private float mouseX; + private float mouseY; + private Vector3 moveVector; + private float mouseWheel; + + // Controls for Touches on Mobile devices + //private float prev_ZoomDelta; + + + private const string event_SmoothingValue = "Slider - Smoothing Value"; + private const string event_FollowDistance = "Slider - Camera Zoom"; + + + void Awake() + { + if (QualitySettings.vSyncCount > 0) + Application.targetFrameRate = 60; + else + Application.targetFrameRate = -1; + + if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.Android) + Input.simulateMouseWithTouches = false; + + cameraTransform = transform; + previousSmoothing = MovementSmoothing; + } + + + // Use this for initialization + void Start() + { + if (CameraTarget == null) + { + // If we don't have a target (assigned by the player, create a dummy in the center of the scene). + dummyTarget = new GameObject("Camera Target").transform; + CameraTarget = dummyTarget; + } + } + + // Update is called once per frame + void LateUpdate() + { + GetPlayerInput(); + + + // Check if we still have a valid target + if (CameraTarget != null) + { + if (CameraMode == CameraModes.Isometric) + { + desiredPosition = CameraTarget.position + Quaternion.Euler(ElevationAngle, OrbitalAngle, 0f) * new Vector3(0, 0, -FollowDistance); + } + else if (CameraMode == CameraModes.Follow) + { + desiredPosition = CameraTarget.position + CameraTarget.TransformDirection(Quaternion.Euler(ElevationAngle, OrbitalAngle, 0f) * (new Vector3(0, 0, -FollowDistance))); + } + else + { + // Free Camera implementation + } + + if (MovementSmoothing == true) + { + // Using Smoothing + cameraTransform.position = Vector3.SmoothDamp(cameraTransform.position, desiredPosition, ref currentVelocity, MovementSmoothingValue * Time.fixedDeltaTime); + //cameraTransform.position = Vector3.Lerp(cameraTransform.position, desiredPosition, Time.deltaTime * 5.0f); + } + else + { + // Not using Smoothing + cameraTransform.position = desiredPosition; + } + + if (RotationSmoothing == true) + cameraTransform.rotation = Quaternion.Lerp(cameraTransform.rotation, Quaternion.LookRotation(CameraTarget.position - cameraTransform.position), RotationSmoothingValue * Time.deltaTime); + else + { + cameraTransform.LookAt(CameraTarget); + } + + } + + } + + + + void GetPlayerInput() + { + moveVector = Vector3.zero; + + // Check Mouse Wheel Input prior to Shift Key so we can apply multiplier on Shift for Scrolling + mouseWheel = Input.GetAxis("Mouse ScrollWheel"); + + float touchCount = Input.touchCount; + + if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift) || touchCount > 0) + { + mouseWheel *= 10; + + if (Input.GetKeyDown(KeyCode.I)) + CameraMode = CameraModes.Isometric; + + if (Input.GetKeyDown(KeyCode.F)) + CameraMode = CameraModes.Follow; + + if (Input.GetKeyDown(KeyCode.S)) + MovementSmoothing = !MovementSmoothing; + + + // Check for right mouse button to change camera follow and elevation angle + if (Input.GetMouseButton(1)) + { + mouseY = Input.GetAxis("Mouse Y"); + mouseX = Input.GetAxis("Mouse X"); + + if (mouseY > 0.01f || mouseY < -0.01f) + { + ElevationAngle -= mouseY * MoveSensitivity; + // Limit Elevation angle between min & max values. + ElevationAngle = Mathf.Clamp(ElevationAngle, MinElevationAngle, MaxElevationAngle); + } + + if (mouseX > 0.01f || mouseX < -0.01f) + { + OrbitalAngle += mouseX * MoveSensitivity; + if (OrbitalAngle > 360) + OrbitalAngle -= 360; + if (OrbitalAngle < 0) + OrbitalAngle += 360; + } + } + + // Get Input from Mobile Device + if (touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved) + { + Vector2 deltaPosition = Input.GetTouch(0).deltaPosition; + + // Handle elevation changes + if (deltaPosition.y > 0.01f || deltaPosition.y < -0.01f) + { + ElevationAngle -= deltaPosition.y * 0.1f; + // Limit Elevation angle between min & max values. + ElevationAngle = Mathf.Clamp(ElevationAngle, MinElevationAngle, MaxElevationAngle); + } + + + // Handle left & right + if (deltaPosition.x > 0.01f || deltaPosition.x < -0.01f) + { + OrbitalAngle += deltaPosition.x * 0.1f; + if (OrbitalAngle > 360) + OrbitalAngle -= 360; + if (OrbitalAngle < 0) + OrbitalAngle += 360; + } + + } + + // Check for left mouse button to select a new CameraTarget or to reset Follow position + if (Input.GetMouseButton(0)) + { + Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); + RaycastHit hit; + + if (Physics.Raycast(ray, out hit, 300, 1 << 10 | 1 << 11 | 1 << 12 | 1 << 14)) + { + if (hit.transform == CameraTarget) + { + // Reset Follow Position + OrbitalAngle = 0; + } + else + { + CameraTarget = hit.transform; + OrbitalAngle = 0; + MovementSmoothing = previousSmoothing; + } + + } + } + + + if (Input.GetMouseButton(2)) + { + if (dummyTarget == null) + { + // We need a Dummy Target to anchor the Camera + dummyTarget = new GameObject("Camera Target").transform; + dummyTarget.position = CameraTarget.position; + dummyTarget.rotation = CameraTarget.rotation; + CameraTarget = dummyTarget; + previousSmoothing = MovementSmoothing; + MovementSmoothing = false; + } + else if (dummyTarget != CameraTarget) + { + // Move DummyTarget to CameraTarget + dummyTarget.position = CameraTarget.position; + dummyTarget.rotation = CameraTarget.rotation; + CameraTarget = dummyTarget; + previousSmoothing = MovementSmoothing; + MovementSmoothing = false; + } + + + mouseY = Input.GetAxis("Mouse Y"); + mouseX = Input.GetAxis("Mouse X"); + + moveVector = cameraTransform.TransformDirection(mouseX, mouseY, 0); + + dummyTarget.Translate(-moveVector, Space.World); + + } + + } + + // Check Pinching to Zoom in - out on Mobile device + if (touchCount == 2) + { + Touch touch0 = Input.GetTouch(0); + Touch touch1 = Input.GetTouch(1); + + Vector2 touch0PrevPos = touch0.position - touch0.deltaPosition; + Vector2 touch1PrevPos = touch1.position - touch1.deltaPosition; + + float prevTouchDelta = (touch0PrevPos - touch1PrevPos).magnitude; + float touchDelta = (touch0.position - touch1.position).magnitude; + + float zoomDelta = prevTouchDelta - touchDelta; + + if (zoomDelta > 0.01f || zoomDelta < -0.01f) + { + FollowDistance += zoomDelta * 0.25f; + // Limit FollowDistance between min & max values. + FollowDistance = Mathf.Clamp(FollowDistance, MinFollowDistance, MaxFollowDistance); + } + + + } + + // Check MouseWheel to Zoom in-out + if (mouseWheel < -0.01f || mouseWheel > 0.01f) + { + + FollowDistance -= mouseWheel * 5.0f; + // Limit FollowDistance between min & max values. + FollowDistance = Mathf.Clamp(FollowDistance, MinFollowDistance, MaxFollowDistance); + } + + + } + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/CameraController.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/CameraController.cs.meta new file mode 100644 index 0000000..75fa178 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/CameraController.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 2d687537154440a3913a9a3c7977978c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/ChatController.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/ChatController.cs new file mode 100644 index 0000000..2915c96 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/ChatController.cs @@ -0,0 +1,51 @@ +using UnityEngine; +using UnityEngine.UI; +using TMPro; + +public class ChatController : MonoBehaviour { + + + public TMP_InputField ChatInputField; + + public TMP_Text ChatDisplayOutput; + + public Scrollbar ChatScrollbar; + + void OnEnable() + { + ChatInputField.onSubmit.AddListener(AddToChatOutput); + } + + void OnDisable() + { + ChatInputField.onSubmit.RemoveListener(AddToChatOutput); + } + + + void AddToChatOutput(string newText) + { + // Clear Input Field + ChatInputField.text = string.Empty; + + var timeNow = System.DateTime.Now; + + string formattedInput = "[<#FFFF80>" + timeNow.Hour.ToString("d2") + ":" + timeNow.Minute.ToString("d2") + ":" + timeNow.Second.ToString("d2") + "] " + newText; + + if (ChatDisplayOutput != null) + { + // No special formatting for first entry + // Add line feed before each subsequent entries + if (ChatDisplayOutput.text == string.Empty) + ChatDisplayOutput.text = formattedInput; + else + ChatDisplayOutput.text += "\n" + formattedInput; + } + + // Keep Chat input field active + ChatInputField.ActivateInputField(); + + // Set the scrollbar to the bottom when next text is submitted. + ChatScrollbar.value = 0; + } + +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/ChatController.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/ChatController.cs.meta new file mode 100644 index 0000000..fd1d420 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/ChatController.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 53d91f98a2664f5cb9af11de72ac54ec +timeCreated: 1487197841 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/DropdownSample.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/DropdownSample.cs new file mode 100644 index 0000000..f9ac60b --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/DropdownSample.cs @@ -0,0 +1,19 @@ +using TMPro; +using UnityEngine; + +public class DropdownSample: MonoBehaviour +{ + [SerializeField] + private TextMeshProUGUI text = null; + + [SerializeField] + private TMP_Dropdown dropdownWithoutPlaceholder = null; + + [SerializeField] + private TMP_Dropdown dropdownWithPlaceholder = null; + + public void OnButtonClick() + { + text.text = dropdownWithPlaceholder.value > -1 ? "Selected values:\n" + dropdownWithoutPlaceholder.value + " - " + dropdownWithPlaceholder.value : "Error: Please make a selection"; + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/DropdownSample.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/DropdownSample.cs.meta new file mode 100644 index 0000000..8046101 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/DropdownSample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ac1eb05af6d391b4eb0f4c070a99f1d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/EnvMapAnimator.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/EnvMapAnimator.cs new file mode 100644 index 0000000..4117707 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/EnvMapAnimator.cs @@ -0,0 +1,35 @@ +using UnityEngine; +using System.Collections; +using TMPro; + +public class EnvMapAnimator : MonoBehaviour { + + //private Vector3 TranslationSpeeds; + public Vector3 RotationSpeeds; + private TMP_Text m_textMeshPro; + private Material m_material; + + + void Awake() + { + //Debug.Log("Awake() on Script called."); + m_textMeshPro = GetComponent(); + m_material = m_textMeshPro.fontSharedMaterial; + } + + // Use this for initialization + IEnumerator Start () + { + Matrix4x4 matrix = new Matrix4x4(); + + while (true) + { + //matrix.SetTRS(new Vector3 (Time.time * TranslationSpeeds.x, Time.time * TranslationSpeeds.y, Time.time * TranslationSpeeds.z), Quaternion.Euler(Time.time * RotationSpeeds.x, Time.time * RotationSpeeds.y , Time.time * RotationSpeeds.z), Vector3.one); + matrix.SetTRS(Vector3.zero, Quaternion.Euler(Time.time * RotationSpeeds.x, Time.time * RotationSpeeds.y , Time.time * RotationSpeeds.z), Vector3.one); + + m_material.SetMatrix("_EnvMatrix", matrix); + + yield return null; + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/EnvMapAnimator.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/EnvMapAnimator.cs.meta new file mode 100644 index 0000000..f42808a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/EnvMapAnimator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a4b6f99e8bc54541bbd149b014ff441c +timeCreated: 1449025325 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/ObjectSpin.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/ObjectSpin.cs new file mode 100644 index 0000000..0ef528b --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/ObjectSpin.cs @@ -0,0 +1,67 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class ObjectSpin : MonoBehaviour + { + #pragma warning disable 0414 + public enum MotionType { Rotation, SearchLight, Translation }; + public MotionType Motion; + + public Vector3 TranslationDistance = new Vector3(5, 0, 0); + public float TranslationSpeed = 1.0f; + public float SpinSpeed = 5; + public int RotationRange = 15; + private Transform m_transform; + + private float m_time; + private Vector3 m_prevPOS; + private Vector3 m_initial_Rotation; + private Vector3 m_initial_Position; + private Color32 m_lightColor; + + void Awake() + { + m_transform = transform; + m_initial_Rotation = m_transform.rotation.eulerAngles; + m_initial_Position = m_transform.position; + + Light light = GetComponent(); + m_lightColor = light != null ? light.color : Color.black; + } + + + // Update is called once per frame + void Update() + { + switch (Motion) + { + case MotionType.Rotation: + m_transform.Rotate(0, SpinSpeed * Time.deltaTime, 0); + break; + case MotionType.SearchLight: + m_time += SpinSpeed * Time.deltaTime; + m_transform.rotation = Quaternion.Euler(m_initial_Rotation.x, Mathf.Sin(m_time) * RotationRange + m_initial_Rotation.y, m_initial_Rotation.z); + break; + case MotionType.Translation: + m_time += TranslationSpeed * Time.deltaTime; + + float x = TranslationDistance.x * Mathf.Cos(m_time); + float y = TranslationDistance.y * Mathf.Sin(m_time) * Mathf.Cos(m_time * 1f); + float z = TranslationDistance.z * Mathf.Sin(m_time); + + m_transform.position = m_initial_Position + new Vector3(x, z, y); + + // Drawing light patterns because they can be cool looking. + //if (Time.frameCount > 1) + // Debug.DrawLine(m_transform.position, m_prevPOS, m_lightColor, 100f); + + m_prevPOS = m_transform.position; + break; + } + } + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/ObjectSpin.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/ObjectSpin.cs.meta new file mode 100644 index 0000000..43c45a1 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/ObjectSpin.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 4f19c7f94c794c5097d8bd11e39c750d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/ShaderPropAnimator.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/ShaderPropAnimator.cs new file mode 100644 index 0000000..d8e56a4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/ShaderPropAnimator.cs @@ -0,0 +1,51 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class ShaderPropAnimator : MonoBehaviour + { + + private Renderer m_Renderer; + private Material m_Material; + + public AnimationCurve GlowCurve; + + public float m_frame; + + void Awake() + { + // Cache a reference to object's renderer + m_Renderer = GetComponent(); + + // Cache a reference to object's material and create an instance by doing so. + m_Material = m_Renderer.material; + } + + void Start() + { + StartCoroutine(AnimateProperties()); + } + + IEnumerator AnimateProperties() + { + //float lightAngle; + float glowPower; + m_frame = Random.Range(0f, 1f); + + while (true) + { + //lightAngle = (m_Material.GetFloat(ShaderPropertyIDs.ID_LightAngle) + Time.deltaTime) % 6.2831853f; + //m_Material.SetFloat(ShaderPropertyIDs.ID_LightAngle, lightAngle); + + glowPower = GlowCurve.Evaluate(m_frame); + m_Material.SetFloat(ShaderUtilities.ID_GlowPower, glowPower); + + m_frame += Time.deltaTime * Random.Range(0.2f, 0.3f); + yield return new WaitForEndOfFrame(); + } + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/ShaderPropAnimator.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/ShaderPropAnimator.cs.meta new file mode 100644 index 0000000..29547c6 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/ShaderPropAnimator.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 2787a46a4dc848c1b4b7b9307b614bfd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/SimpleScript.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/SimpleScript.cs new file mode 100644 index 0000000..8684b48 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/SimpleScript.cs @@ -0,0 +1,58 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class SimpleScript : MonoBehaviour + { + + private TextMeshPro m_textMeshPro; + //private TMP_FontAsset m_FontAsset; + + private const string label = "The <#0050FF>count is: {0:2}"; + private float m_frame; + + + void Start() + { + // Add new TextMesh Pro Component + m_textMeshPro = gameObject.AddComponent(); + + m_textMeshPro.autoSizeTextContainer = true; + + // Load the Font Asset to be used. + //m_FontAsset = Resources.Load("Fonts & Materials/LiberationSans SDF", typeof(TMP_FontAsset)) as TMP_FontAsset; + //m_textMeshPro.font = m_FontAsset; + + // Assign Material to TextMesh Pro Component + //m_textMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/LiberationSans SDF - Bevel", typeof(Material)) as Material; + //m_textMeshPro.fontSharedMaterial.EnableKeyword("BEVEL_ON"); + + // Set various font settings. + m_textMeshPro.fontSize = 48; + + m_textMeshPro.alignment = TextAlignmentOptions.Center; + + //m_textMeshPro.anchorDampening = true; // Has been deprecated but under consideration for re-implementation. + //m_textMeshPro.enableAutoSizing = true; + + //m_textMeshPro.characterSpacing = 0.2f; + //m_textMeshPro.wordSpacing = 0.1f; + + //m_textMeshPro.enableCulling = true; + m_textMeshPro.textWrappingMode = TextWrappingModes.NoWrap; + + //textMeshPro.fontColor = new Color32(255, 255, 255, 255); + } + + + void Update() + { + m_textMeshPro.SetText(label, m_frame % 1000); + m_frame += 1 * Time.deltaTime; + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/SimpleScript.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/SimpleScript.cs.meta new file mode 100644 index 0000000..7fbe336 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/SimpleScript.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 9eff140b25d64601aabc6ba32245d099 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/SkewTextExample.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/SkewTextExample.cs new file mode 100644 index 0000000..205b0fd --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/SkewTextExample.cs @@ -0,0 +1,158 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class SkewTextExample : MonoBehaviour + { + + private TMP_Text m_TextComponent; + + public AnimationCurve VertexCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.25f, 2.0f), new Keyframe(0.5f, 0), new Keyframe(0.75f, 2.0f), new Keyframe(1, 0f)); + //public float AngleMultiplier = 1.0f; + //public float SpeedMultiplier = 1.0f; + public float CurveScale = 1.0f; + public float ShearAmount = 1.0f; + + void Awake() + { + m_TextComponent = gameObject.GetComponent(); + } + + + void Start() + { + StartCoroutine(WarpText()); + } + + + private AnimationCurve CopyAnimationCurve(AnimationCurve curve) + { + AnimationCurve newCurve = new AnimationCurve(); + + newCurve.keys = curve.keys; + + return newCurve; + } + + + /// + /// Method to curve text along a Unity animation curve. + /// + /// + /// + IEnumerator WarpText() + { + VertexCurve.preWrapMode = WrapMode.Clamp; + VertexCurve.postWrapMode = WrapMode.Clamp; + + //Mesh mesh = m_TextComponent.textInfo.meshInfo[0].mesh; + + Vector3[] vertices; + Matrix4x4 matrix; + + m_TextComponent.havePropertiesChanged = true; // Need to force the TextMeshPro Object to be updated. + CurveScale *= 10; + float old_CurveScale = CurveScale; + float old_ShearValue = ShearAmount; + AnimationCurve old_curve = CopyAnimationCurve(VertexCurve); + + while (true) + { + if (!m_TextComponent.havePropertiesChanged && old_CurveScale == CurveScale && old_curve.keys[1].value == VertexCurve.keys[1].value && old_ShearValue == ShearAmount) + { + yield return null; + continue; + } + + old_CurveScale = CurveScale; + old_curve = CopyAnimationCurve(VertexCurve); + old_ShearValue = ShearAmount; + + m_TextComponent.ForceMeshUpdate(); // Generate the mesh and populate the textInfo with data we can use and manipulate. + + TMP_TextInfo textInfo = m_TextComponent.textInfo; + int characterCount = textInfo.characterCount; + + + if (characterCount == 0) continue; + + //vertices = textInfo.meshInfo[0].vertices; + //int lastVertexIndex = textInfo.characterInfo[characterCount - 1].vertexIndex; + + float boundsMinX = m_TextComponent.bounds.min.x; //textInfo.meshInfo[0].mesh.bounds.min.x; + float boundsMaxX = m_TextComponent.bounds.max.x; //textInfo.meshInfo[0].mesh.bounds.max.x; + + + + for (int i = 0; i < characterCount; i++) + { + if (!textInfo.characterInfo[i].isVisible) + continue; + + int vertexIndex = textInfo.characterInfo[i].vertexIndex; + + // Get the index of the mesh used by this character. + int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; + + vertices = textInfo.meshInfo[materialIndex].vertices; + + // Compute the baseline mid point for each character + Vector3 offsetToMidBaseline = new Vector2((vertices[vertexIndex + 0].x + vertices[vertexIndex + 2].x) / 2, textInfo.characterInfo[i].baseLine); + //float offsetY = VertexCurve.Evaluate((float)i / characterCount + loopCount / 50f); // Random.Range(-0.25f, 0.25f); + + // Apply offset to adjust our pivot point. + vertices[vertexIndex + 0] += -offsetToMidBaseline; + vertices[vertexIndex + 1] += -offsetToMidBaseline; + vertices[vertexIndex + 2] += -offsetToMidBaseline; + vertices[vertexIndex + 3] += -offsetToMidBaseline; + + // Apply the Shearing FX + float shear_value = ShearAmount * 0.01f; + Vector3 topShear = new Vector3(shear_value * (textInfo.characterInfo[i].topRight.y - textInfo.characterInfo[i].baseLine), 0, 0); + Vector3 bottomShear = new Vector3(shear_value * (textInfo.characterInfo[i].baseLine - textInfo.characterInfo[i].bottomRight.y), 0, 0); + + vertices[vertexIndex + 0] += -bottomShear; + vertices[vertexIndex + 1] += topShear; + vertices[vertexIndex + 2] += topShear; + vertices[vertexIndex + 3] += -bottomShear; + + + // Compute the angle of rotation for each character based on the animation curve + float x0 = (offsetToMidBaseline.x - boundsMinX) / (boundsMaxX - boundsMinX); // Character's position relative to the bounds of the mesh. + float x1 = x0 + 0.0001f; + float y0 = VertexCurve.Evaluate(x0) * CurveScale; + float y1 = VertexCurve.Evaluate(x1) * CurveScale; + + Vector3 horizontal = new Vector3(1, 0, 0); + //Vector3 normal = new Vector3(-(y1 - y0), (x1 * (boundsMaxX - boundsMinX) + boundsMinX) - offsetToMidBaseline.x, 0); + Vector3 tangent = new Vector3(x1 * (boundsMaxX - boundsMinX) + boundsMinX, y1) - new Vector3(offsetToMidBaseline.x, y0); + + float dot = Mathf.Acos(Vector3.Dot(horizontal, tangent.normalized)) * 57.2957795f; + Vector3 cross = Vector3.Cross(horizontal, tangent); + float angle = cross.z > 0 ? dot : 360 - dot; + + matrix = Matrix4x4.TRS(new Vector3(0, y0, 0), Quaternion.Euler(0, 0, angle), Vector3.one); + + vertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]); + vertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]); + vertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]); + vertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]); + + vertices[vertexIndex + 0] += offsetToMidBaseline; + vertices[vertexIndex + 1] += offsetToMidBaseline; + vertices[vertexIndex + 2] += offsetToMidBaseline; + vertices[vertexIndex + 3] += offsetToMidBaseline; + } + + + // Upload the mesh with the revised information + m_TextComponent.UpdateVertexData(); + + yield return null; // new WaitForSeconds(0.025f); + } + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/SkewTextExample.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/SkewTextExample.cs.meta new file mode 100644 index 0000000..4611105 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/SkewTextExample.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d412675cfb3441efa3bf8dcd9b7624dc +timeCreated: 1458801336 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_DigitValidator.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_DigitValidator.cs new file mode 100644 index 0000000..ad76118 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_DigitValidator.cs @@ -0,0 +1,27 @@ +using UnityEngine; +using System; + + +namespace TMPro +{ + /// + /// EXample of a Custom Character Input Validator to only allow digits from 0 to 9. + /// + [Serializable] + //[CreateAssetMenu(fileName = "InputValidator - Digits.asset", menuName = "TextMeshPro/Input Validators/Digits", order = 100)] + public class TMP_DigitValidator : TMP_InputValidator + { + // Custom text input validation function + public override char Validate(ref string text, ref int pos, char ch) + { + if (ch >= '0' && ch <= '9') + { + text += ch; + pos += 1; + return ch; + } + + return (char)0; + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_DigitValidator.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_DigitValidator.cs.meta new file mode 100644 index 0000000..f013655 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_DigitValidator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1a7eb92a01ed499a987bde9def05fbce +timeCreated: 1473112765 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_ExampleScript_01.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_ExampleScript_01.cs new file mode 100644 index 0000000..9f022f3 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_ExampleScript_01.cs @@ -0,0 +1,64 @@ +using UnityEngine; +using UnityEngine.UI; +using System.Collections; +using TMPro; + + +namespace TMPro.Examples +{ + + public class TMP_ExampleScript_01 : MonoBehaviour + { + public enum objectType { TextMeshPro = 0, TextMeshProUGUI = 1 }; + + public objectType ObjectType; + public bool isStatic; + + private TMP_Text m_text; + + //private TMP_InputField m_inputfield; + + + private const string k_label = "The count is <#0080ff>{0}"; + private int count; + + void Awake() + { + // Get a reference to the TMP text component if one already exists otherwise add one. + // This example show the convenience of having both TMP components derive from TMP_Text. + if (ObjectType == 0) + m_text = GetComponent() ?? gameObject.AddComponent(); + else + m_text = GetComponent() ?? gameObject.AddComponent(); + + // Load a new font asset and assign it to the text object. + m_text.font = Resources.Load("Fonts & Materials/Anton SDF"); + + // Load a new material preset which was created with the context menu duplicate. + m_text.fontSharedMaterial = Resources.Load("Fonts & Materials/Anton SDF - Drop Shadow"); + + // Set the size of the font. + m_text.fontSize = 120; + + // Set the text + m_text.text = "A <#0080ff>simple line of text."; + + // Get the preferred width and height based on the supplied width and height as opposed to the actual size of the current text container. + Vector2 size = m_text.GetPreferredValues(Mathf.Infinity, Mathf.Infinity); + + // Set the size of the RectTransform based on the new calculated values. + m_text.rectTransform.sizeDelta = new Vector2(size.x, size.y); + } + + + void Update() + { + if (!isStatic) + { + m_text.SetText(k_label, count % 1000); + count += 1; + } + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_ExampleScript_01.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_ExampleScript_01.cs.meta new file mode 100644 index 0000000..af5c4d4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_ExampleScript_01.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6f2c5b59b6874405865e2616e4ec276a +timeCreated: 1449625634 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_FrameRateCounter.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_FrameRateCounter.cs new file mode 100644 index 0000000..78311f8 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_FrameRateCounter.cs @@ -0,0 +1,134 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class TMP_FrameRateCounter : MonoBehaviour + { + public float UpdateInterval = 5.0f; + private float m_LastInterval = 0; + private int m_Frames = 0; + + public enum FpsCounterAnchorPositions { TopLeft, BottomLeft, TopRight, BottomRight }; + + public FpsCounterAnchorPositions AnchorPosition = FpsCounterAnchorPositions.TopRight; + + private string htmlColorTag; + private const string fpsLabel = "{0:2} <#8080ff>FPS \n<#FF8000>{1:2} <#8080ff>MS"; + + private TextMeshPro m_TextMeshPro; + private Transform m_frameCounter_transform; + private Camera m_camera; + + private FpsCounterAnchorPositions last_AnchorPosition; + + void Awake() + { + if (!enabled) + return; + + m_camera = Camera.main; + Application.targetFrameRate = 9999; + + GameObject frameCounter = new GameObject("Frame Counter"); + + m_TextMeshPro = frameCounter.AddComponent(); + m_TextMeshPro.font = Resources.Load("Fonts & Materials/LiberationSans SDF"); + m_TextMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/LiberationSans SDF - Overlay"); + + + m_frameCounter_transform = frameCounter.transform; + m_frameCounter_transform.SetParent(m_camera.transform); + m_frameCounter_transform.localRotation = Quaternion.identity; + + m_TextMeshPro.textWrappingMode = TextWrappingModes.NoWrap; + m_TextMeshPro.fontSize = 24; + //m_TextMeshPro.FontColor = new Color32(255, 255, 255, 128); + //m_TextMeshPro.edgeWidth = .15f; + //m_TextMeshPro.isOverlay = true; + + //m_TextMeshPro.FaceColor = new Color32(255, 128, 0, 0); + //m_TextMeshPro.EdgeColor = new Color32(0, 255, 0, 255); + //m_TextMeshPro.FontMaterial.renderQueue = 4000; + + //m_TextMeshPro.CreateSoftShadowClone(new Vector2(1f, -1f)); + + Set_FrameCounter_Position(AnchorPosition); + last_AnchorPosition = AnchorPosition; + + + } + + void Start() + { + m_LastInterval = Time.realtimeSinceStartup; + m_Frames = 0; + } + + void Update() + { + if (AnchorPosition != last_AnchorPosition) + Set_FrameCounter_Position(AnchorPosition); + + last_AnchorPosition = AnchorPosition; + + m_Frames += 1; + float timeNow = Time.realtimeSinceStartup; + + if (timeNow > m_LastInterval + UpdateInterval) + { + // display two fractional digits (f2 format) + float fps = m_Frames / (timeNow - m_LastInterval); + float ms = 1000.0f / Mathf.Max(fps, 0.00001f); + + if (fps < 30) + htmlColorTag = ""; + else if (fps < 10) + htmlColorTag = ""; + else + htmlColorTag = ""; + + //string format = System.String.Format(htmlColorTag + "{0:F2} FPS \n{1:F2} <#8080ff>MS",fps, ms); + //m_TextMeshPro.text = format; + + m_TextMeshPro.SetText(htmlColorTag + fpsLabel, fps, ms); + + m_Frames = 0; + m_LastInterval = timeNow; + } + } + + + void Set_FrameCounter_Position(FpsCounterAnchorPositions anchor_position) + { + //Debug.Log("Changing frame counter anchor position."); + m_TextMeshPro.margin = new Vector4(1f, 1f, 1f, 1f); + + switch (anchor_position) + { + case FpsCounterAnchorPositions.TopLeft: + m_TextMeshPro.alignment = TextAlignmentOptions.TopLeft; + m_TextMeshPro.rectTransform.pivot = new Vector2(0, 1); + m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(0, 1, 100.0f)); + break; + case FpsCounterAnchorPositions.BottomLeft: + m_TextMeshPro.alignment = TextAlignmentOptions.BottomLeft; + m_TextMeshPro.rectTransform.pivot = new Vector2(0, 0); + m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(0, 0, 100.0f)); + break; + case FpsCounterAnchorPositions.TopRight: + m_TextMeshPro.alignment = TextAlignmentOptions.TopRight; + m_TextMeshPro.rectTransform.pivot = new Vector2(1, 1); + m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(1, 1, 100.0f)); + break; + case FpsCounterAnchorPositions.BottomRight: + m_TextMeshPro.alignment = TextAlignmentOptions.BottomRight; + m_TextMeshPro.rectTransform.pivot = new Vector2(1, 0); + m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(1, 0, 100.0f)); + break; + } + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_FrameRateCounter.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_FrameRateCounter.cs.meta new file mode 100644 index 0000000..48fa119 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_FrameRateCounter.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 686ec78b56aa445795335fbadafcfaa4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_PhoneNumberValidator.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_PhoneNumberValidator.cs new file mode 100644 index 0000000..0d363ce --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_PhoneNumberValidator.cs @@ -0,0 +1,105 @@ +using UnityEngine; +using System.Collections; +using System; + +namespace TMPro +{ + /// + /// Example of a Custom Character Input Validator to only allow phone number in the (800) 555-1212 format. + /// + [Serializable] + //[CreateAssetMenu(fileName = "InputValidator - Phone Numbers.asset", menuName = "TextMeshPro/Input Validators/Phone Numbers")] + public class TMP_PhoneNumberValidator : TMP_InputValidator + { + // Custom text input validation function + public override char Validate(ref string text, ref int pos, char ch) + { + Debug.Log("Trying to validate..."); + + // Return unless the character is a valid digit + if (ch < '0' && ch > '9') return (char)0; + + int length = text.Length; + + // Enforce Phone Number format for every character input. + for (int i = 0; i < length + 1; i++) + { + switch (i) + { + case 0: + if (i == length) + text = "(" + ch; + pos = 2; + break; + case 1: + if (i == length) + text += ch; + pos = 2; + break; + case 2: + if (i == length) + text += ch; + pos = 3; + break; + case 3: + if (i == length) + text += ch + ") "; + pos = 6; + break; + case 4: + if (i == length) + text += ") " + ch; + pos = 7; + break; + case 5: + if (i == length) + text += " " + ch; + pos = 7; + break; + case 6: + if (i == length) + text += ch; + pos = 7; + break; + case 7: + if (i == length) + text += ch; + pos = 8; + break; + case 8: + if (i == length) + text += ch + "-"; + pos = 10; + break; + case 9: + if (i == length) + text += "-" + ch; + pos = 11; + break; + case 10: + if (i == length) + text += ch; + pos = 11; + break; + case 11: + if (i == length) + text += ch; + pos = 12; + break; + case 12: + if (i == length) + text += ch; + pos = 13; + break; + case 13: + if (i == length) + text += ch; + pos = 14; + break; + } + } + + return ch; + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_PhoneNumberValidator.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_PhoneNumberValidator.cs.meta new file mode 100644 index 0000000..66324f0 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_PhoneNumberValidator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 83680ab1a69f4102ac67d1459fe76e1f +timeCreated: 1473056437 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventCheck.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventCheck.cs new file mode 100644 index 0000000..abbe658 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventCheck.cs @@ -0,0 +1,73 @@ +using UnityEngine; + + +namespace TMPro.Examples +{ + public class TMP_TextEventCheck : MonoBehaviour + { + + public TMP_TextEventHandler TextEventHandler; + + private TMP_Text m_TextComponent; + + void OnEnable() + { + if (TextEventHandler != null) + { + // Get a reference to the text component + m_TextComponent = TextEventHandler.GetComponent(); + + TextEventHandler.onCharacterSelection.AddListener(OnCharacterSelection); + TextEventHandler.onSpriteSelection.AddListener(OnSpriteSelection); + TextEventHandler.onWordSelection.AddListener(OnWordSelection); + TextEventHandler.onLineSelection.AddListener(OnLineSelection); + TextEventHandler.onLinkSelection.AddListener(OnLinkSelection); + } + } + + + void OnDisable() + { + if (TextEventHandler != null) + { + TextEventHandler.onCharacterSelection.RemoveListener(OnCharacterSelection); + TextEventHandler.onSpriteSelection.RemoveListener(OnSpriteSelection); + TextEventHandler.onWordSelection.RemoveListener(OnWordSelection); + TextEventHandler.onLineSelection.RemoveListener(OnLineSelection); + TextEventHandler.onLinkSelection.RemoveListener(OnLinkSelection); + } + } + + + void OnCharacterSelection(char c, int index) + { + Debug.Log("Character [" + c + "] at Index: " + index + " has been selected."); + } + + void OnSpriteSelection(char c, int index) + { + Debug.Log("Sprite [" + c + "] at Index: " + index + " has been selected."); + } + + void OnWordSelection(string word, int firstCharacterIndex, int length) + { + Debug.Log("Word [" + word + "] with first character index of " + firstCharacterIndex + " and length of " + length + " has been selected."); + } + + void OnLineSelection(string lineText, int firstCharacterIndex, int length) + { + Debug.Log("Line [" + lineText + "] with first character index of " + firstCharacterIndex + " and length of " + length + " has been selected."); + } + + void OnLinkSelection(string linkID, string linkText, int linkIndex) + { + if (m_TextComponent != null) + { + TMP_LinkInfo linkInfo = m_TextComponent.textInfo.linkInfo[linkIndex]; + } + + Debug.Log("Link Index: " + linkIndex + " with ID [" + linkID + "] and Text \"" + linkText + "\" has been selected."); + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventCheck.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventCheck.cs.meta new file mode 100644 index 0000000..9012a15 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventCheck.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d736ce056cf444ca96e424f4d9c42b76 +timeCreated: 1480416736 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventHandler.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventHandler.cs new file mode 100644 index 0000000..88965e2 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventHandler.cs @@ -0,0 +1,263 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.EventSystems; +using System; + + +namespace TMPro +{ + + public class TMP_TextEventHandler : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler + { + [Serializable] + public class CharacterSelectionEvent : UnityEvent { } + + [Serializable] + public class SpriteSelectionEvent : UnityEvent { } + + [Serializable] + public class WordSelectionEvent : UnityEvent { } + + [Serializable] + public class LineSelectionEvent : UnityEvent { } + + [Serializable] + public class LinkSelectionEvent : UnityEvent { } + + + /// + /// Event delegate triggered when pointer is over a character. + /// + public CharacterSelectionEvent onCharacterSelection + { + get { return m_OnCharacterSelection; } + set { m_OnCharacterSelection = value; } + } + [SerializeField] + private CharacterSelectionEvent m_OnCharacterSelection = new CharacterSelectionEvent(); + + + /// + /// Event delegate triggered when pointer is over a sprite. + /// + public SpriteSelectionEvent onSpriteSelection + { + get { return m_OnSpriteSelection; } + set { m_OnSpriteSelection = value; } + } + [SerializeField] + private SpriteSelectionEvent m_OnSpriteSelection = new SpriteSelectionEvent(); + + + /// + /// Event delegate triggered when pointer is over a word. + /// + public WordSelectionEvent onWordSelection + { + get { return m_OnWordSelection; } + set { m_OnWordSelection = value; } + } + [SerializeField] + private WordSelectionEvent m_OnWordSelection = new WordSelectionEvent(); + + + /// + /// Event delegate triggered when pointer is over a line. + /// + public LineSelectionEvent onLineSelection + { + get { return m_OnLineSelection; } + set { m_OnLineSelection = value; } + } + [SerializeField] + private LineSelectionEvent m_OnLineSelection = new LineSelectionEvent(); + + + /// + /// Event delegate triggered when pointer is over a link. + /// + public LinkSelectionEvent onLinkSelection + { + get { return m_OnLinkSelection; } + set { m_OnLinkSelection = value; } + } + [SerializeField] + private LinkSelectionEvent m_OnLinkSelection = new LinkSelectionEvent(); + + + + private TMP_Text m_TextComponent; + + private Camera m_Camera; + private Canvas m_Canvas; + + private int m_selectedLink = -1; + private int m_lastCharIndex = -1; + private int m_lastWordIndex = -1; + private int m_lastLineIndex = -1; + + void Awake() + { + // Get a reference to the text component. + m_TextComponent = gameObject.GetComponent(); + + // Get a reference to the camera rendering the text taking into consideration the text component type. + if (m_TextComponent.GetType() == typeof(TextMeshProUGUI)) + { + m_Canvas = gameObject.GetComponentInParent(); + if (m_Canvas != null) + { + if (m_Canvas.renderMode == RenderMode.ScreenSpaceOverlay) + m_Camera = null; + else + m_Camera = m_Canvas.worldCamera; + } + } + else + { + m_Camera = Camera.main; + } + } + + + void LateUpdate() + { + if (TMP_TextUtilities.IsIntersectingRectTransform(m_TextComponent.rectTransform, Input.mousePosition, m_Camera)) + { + #region Nearest Character + /*int charIndex = TMP_TextUtilities.FindNearestCharacterOnLine(m_TextComponent, Input.mousePosition, 0, m_Camera, false); + if (charIndex != -1 && charIndex != m_lastCharIndex) + { + m_lastCharIndex = charIndex; + }*/ + #endregion + + + #region Example of Character or Sprite Selection + int charIndex = TMP_TextUtilities.FindIntersectingCharacter(m_TextComponent, Input.mousePosition, m_Camera, true); + if (charIndex != -1 && charIndex != m_lastCharIndex) + { + m_lastCharIndex = charIndex; + + TMP_TextElementType elementType = m_TextComponent.textInfo.characterInfo[charIndex].elementType; + + // Send event to any event listeners depending on whether it is a character or sprite. + if (elementType == TMP_TextElementType.Character) + SendOnCharacterSelection(m_TextComponent.textInfo.characterInfo[charIndex].character, charIndex); + else if (elementType == TMP_TextElementType.Sprite) + SendOnSpriteSelection(m_TextComponent.textInfo.characterInfo[charIndex].character, charIndex); + } + #endregion + + + #region Example of Word Selection + // Check if Mouse intersects any words and if so assign a random color to that word. + int wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextComponent, Input.mousePosition, m_Camera); + if (wordIndex != -1 && wordIndex != m_lastWordIndex) + { + m_lastWordIndex = wordIndex; + + // Get the information about the selected word. + TMP_WordInfo wInfo = m_TextComponent.textInfo.wordInfo[wordIndex]; + + // Send the event to any listeners. + SendOnWordSelection(wInfo.GetWord(), wInfo.firstCharacterIndex, wInfo.characterCount); + } + #endregion + + + #region Example of Line Selection + // Check if Mouse intersects any words and if so assign a random color to that word. + int lineIndex = TMP_TextUtilities.FindIntersectingLine(m_TextComponent, Input.mousePosition, m_Camera); + if (lineIndex != -1 && lineIndex != m_lastLineIndex) + { + m_lastLineIndex = lineIndex; + + // Get the information about the selected word. + TMP_LineInfo lineInfo = m_TextComponent.textInfo.lineInfo[lineIndex]; + + // Send the event to any listeners. + char[] buffer = new char[lineInfo.characterCount]; + for (int i = 0; i < lineInfo.characterCount && i < m_TextComponent.textInfo.characterInfo.Length; i++) + { + buffer[i] = m_TextComponent.textInfo.characterInfo[i + lineInfo.firstCharacterIndex].character; + } + + string lineText = new string(buffer); + SendOnLineSelection(lineText, lineInfo.firstCharacterIndex, lineInfo.characterCount); + } + #endregion + + + #region Example of Link Handling + // Check if mouse intersects with any links. + int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextComponent, Input.mousePosition, m_Camera); + + // Handle new Link selection. + if (linkIndex != -1 && linkIndex != m_selectedLink) + { + m_selectedLink = linkIndex; + + // Get information about the link. + TMP_LinkInfo linkInfo = m_TextComponent.textInfo.linkInfo[linkIndex]; + + // Send the event to any listeners. + SendOnLinkSelection(linkInfo.GetLinkID(), linkInfo.GetLinkText(), linkIndex); + } + #endregion + } + else + { + // Reset all selections given we are hovering outside the text container bounds. + m_selectedLink = -1; + m_lastCharIndex = -1; + m_lastWordIndex = -1; + m_lastLineIndex = -1; + } + } + + + public void OnPointerEnter(PointerEventData eventData) + { + //Debug.Log("OnPointerEnter()"); + } + + + public void OnPointerExit(PointerEventData eventData) + { + //Debug.Log("OnPointerExit()"); + } + + + private void SendOnCharacterSelection(char character, int characterIndex) + { + if (onCharacterSelection != null) + onCharacterSelection.Invoke(character, characterIndex); + } + + private void SendOnSpriteSelection(char character, int characterIndex) + { + if (onSpriteSelection != null) + onSpriteSelection.Invoke(character, characterIndex); + } + + private void SendOnWordSelection(string word, int charIndex, int length) + { + if (onWordSelection != null) + onWordSelection.Invoke(word, charIndex, length); + } + + private void SendOnLineSelection(string line, int charIndex, int length) + { + if (onLineSelection != null) + onLineSelection.Invoke(line, charIndex, length); + } + + private void SendOnLinkSelection(string linkID, string linkText, int linkIndex) + { + if (onLinkSelection != null) + onLinkSelection.Invoke(linkID, linkText, linkIndex); + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventHandler.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventHandler.cs.meta new file mode 100644 index 0000000..03c5199 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventHandler.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1312ae25639a4bae8e25ae223209cc50 +timeCreated: 1452811039 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextInfoDebugTool.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextInfoDebugTool.cs new file mode 100644 index 0000000..64e75af --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextInfoDebugTool.cs @@ -0,0 +1,652 @@ +using System; +using UnityEngine; +using System.Collections; +using UnityEditor; + + +namespace TMPro.Examples +{ + + public class TMP_TextInfoDebugTool : MonoBehaviour + { + // Since this script is used for debugging, we exclude it from builds. + // TODO: Rework this script to make it into an editor utility. + #if UNITY_EDITOR + public bool ShowCharacters; + public bool ShowWords; + public bool ShowLinks; + public bool ShowLines; + public bool ShowMeshBounds; + public bool ShowTextBounds; + [Space(10)] + [TextArea(2, 2)] + public string ObjectStats; + + [SerializeField] + private TMP_Text m_TextComponent; + + private Transform m_Transform; + private TMP_TextInfo m_TextInfo; + + private float m_ScaleMultiplier; + private float m_HandleSize; + + + void OnDrawGizmos() + { + if (m_TextComponent == null) + { + m_TextComponent = GetComponent(); + + if (m_TextComponent == null) + return; + } + + m_Transform = m_TextComponent.transform; + + // Get a reference to the text object's textInfo + m_TextInfo = m_TextComponent.textInfo; + + // Update Text Statistics + ObjectStats = "Characters: " + m_TextInfo.characterCount + " Words: " + m_TextInfo.wordCount + " Spaces: " + m_TextInfo.spaceCount + " Sprites: " + m_TextInfo.spriteCount + " Links: " + m_TextInfo.linkCount + + "\nLines: " + m_TextInfo.lineCount + " Pages: " + m_TextInfo.pageCount; + + // Get the handle size for drawing the various + m_ScaleMultiplier = m_TextComponent.GetType() == typeof(TextMeshPro) ? 1 : 0.1f; + m_HandleSize = HandleUtility.GetHandleSize(m_Transform.position) * m_ScaleMultiplier; + + // Draw line metrics + #region Draw Lines + if (ShowLines) + DrawLineBounds(); + #endregion + + // Draw word metrics + #region Draw Words + if (ShowWords) + DrawWordBounds(); + #endregion + + // Draw character metrics + #region Draw Characters + if (ShowCharacters) + DrawCharactersBounds(); + #endregion + + // Draw Quads around each of the words + #region Draw Links + if (ShowLinks) + DrawLinkBounds(); + #endregion + + // Draw Quad around the bounds of the text + #region Draw Bounds + if (ShowMeshBounds) + DrawBounds(); + #endregion + + // Draw Quad around the rendered region of the text. + #region Draw Text Bounds + if (ShowTextBounds) + DrawTextBounds(); + #endregion + } + + + /// + /// Method to draw a rectangle around each character. + /// + /// + void DrawCharactersBounds() + { + int characterCount = m_TextInfo.characterCount; + + for (int i = 0; i < characterCount; i++) + { + // Draw visible as well as invisible characters + TMP_CharacterInfo characterInfo = m_TextInfo.characterInfo[i]; + + bool isCharacterVisible = i < m_TextComponent.maxVisibleCharacters && + characterInfo.lineNumber < m_TextComponent.maxVisibleLines && + i >= m_TextComponent.firstVisibleCharacter; + + if (m_TextComponent.overflowMode == TextOverflowModes.Page) + isCharacterVisible = isCharacterVisible && characterInfo.pageNumber + 1 == m_TextComponent.pageToDisplay; + + if (!isCharacterVisible) + continue; + + float dottedLineSize = 6; + + // Get Bottom Left and Top Right position of the current character + Vector3 bottomLeft = m_Transform.TransformPoint(characterInfo.bottomLeft); + Vector3 topLeft = m_Transform.TransformPoint(new Vector3(characterInfo.topLeft.x, characterInfo.topLeft.y, 0)); + Vector3 topRight = m_Transform.TransformPoint(characterInfo.topRight); + Vector3 bottomRight = m_Transform.TransformPoint(new Vector3(characterInfo.bottomRight.x, characterInfo.bottomRight.y, 0)); + + // Draw character bounds + if (characterInfo.isVisible) + { + Color color = Color.green; + DrawDottedRectangle(bottomLeft, topRight, color); + } + else + { + Color color = Color.grey; + + float whiteSpaceAdvance = Math.Abs(characterInfo.origin - characterInfo.xAdvance) > 0.01f ? characterInfo.xAdvance : characterInfo.origin + (characterInfo.ascender - characterInfo.descender) * 0.03f; + DrawDottedRectangle(m_Transform.TransformPoint(new Vector3(characterInfo.origin, characterInfo.descender, 0)), m_Transform.TransformPoint(new Vector3(whiteSpaceAdvance, characterInfo.ascender, 0)), color, 4); + } + + float origin = characterInfo.origin; + float advance = characterInfo.xAdvance; + float ascentline = characterInfo.ascender; + float baseline = characterInfo.baseLine; + float descentline = characterInfo.descender; + + //Draw Ascent line + Vector3 ascentlineStart = m_Transform.TransformPoint(new Vector3(origin, ascentline, 0)); + Vector3 ascentlineEnd = m_Transform.TransformPoint(new Vector3(advance, ascentline, 0)); + + Handles.color = Color.cyan; + Handles.DrawDottedLine(ascentlineStart, ascentlineEnd, dottedLineSize); + + // Draw Cap Height & Mean line + float capline = characterInfo.fontAsset == null ? 0 : baseline + characterInfo.fontAsset.faceInfo.capLine * characterInfo.scale; + Vector3 capHeightStart = new Vector3(topLeft.x, m_Transform.TransformPoint(new Vector3(0, capline, 0)).y, 0); + Vector3 capHeightEnd = new Vector3(topRight.x, m_Transform.TransformPoint(new Vector3(0, capline, 0)).y, 0); + + float meanline = characterInfo.fontAsset == null ? 0 : baseline + characterInfo.fontAsset.faceInfo.meanLine * characterInfo.scale; + Vector3 meanlineStart = new Vector3(topLeft.x, m_Transform.TransformPoint(new Vector3(0, meanline, 0)).y, 0); + Vector3 meanlineEnd = new Vector3(topRight.x, m_Transform.TransformPoint(new Vector3(0, meanline, 0)).y, 0); + + if (characterInfo.isVisible) + { + // Cap line + Handles.color = Color.cyan; + Handles.DrawDottedLine(capHeightStart, capHeightEnd, dottedLineSize); + + // Mean line + Handles.color = Color.cyan; + Handles.DrawDottedLine(meanlineStart, meanlineEnd, dottedLineSize); + } + + //Draw Base line + Vector3 baselineStart = m_Transform.TransformPoint(new Vector3(origin, baseline, 0)); + Vector3 baselineEnd = m_Transform.TransformPoint(new Vector3(advance, baseline, 0)); + + Handles.color = Color.cyan; + Handles.DrawDottedLine(baselineStart, baselineEnd, dottedLineSize); + + //Draw Descent line + Vector3 descentlineStart = m_Transform.TransformPoint(new Vector3(origin, descentline, 0)); + Vector3 descentlineEnd = m_Transform.TransformPoint(new Vector3(advance, descentline, 0)); + + Handles.color = Color.cyan; + Handles.DrawDottedLine(descentlineStart, descentlineEnd, dottedLineSize); + + // Draw Origin + Vector3 originPosition = m_Transform.TransformPoint(new Vector3(origin, baseline, 0)); + DrawCrosshair(originPosition, 0.05f / m_ScaleMultiplier, Color.cyan); + + // Draw Horizontal Advance + Vector3 advancePosition = m_Transform.TransformPoint(new Vector3(advance, baseline, 0)); + DrawSquare(advancePosition, 0.025f / m_ScaleMultiplier, Color.yellow); + DrawCrosshair(advancePosition, 0.0125f / m_ScaleMultiplier, Color.yellow); + + // Draw text labels for metrics + if (m_HandleSize < 0.5f) + { + GUIStyle style = new GUIStyle(GUI.skin.GetStyle("Label")); + style.normal.textColor = new Color(0.6f, 0.6f, 0.6f, 1.0f); + style.fontSize = 12; + style.fixedWidth = 200; + style.fixedHeight = 20; + + Vector3 labelPosition; + float center = (origin + advance) / 2; + + //float baselineMetrics = 0; + //float ascentlineMetrics = ascentline - baseline; + //float caplineMetrics = capline - baseline; + //float meanlineMetrics = meanline - baseline; + //float descentlineMetrics = descentline - baseline; + + // Ascent Line + labelPosition = m_Transform.TransformPoint(new Vector3(center, ascentline, 0)); + style.alignment = TextAnchor.UpperCenter; + Handles.Label(labelPosition, "Ascent Line", style); + //Handles.Label(labelPosition, "Ascent Line (" + ascentlineMetrics.ToString("f3") + ")" , style); + + // Base Line + labelPosition = m_Transform.TransformPoint(new Vector3(center, baseline, 0)); + Handles.Label(labelPosition, "Base Line", style); + //Handles.Label(labelPosition, "Base Line (" + baselineMetrics.ToString("f3") + ")" , style); + + // Descent line + labelPosition = m_Transform.TransformPoint(new Vector3(center, descentline, 0)); + Handles.Label(labelPosition, "Descent Line", style); + //Handles.Label(labelPosition, "Descent Line (" + descentlineMetrics.ToString("f3") + ")" , style); + + if (characterInfo.isVisible) + { + // Cap Line + labelPosition = m_Transform.TransformPoint(new Vector3(center, capline, 0)); + style.alignment = TextAnchor.UpperCenter; + Handles.Label(labelPosition, "Cap Line", style); + //Handles.Label(labelPosition, "Cap Line (" + caplineMetrics.ToString("f3") + ")" , style); + + // Mean Line + labelPosition = m_Transform.TransformPoint(new Vector3(center, meanline, 0)); + style.alignment = TextAnchor.UpperCenter; + Handles.Label(labelPosition, "Mean Line", style); + //Handles.Label(labelPosition, "Mean Line (" + ascentlineMetrics.ToString("f3") + ")" , style); + + // Origin + labelPosition = m_Transform.TransformPoint(new Vector3(origin, baseline, 0)); + style.alignment = TextAnchor.UpperRight; + Handles.Label(labelPosition, "Origin ", style); + + // Advance + labelPosition = m_Transform.TransformPoint(new Vector3(advance, baseline, 0)); + style.alignment = TextAnchor.UpperLeft; + Handles.Label(labelPosition, " Advance", style); + } + } + } + } + + + /// + /// Method to draw rectangles around each word of the text. + /// + /// + void DrawWordBounds() + { + for (int i = 0; i < m_TextInfo.wordCount; i++) + { + TMP_WordInfo wInfo = m_TextInfo.wordInfo[i]; + + bool isBeginRegion = false; + + Vector3 bottomLeft = Vector3.zero; + Vector3 topLeft = Vector3.zero; + Vector3 bottomRight = Vector3.zero; + Vector3 topRight = Vector3.zero; + + float maxAscender = -Mathf.Infinity; + float minDescender = Mathf.Infinity; + + Color wordColor = Color.green; + + // Iterate through each character of the word + for (int j = 0; j < wInfo.characterCount; j++) + { + int characterIndex = wInfo.firstCharacterIndex + j; + TMP_CharacterInfo currentCharInfo = m_TextInfo.characterInfo[characterIndex]; + int currentLine = currentCharInfo.lineNumber; + + bool isCharacterVisible = characterIndex > m_TextComponent.maxVisibleCharacters || + currentCharInfo.lineNumber > m_TextComponent.maxVisibleLines || + (m_TextComponent.overflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != m_TextComponent.pageToDisplay) ? false : true; + + // Track Max Ascender and Min Descender + maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender); + minDescender = Mathf.Min(minDescender, currentCharInfo.descender); + + if (isBeginRegion == false && isCharacterVisible) + { + isBeginRegion = true; + + bottomLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0); + topLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0); + + //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]"); + + // If Word is one character + if (wInfo.characterCount == 1) + { + isBeginRegion = false; + + topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0)); + bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0)); + bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0)); + topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0)); + + // Draw Region + DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor); + + //Debug.Log("End Word Region at [" + currentCharInfo.character + "]"); + } + } + + // Last Character of Word + if (isBeginRegion && j == wInfo.characterCount - 1) + { + isBeginRegion = false; + + topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0)); + bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0)); + bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0)); + topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0)); + + // Draw Region + DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor); + + //Debug.Log("End Word Region at [" + currentCharInfo.character + "]"); + } + // If Word is split on more than one line. + else if (isBeginRegion && currentLine != m_TextInfo.characterInfo[characterIndex + 1].lineNumber) + { + isBeginRegion = false; + + topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0)); + bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0)); + bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0)); + topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0)); + + // Draw Region + DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor); + //Debug.Log("End Word Region at [" + currentCharInfo.character + "]"); + maxAscender = -Mathf.Infinity; + minDescender = Mathf.Infinity; + + } + } + + //Debug.Log(wInfo.GetWord(m_TextMeshPro.textInfo.characterInfo)); + } + + + } + + + /// + /// Draw rectangle around each of the links contained in the text. + /// + /// + void DrawLinkBounds() + { + TMP_TextInfo textInfo = m_TextComponent.textInfo; + + for (int i = 0; i < textInfo.linkCount; i++) + { + TMP_LinkInfo linkInfo = textInfo.linkInfo[i]; + + bool isBeginRegion = false; + + Vector3 bottomLeft = Vector3.zero; + Vector3 topLeft = Vector3.zero; + Vector3 bottomRight = Vector3.zero; + Vector3 topRight = Vector3.zero; + + float maxAscender = -Mathf.Infinity; + float minDescender = Mathf.Infinity; + + Color32 linkColor = Color.cyan; + + // Iterate through each character of the link text + for (int j = 0; j < linkInfo.linkTextLength; j++) + { + int characterIndex = linkInfo.linkTextfirstCharacterIndex + j; + TMP_CharacterInfo currentCharInfo = textInfo.characterInfo[characterIndex]; + int currentLine = currentCharInfo.lineNumber; + + bool isCharacterVisible = characterIndex > m_TextComponent.maxVisibleCharacters || + currentCharInfo.lineNumber > m_TextComponent.maxVisibleLines || + (m_TextComponent.overflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != m_TextComponent.pageToDisplay) ? false : true; + + // Track Max Ascender and Min Descender + maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender); + minDescender = Mathf.Min(minDescender, currentCharInfo.descender); + + if (isBeginRegion == false && isCharacterVisible) + { + isBeginRegion = true; + + bottomLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0); + topLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0); + + //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]"); + + // If Link is one character + if (linkInfo.linkTextLength == 1) + { + isBeginRegion = false; + + topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0)); + bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0)); + bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0)); + topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0)); + + // Draw Region + DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor); + + //Debug.Log("End Word Region at [" + currentCharInfo.character + "]"); + } + } + + // Last Character of Link + if (isBeginRegion && j == linkInfo.linkTextLength - 1) + { + isBeginRegion = false; + + topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0)); + bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0)); + bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0)); + topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0)); + + // Draw Region + DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor); + + //Debug.Log("End Word Region at [" + currentCharInfo.character + "]"); + } + // If Link is split on more than one line. + else if (isBeginRegion && currentLine != textInfo.characterInfo[characterIndex + 1].lineNumber) + { + isBeginRegion = false; + + topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0)); + bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0)); + bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0)); + topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0)); + + // Draw Region + DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor); + + maxAscender = -Mathf.Infinity; + minDescender = Mathf.Infinity; + //Debug.Log("End Word Region at [" + currentCharInfo.character + "]"); + } + } + + //Debug.Log(wInfo.GetWord(m_TextMeshPro.textInfo.characterInfo)); + } + } + + + /// + /// Draw Rectangles around each lines of the text. + /// + /// + void DrawLineBounds() + { + int lineCount = m_TextInfo.lineCount; + + for (int i = 0; i < lineCount; i++) + { + TMP_LineInfo lineInfo = m_TextInfo.lineInfo[i]; + TMP_CharacterInfo firstCharacterInfo = m_TextInfo.characterInfo[lineInfo.firstCharacterIndex]; + TMP_CharacterInfo lastCharacterInfo = m_TextInfo.characterInfo[lineInfo.lastCharacterIndex]; + + bool isLineVisible = (lineInfo.characterCount == 1 && (firstCharacterInfo.character == 10 || firstCharacterInfo.character == 11 || firstCharacterInfo.character == 0x2028 || firstCharacterInfo.character == 0x2029)) || + i > m_TextComponent.maxVisibleLines || + (m_TextComponent.overflowMode == TextOverflowModes.Page && firstCharacterInfo.pageNumber + 1 != m_TextComponent.pageToDisplay) ? false : true; + + if (!isLineVisible) continue; + + float lineBottomLeft = firstCharacterInfo.bottomLeft.x; + float lineTopRight = lastCharacterInfo.topRight.x; + + float ascentline = lineInfo.ascender; + float baseline = lineInfo.baseline; + float descentline = lineInfo.descender; + + float dottedLineSize = 12; + + // Draw line extents + DrawDottedRectangle(m_Transform.TransformPoint(lineInfo.lineExtents.min), m_Transform.TransformPoint(lineInfo.lineExtents.max), Color.green, 4); + + // Draw Ascent line + Vector3 ascentlineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, ascentline, 0)); + Vector3 ascentlineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, ascentline, 0)); + + Handles.color = Color.yellow; + Handles.DrawDottedLine(ascentlineStart, ascentlineEnd, dottedLineSize); + + // Draw Base line + Vector3 baseLineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, baseline, 0)); + Vector3 baseLineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, baseline, 0)); + + Handles.color = Color.yellow; + Handles.DrawDottedLine(baseLineStart, baseLineEnd, dottedLineSize); + + // Draw Descent line + Vector3 descentLineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, descentline, 0)); + Vector3 descentLineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, descentline, 0)); + + Handles.color = Color.yellow; + Handles.DrawDottedLine(descentLineStart, descentLineEnd, dottedLineSize); + + // Draw text labels for metrics + if (m_HandleSize < 1.0f) + { + GUIStyle style = new GUIStyle(); + style.normal.textColor = new Color(0.8f, 0.8f, 0.8f, 1.0f); + style.fontSize = 12; + style.fixedWidth = 200; + style.fixedHeight = 20; + Vector3 labelPosition; + + // Ascent Line + labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, ascentline, 0)); + style.padding = new RectOffset(0, 10, 0, 5); + style.alignment = TextAnchor.MiddleRight; + Handles.Label(labelPosition, "Ascent Line", style); + + // Base Line + labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, baseline, 0)); + Handles.Label(labelPosition, "Base Line", style); + + // Descent line + labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, descentline, 0)); + Handles.Label(labelPosition, "Descent Line", style); + } + } + } + + + /// + /// Draw Rectangle around the bounds of the text object. + /// + void DrawBounds() + { + Bounds meshBounds = m_TextComponent.bounds; + + // Get Bottom Left and Top Right position of each word + Vector3 bottomLeft = m_TextComponent.transform.position + meshBounds.min; + Vector3 topRight = m_TextComponent.transform.position + meshBounds.max; + + DrawRectangle(bottomLeft, topRight, new Color(1, 0.5f, 0)); + } + + + void DrawTextBounds() + { + Bounds textBounds = m_TextComponent.textBounds; + + Vector3 bottomLeft = m_TextComponent.transform.position + (textBounds.center - textBounds.extents); + Vector3 topRight = m_TextComponent.transform.position + (textBounds.center + textBounds.extents); + + DrawRectangle(bottomLeft, topRight, new Color(0f, 0.5f, 0.5f)); + } + + + // Draw Rectangles + void DrawRectangle(Vector3 BL, Vector3 TR, Color color) + { + Gizmos.color = color; + + Gizmos.DrawLine(new Vector3(BL.x, BL.y, 0), new Vector3(BL.x, TR.y, 0)); + Gizmos.DrawLine(new Vector3(BL.x, TR.y, 0), new Vector3(TR.x, TR.y, 0)); + Gizmos.DrawLine(new Vector3(TR.x, TR.y, 0), new Vector3(TR.x, BL.y, 0)); + Gizmos.DrawLine(new Vector3(TR.x, BL.y, 0), new Vector3(BL.x, BL.y, 0)); + } + + void DrawDottedRectangle(Vector3 bottomLeft, Vector3 topRight, Color color, float size = 5.0f) + { + Handles.color = color; + Handles.DrawDottedLine(bottomLeft, new Vector3(bottomLeft.x, topRight.y, bottomLeft.z), size); + Handles.DrawDottedLine(new Vector3(bottomLeft.x, topRight.y, bottomLeft.z), topRight, size); + Handles.DrawDottedLine(topRight, new Vector3(topRight.x, bottomLeft.y, bottomLeft.z), size); + Handles.DrawDottedLine(new Vector3(topRight.x, bottomLeft.y, bottomLeft.z), bottomLeft, size); + } + + void DrawSolidRectangle(Vector3 bottomLeft, Vector3 topRight, Color color, float size = 5.0f) + { + Handles.color = color; + Rect rect = new Rect(bottomLeft, topRight - bottomLeft); + Handles.DrawSolidRectangleWithOutline(rect, color, Color.black); + } + + void DrawSquare(Vector3 position, float size, Color color) + { + Handles.color = color; + Vector3 bottomLeft = new Vector3(position.x - size, position.y - size, position.z); + Vector3 topLeft = new Vector3(position.x - size, position.y + size, position.z); + Vector3 topRight = new Vector3(position.x + size, position.y + size, position.z); + Vector3 bottomRight = new Vector3(position.x + size, position.y - size, position.z); + + Handles.DrawLine(bottomLeft, topLeft); + Handles.DrawLine(topLeft, topRight); + Handles.DrawLine(topRight, bottomRight); + Handles.DrawLine(bottomRight, bottomLeft); + } + + void DrawCrosshair(Vector3 position, float size, Color color) + { + Handles.color = color; + + Handles.DrawLine(new Vector3(position.x - size, position.y, position.z), new Vector3(position.x + size, position.y, position.z)); + Handles.DrawLine(new Vector3(position.x, position.y - size, position.z), new Vector3(position.x, position.y + size, position.z)); + } + + + // Draw Rectangles + void DrawRectangle(Vector3 bl, Vector3 tl, Vector3 tr, Vector3 br, Color color) + { + Gizmos.color = color; + + Gizmos.DrawLine(bl, tl); + Gizmos.DrawLine(tl, tr); + Gizmos.DrawLine(tr, br); + Gizmos.DrawLine(br, bl); + } + + + // Draw Rectangles + void DrawDottedRectangle(Vector3 bl, Vector3 tl, Vector3 tr, Vector3 br, Color color) + { + var cam = Camera.current; + float dotSpacing = (cam.WorldToScreenPoint(br).x - cam.WorldToScreenPoint(bl).x) / 75f; + UnityEditor.Handles.color = color; + + UnityEditor.Handles.DrawDottedLine(bl, tl, dotSpacing); + UnityEditor.Handles.DrawDottedLine(tl, tr, dotSpacing); + UnityEditor.Handles.DrawDottedLine(tr, br, dotSpacing); + UnityEditor.Handles.DrawDottedLine(br, bl, dotSpacing); + } + #endif + } +} + diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextInfoDebugTool.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextInfoDebugTool.cs.meta new file mode 100644 index 0000000..12400bf --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextInfoDebugTool.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 21256c5b62f346f18640dad779911e20 +timeCreated: 1430348781 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_A.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_A.cs new file mode 100644 index 0000000..33d56e4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_A.cs @@ -0,0 +1,157 @@ +using UnityEngine; +using UnityEngine.EventSystems; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class TMP_TextSelector_A : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler + { + private TextMeshPro m_TextMeshPro; + + private Camera m_Camera; + + private bool m_isHoveringObject; + private int m_selectedLink = -1; + private int m_lastCharIndex = -1; + private int m_lastWordIndex = -1; + + void Awake() + { + m_TextMeshPro = gameObject.GetComponent(); + m_Camera = Camera.main; + + // Force generation of the text object so we have valid data to work with. This is needed since LateUpdate() will be called before the text object has a chance to generated when entering play mode. + m_TextMeshPro.ForceMeshUpdate(); + } + + + void LateUpdate() + { + m_isHoveringObject = false; + + if (TMP_TextUtilities.IsIntersectingRectTransform(m_TextMeshPro.rectTransform, Input.mousePosition, Camera.main)) + { + m_isHoveringObject = true; + } + + if (m_isHoveringObject) + { + #region Example of Character Selection + int charIndex = TMP_TextUtilities.FindIntersectingCharacter(m_TextMeshPro, Input.mousePosition, Camera.main, true); + if (charIndex != -1 && charIndex != m_lastCharIndex && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) + { + //Debug.Log("[" + m_TextMeshPro.textInfo.characterInfo[charIndex].character + "] has been selected."); + + m_lastCharIndex = charIndex; + + int meshIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].materialReferenceIndex; + + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].vertexIndex; + + Color32 c = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255); + + Color32[] vertexColors = m_TextMeshPro.textInfo.meshInfo[meshIndex].colors32; + + vertexColors[vertexIndex + 0] = c; + vertexColors[vertexIndex + 1] = c; + vertexColors[vertexIndex + 2] = c; + vertexColors[vertexIndex + 3] = c; + + //m_TextMeshPro.mesh.colors32 = vertexColors; + m_TextMeshPro.textInfo.meshInfo[meshIndex].mesh.colors32 = vertexColors; + } + #endregion + + #region Example of Link Handling + // Check if mouse intersects with any links. + int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, m_Camera); + + // Clear previous link selection if one existed. + if ((linkIndex == -1 && m_selectedLink != -1) || linkIndex != m_selectedLink) + { + //m_TextPopup_RectTransform.gameObject.SetActive(false); + m_selectedLink = -1; + } + + // Handle new Link selection. + if (linkIndex != -1 && linkIndex != m_selectedLink) + { + m_selectedLink = linkIndex; + + TMP_LinkInfo linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex]; + + // The following provides an example of how to access the link properties. + //Debug.Log("Link ID: \"" + linkInfo.GetLinkID() + "\" Link Text: \"" + linkInfo.GetLinkText() + "\""); // Example of how to retrieve the Link ID and Link Text. + + Vector3 worldPointInRectangle; + + RectTransformUtility.ScreenPointToWorldPointInRectangle(m_TextMeshPro.rectTransform, Input.mousePosition, m_Camera, out worldPointInRectangle); + + switch (linkInfo.GetLinkID()) + { + case "id_01": // 100041637: // id_01 + //m_TextPopup_RectTransform.position = worldPointInRectangle; + //m_TextPopup_RectTransform.gameObject.SetActive(true); + //m_TextPopup_TMPComponent.text = k_LinkText + " ID 01"; + break; + case "id_02": // 100041638: // id_02 + //m_TextPopup_RectTransform.position = worldPointInRectangle; + //m_TextPopup_RectTransform.gameObject.SetActive(true); + //m_TextPopup_TMPComponent.text = k_LinkText + " ID 02"; + break; + } + } + #endregion + + + #region Example of Word Selection + // Check if Mouse intersects any words and if so assign a random color to that word. + int wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextMeshPro, Input.mousePosition, Camera.main); + if (wordIndex != -1 && wordIndex != m_lastWordIndex) + { + m_lastWordIndex = wordIndex; + + TMP_WordInfo wInfo = m_TextMeshPro.textInfo.wordInfo[wordIndex]; + + Vector3 wordPOS = m_TextMeshPro.transform.TransformPoint(m_TextMeshPro.textInfo.characterInfo[wInfo.firstCharacterIndex].bottomLeft); + wordPOS = Camera.main.WorldToScreenPoint(wordPOS); + + //Debug.Log("Mouse Position: " + Input.mousePosition.ToString("f3") + " Word Position: " + wordPOS.ToString("f3")); + + Color32[] vertexColors = m_TextMeshPro.textInfo.meshInfo[0].colors32; + + Color32 c = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255); + for (int i = 0; i < wInfo.characterCount; i++) + { + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[wInfo.firstCharacterIndex + i].vertexIndex; + + vertexColors[vertexIndex + 0] = c; + vertexColors[vertexIndex + 1] = c; + vertexColors[vertexIndex + 2] = c; + vertexColors[vertexIndex + 3] = c; + } + + m_TextMeshPro.mesh.colors32 = vertexColors; + } + #endregion + } + } + + + public void OnPointerEnter(PointerEventData eventData) + { + Debug.Log("OnPointerEnter()"); + m_isHoveringObject = true; + } + + + public void OnPointerExit(PointerEventData eventData) + { + Debug.Log("OnPointerExit()"); + m_isHoveringObject = false; + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_A.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_A.cs.meta new file mode 100644 index 0000000..da25ec4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_A.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 103e0a6a1d404693b9fb1a5173e0e979 +timeCreated: 1452811039 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_B.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_B.cs new file mode 100644 index 0000000..e11087d --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_B.cs @@ -0,0 +1,547 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.EventSystems; +using System.Collections; +using System.Collections.Generic; + + +#pragma warning disable 0618 // Disabled warning due to SetVertices being deprecated until new release with SetMesh() is available. + +namespace TMPro.Examples +{ + + public class TMP_TextSelector_B : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler, IPointerUpHandler + { + public RectTransform TextPopup_Prefab_01; + + private RectTransform m_TextPopup_RectTransform; + private TextMeshProUGUI m_TextPopup_TMPComponent; + private const string k_LinkText = "You have selected link <#ffff00>"; + private const string k_WordText = "Word Index: <#ffff00>"; + + + private TextMeshProUGUI m_TextMeshPro; + private Canvas m_Canvas; + private Camera m_Camera; + + // Flags + private bool isHoveringObject; + private int m_selectedWord = -1; + private int m_selectedLink = -1; + private int m_lastIndex = -1; + + private Matrix4x4 m_matrix; + + private TMP_MeshInfo[] m_cachedMeshInfoVertexData; + + void Awake() + { + m_TextMeshPro = gameObject.GetComponent(); + + + m_Canvas = gameObject.GetComponentInParent(); + + // Get a reference to the camera if Canvas Render Mode is not ScreenSpace Overlay. + if (m_Canvas.renderMode == RenderMode.ScreenSpaceOverlay) + m_Camera = null; + else + m_Camera = m_Canvas.worldCamera; + + // Create pop-up text object which is used to show the link information. + m_TextPopup_RectTransform = Instantiate(TextPopup_Prefab_01) as RectTransform; + m_TextPopup_RectTransform.SetParent(m_Canvas.transform, false); + m_TextPopup_TMPComponent = m_TextPopup_RectTransform.GetComponentInChildren(); + m_TextPopup_RectTransform.gameObject.SetActive(false); + } + + + void OnEnable() + { + // Subscribe to event fired when text object has been regenerated. + TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED); + } + + void OnDisable() + { + // UnSubscribe to event fired when text object has been regenerated. + TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED); + } + + + void ON_TEXT_CHANGED(Object obj) + { + if (obj == m_TextMeshPro) + { + // Update cached vertex data. + m_cachedMeshInfoVertexData = m_TextMeshPro.textInfo.CopyMeshInfoVertexData(); + } + } + + + void LateUpdate() + { + if (isHoveringObject) + { + // Check if Mouse Intersects any of the characters. If so, assign a random color. + #region Handle Character Selection + int charIndex = TMP_TextUtilities.FindIntersectingCharacter(m_TextMeshPro, Input.mousePosition, m_Camera, true); + + // Undo Swap and Vertex Attribute changes. + if (charIndex == -1 || charIndex != m_lastIndex) + { + RestoreCachedVertexAttributes(m_lastIndex); + m_lastIndex = -1; + } + + if (charIndex != -1 && charIndex != m_lastIndex && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) + { + m_lastIndex = charIndex; + + // Get the index of the material / sub text object used by this character. + int materialIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].materialReferenceIndex; + + // Get the index of the first vertex of the selected character. + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].vertexIndex; + + // Get a reference to the vertices array. + Vector3[] vertices = m_TextMeshPro.textInfo.meshInfo[materialIndex].vertices; + + // Determine the center point of the character. + Vector2 charMidBasline = (vertices[vertexIndex + 0] + vertices[vertexIndex + 2]) / 2; + + // Need to translate all 4 vertices of the character to aligned with middle of character / baseline. + // This is needed so the matrix TRS is applied at the origin for each character. + Vector3 offset = charMidBasline; + + // Translate the character to the middle baseline. + vertices[vertexIndex + 0] = vertices[vertexIndex + 0] - offset; + vertices[vertexIndex + 1] = vertices[vertexIndex + 1] - offset; + vertices[vertexIndex + 2] = vertices[vertexIndex + 2] - offset; + vertices[vertexIndex + 3] = vertices[vertexIndex + 3] - offset; + + float zoomFactor = 1.5f; + + // Setup the Matrix for the scale change. + m_matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one * zoomFactor); + + // Apply Matrix operation on the given character. + vertices[vertexIndex + 0] = m_matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]); + vertices[vertexIndex + 1] = m_matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]); + vertices[vertexIndex + 2] = m_matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]); + vertices[vertexIndex + 3] = m_matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]); + + // Translate the character back to its original position. + vertices[vertexIndex + 0] = vertices[vertexIndex + 0] + offset; + vertices[vertexIndex + 1] = vertices[vertexIndex + 1] + offset; + vertices[vertexIndex + 2] = vertices[vertexIndex + 2] + offset; + vertices[vertexIndex + 3] = vertices[vertexIndex + 3] + offset; + + // Change Vertex Colors of the highlighted character + Color32 c = new Color32(255, 255, 192, 255); + + // Get a reference to the vertex color + Color32[] vertexColors = m_TextMeshPro.textInfo.meshInfo[materialIndex].colors32; + + vertexColors[vertexIndex + 0] = c; + vertexColors[vertexIndex + 1] = c; + vertexColors[vertexIndex + 2] = c; + vertexColors[vertexIndex + 3] = c; + + + // Get a reference to the meshInfo of the selected character. + TMP_MeshInfo meshInfo = m_TextMeshPro.textInfo.meshInfo[materialIndex]; + + // Get the index of the last character's vertex attributes. + int lastVertexIndex = vertices.Length - 4; + + // Swap the current character's vertex attributes with those of the last element in the vertex attribute arrays. + // We do this to make sure this character is rendered last and over other characters. + meshInfo.SwapVertexData(vertexIndex, lastVertexIndex); + + // Need to update the appropriate + m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All); + } + #endregion + + + #region Word Selection Handling + //Check if Mouse intersects any words and if so assign a random color to that word. + int wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextMeshPro, Input.mousePosition, m_Camera); + + // Clear previous word selection. + if (m_TextPopup_RectTransform != null && m_selectedWord != -1 && (wordIndex == -1 || wordIndex != m_selectedWord)) + { + TMP_WordInfo wInfo = m_TextMeshPro.textInfo.wordInfo[m_selectedWord]; + + // Iterate through each of the characters of the word. + for (int i = 0; i < wInfo.characterCount; i++) + { + int characterIndex = wInfo.firstCharacterIndex + i; + + // Get the index of the material / sub text object used by this character. + int meshIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].materialReferenceIndex; + + // Get the index of the first vertex of this character. + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].vertexIndex; + + // Get a reference to the vertex color + Color32[] vertexColors = m_TextMeshPro.textInfo.meshInfo[meshIndex].colors32; + + Color32 c = vertexColors[vertexIndex + 0].Tint(1.33333f); + + vertexColors[vertexIndex + 0] = c; + vertexColors[vertexIndex + 1] = c; + vertexColors[vertexIndex + 2] = c; + vertexColors[vertexIndex + 3] = c; + } + + // Update Geometry + m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All); + + m_selectedWord = -1; + } + + + // Word Selection Handling + if (wordIndex != -1 && wordIndex != m_selectedWord && !(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) + { + m_selectedWord = wordIndex; + + TMP_WordInfo wInfo = m_TextMeshPro.textInfo.wordInfo[wordIndex]; + + // Iterate through each of the characters of the word. + for (int i = 0; i < wInfo.characterCount; i++) + { + int characterIndex = wInfo.firstCharacterIndex + i; + + // Get the index of the material / sub text object used by this character. + int meshIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].materialReferenceIndex; + + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].vertexIndex; + + // Get a reference to the vertex color + Color32[] vertexColors = m_TextMeshPro.textInfo.meshInfo[meshIndex].colors32; + + Color32 c = vertexColors[vertexIndex + 0].Tint(0.75f); + + vertexColors[vertexIndex + 0] = c; + vertexColors[vertexIndex + 1] = c; + vertexColors[vertexIndex + 2] = c; + vertexColors[vertexIndex + 3] = c; + } + + // Update Geometry + m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All); + + } + #endregion + + + #region Example of Link Handling + // Check if mouse intersects with any links. + int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, m_Camera); + + // Clear previous link selection if one existed. + if ((linkIndex == -1 && m_selectedLink != -1) || linkIndex != m_selectedLink) + { + m_TextPopup_RectTransform.gameObject.SetActive(false); + m_selectedLink = -1; + } + + // Handle new Link selection. + if (linkIndex != -1 && linkIndex != m_selectedLink) + { + m_selectedLink = linkIndex; + + TMP_LinkInfo linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex]; + + // Debug.Log("Link ID: \"" + linkInfo.GetLinkID() + "\" Link Text: \"" + linkInfo.GetLinkText() + "\""); // Example of how to retrieve the Link ID and Link Text. + + Vector3 worldPointInRectangle; + RectTransformUtility.ScreenPointToWorldPointInRectangle(m_TextMeshPro.rectTransform, Input.mousePosition, m_Camera, out worldPointInRectangle); + + switch (linkInfo.GetLinkID()) + { + case "id_01": // 100041637: // id_01 + m_TextPopup_RectTransform.position = worldPointInRectangle; + m_TextPopup_RectTransform.gameObject.SetActive(true); + m_TextPopup_TMPComponent.text = k_LinkText + " ID 01"; + break; + case "id_02": // 100041638: // id_02 + m_TextPopup_RectTransform.position = worldPointInRectangle; + m_TextPopup_RectTransform.gameObject.SetActive(true); + m_TextPopup_TMPComponent.text = k_LinkText + " ID 02"; + break; + } + } + #endregion + + } + else + { + // Restore any character that may have been modified + if (m_lastIndex != -1) + { + RestoreCachedVertexAttributes(m_lastIndex); + m_lastIndex = -1; + } + } + + } + + + public void OnPointerEnter(PointerEventData eventData) + { + //Debug.Log("OnPointerEnter()"); + isHoveringObject = true; + } + + + public void OnPointerExit(PointerEventData eventData) + { + //Debug.Log("OnPointerExit()"); + isHoveringObject = false; + } + + + public void OnPointerClick(PointerEventData eventData) + { + //Debug.Log("Click at POS: " + eventData.position + " World POS: " + eventData.worldPosition); + + // Check if Mouse Intersects any of the characters. If so, assign a random color. + #region Character Selection Handling + /* + int charIndex = TMP_TextUtilities.FindIntersectingCharacter(m_TextMeshPro, Input.mousePosition, m_Camera, true); + if (charIndex != -1 && charIndex != m_lastIndex) + { + //Debug.Log("Character [" + m_TextMeshPro.textInfo.characterInfo[index].character + "] was selected at POS: " + eventData.position); + m_lastIndex = charIndex; + + Color32 c = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255); + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].vertexIndex; + + UIVertex[] uiVertices = m_TextMeshPro.textInfo.meshInfo.uiVertices; + + uiVertices[vertexIndex + 0].color = c; + uiVertices[vertexIndex + 1].color = c; + uiVertices[vertexIndex + 2].color = c; + uiVertices[vertexIndex + 3].color = c; + + m_TextMeshPro.canvasRenderer.SetVertices(uiVertices, uiVertices.Length); + } + */ + #endregion + + + #region Word Selection Handling + //Check if Mouse intersects any words and if so assign a random color to that word. + /* + int wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextMeshPro, Input.mousePosition, m_Camera); + + // Clear previous word selection. + if (m_TextPopup_RectTransform != null && m_selectedWord != -1 && (wordIndex == -1 || wordIndex != m_selectedWord)) + { + TMP_WordInfo wInfo = m_TextMeshPro.textInfo.wordInfo[m_selectedWord]; + + // Get a reference to the uiVertices array. + UIVertex[] uiVertices = m_TextMeshPro.textInfo.meshInfo.uiVertices; + + // Iterate through each of the characters of the word. + for (int i = 0; i < wInfo.characterCount; i++) + { + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[wInfo.firstCharacterIndex + i].vertexIndex; + + Color32 c = uiVertices[vertexIndex + 0].color.Tint(1.33333f); + + uiVertices[vertexIndex + 0].color = c; + uiVertices[vertexIndex + 1].color = c; + uiVertices[vertexIndex + 2].color = c; + uiVertices[vertexIndex + 3].color = c; + } + + m_TextMeshPro.canvasRenderer.SetVertices(uiVertices, uiVertices.Length); + + m_selectedWord = -1; + } + + // Handle word selection + if (wordIndex != -1 && wordIndex != m_selectedWord) + { + m_selectedWord = wordIndex; + + TMP_WordInfo wInfo = m_TextMeshPro.textInfo.wordInfo[wordIndex]; + + // Get a reference to the uiVertices array. + UIVertex[] uiVertices = m_TextMeshPro.textInfo.meshInfo.uiVertices; + + // Iterate through each of the characters of the word. + for (int i = 0; i < wInfo.characterCount; i++) + { + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[wInfo.firstCharacterIndex + i].vertexIndex; + + Color32 c = uiVertices[vertexIndex + 0].color.Tint(0.75f); + + uiVertices[vertexIndex + 0].color = c; + uiVertices[vertexIndex + 1].color = c; + uiVertices[vertexIndex + 2].color = c; + uiVertices[vertexIndex + 3].color = c; + } + + m_TextMeshPro.canvasRenderer.SetVertices(uiVertices, uiVertices.Length); + } + */ + #endregion + + + #region Link Selection Handling + /* + // Check if Mouse intersects any words and if so assign a random color to that word. + int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, m_Camera); + if (linkIndex != -1) + { + TMP_LinkInfo linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex]; + int linkHashCode = linkInfo.hashCode; + + //Debug.Log(TMP_TextUtilities.GetSimpleHashCode("id_02")); + + switch (linkHashCode) + { + case 291445: // id_01 + if (m_LinkObject01 == null) + m_LinkObject01 = Instantiate(Link_01_Prefab); + else + { + m_LinkObject01.gameObject.SetActive(true); + } + + break; + case 291446: // id_02 + break; + + } + + // Example of how to modify vertex attributes like colors + #region Vertex Attribute Modification Example + UIVertex[] uiVertices = m_TextMeshPro.textInfo.meshInfo.uiVertices; + + Color32 c = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255); + for (int i = 0; i < linkInfo.characterCount; i++) + { + TMP_CharacterInfo cInfo = m_TextMeshPro.textInfo.characterInfo[linkInfo.firstCharacterIndex + i]; + + if (!cInfo.isVisible) continue; // Skip invisible characters. + + int vertexIndex = cInfo.vertexIndex; + + uiVertices[vertexIndex + 0].color = c; + uiVertices[vertexIndex + 1].color = c; + uiVertices[vertexIndex + 2].color = c; + uiVertices[vertexIndex + 3].color = c; + } + + m_TextMeshPro.canvasRenderer.SetVertices(uiVertices, uiVertices.Length); + #endregion + } + */ + #endregion + } + + + public void OnPointerUp(PointerEventData eventData) + { + //Debug.Log("OnPointerUp()"); + } + + + void RestoreCachedVertexAttributes(int index) + { + if (index == -1 || index > m_TextMeshPro.textInfo.characterCount - 1) return; + + // Get the index of the material / sub text object used by this character. + int materialIndex = m_TextMeshPro.textInfo.characterInfo[index].materialReferenceIndex; + + // Get the index of the first vertex of the selected character. + int vertexIndex = m_TextMeshPro.textInfo.characterInfo[index].vertexIndex; + + // Restore Vertices + // Get a reference to the cached / original vertices. + Vector3[] src_vertices = m_cachedMeshInfoVertexData[materialIndex].vertices; + + // Get a reference to the vertices that we need to replace. + Vector3[] dst_vertices = m_TextMeshPro.textInfo.meshInfo[materialIndex].vertices; + + // Restore / Copy vertices from source to destination + dst_vertices[vertexIndex + 0] = src_vertices[vertexIndex + 0]; + dst_vertices[vertexIndex + 1] = src_vertices[vertexIndex + 1]; + dst_vertices[vertexIndex + 2] = src_vertices[vertexIndex + 2]; + dst_vertices[vertexIndex + 3] = src_vertices[vertexIndex + 3]; + + // Restore Vertex Colors + // Get a reference to the vertex colors we need to replace. + Color32[] dst_colors = m_TextMeshPro.textInfo.meshInfo[materialIndex].colors32; + + // Get a reference to the cached / original vertex colors. + Color32[] src_colors = m_cachedMeshInfoVertexData[materialIndex].colors32; + + // Copy the vertex colors from source to destination. + dst_colors[vertexIndex + 0] = src_colors[vertexIndex + 0]; + dst_colors[vertexIndex + 1] = src_colors[vertexIndex + 1]; + dst_colors[vertexIndex + 2] = src_colors[vertexIndex + 2]; + dst_colors[vertexIndex + 3] = src_colors[vertexIndex + 3]; + + // Restore UV0S + // UVS0 + Vector4[] src_uv0s = m_cachedMeshInfoVertexData[materialIndex].uvs0; + Vector4[] dst_uv0s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs0; + dst_uv0s[vertexIndex + 0] = src_uv0s[vertexIndex + 0]; + dst_uv0s[vertexIndex + 1] = src_uv0s[vertexIndex + 1]; + dst_uv0s[vertexIndex + 2] = src_uv0s[vertexIndex + 2]; + dst_uv0s[vertexIndex + 3] = src_uv0s[vertexIndex + 3]; + + // UVS2 + Vector2[] src_uv2s = m_cachedMeshInfoVertexData[materialIndex].uvs2; + Vector2[] dst_uv2s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs2; + dst_uv2s[vertexIndex + 0] = src_uv2s[vertexIndex + 0]; + dst_uv2s[vertexIndex + 1] = src_uv2s[vertexIndex + 1]; + dst_uv2s[vertexIndex + 2] = src_uv2s[vertexIndex + 2]; + dst_uv2s[vertexIndex + 3] = src_uv2s[vertexIndex + 3]; + + + // Restore last vertex attribute as we swapped it as well + int lastIndex = (src_vertices.Length / 4 - 1) * 4; + + // Vertices + dst_vertices[lastIndex + 0] = src_vertices[lastIndex + 0]; + dst_vertices[lastIndex + 1] = src_vertices[lastIndex + 1]; + dst_vertices[lastIndex + 2] = src_vertices[lastIndex + 2]; + dst_vertices[lastIndex + 3] = src_vertices[lastIndex + 3]; + + // Vertex Colors + src_colors = m_cachedMeshInfoVertexData[materialIndex].colors32; + dst_colors = m_TextMeshPro.textInfo.meshInfo[materialIndex].colors32; + dst_colors[lastIndex + 0] = src_colors[lastIndex + 0]; + dst_colors[lastIndex + 1] = src_colors[lastIndex + 1]; + dst_colors[lastIndex + 2] = src_colors[lastIndex + 2]; + dst_colors[lastIndex + 3] = src_colors[lastIndex + 3]; + + // UVS0 + src_uv0s = m_cachedMeshInfoVertexData[materialIndex].uvs0; + dst_uv0s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs0; + dst_uv0s[lastIndex + 0] = src_uv0s[lastIndex + 0]; + dst_uv0s[lastIndex + 1] = src_uv0s[lastIndex + 1]; + dst_uv0s[lastIndex + 2] = src_uv0s[lastIndex + 2]; + dst_uv0s[lastIndex + 3] = src_uv0s[lastIndex + 3]; + + // UVS2 + src_uv2s = m_cachedMeshInfoVertexData[materialIndex].uvs2; + dst_uv2s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs2; + dst_uv2s[lastIndex + 0] = src_uv2s[lastIndex + 0]; + dst_uv2s[lastIndex + 1] = src_uv2s[lastIndex + 1]; + dst_uv2s[lastIndex + 2] = src_uv2s[lastIndex + 2]; + dst_uv2s[lastIndex + 3] = src_uv2s[lastIndex + 3]; + + // Need to update the appropriate + m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All); + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_B.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_B.cs.meta new file mode 100644 index 0000000..0fc3741 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextSelector_B.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: a05dcd8be7ec4ccbb35c26219884aa37 +timeCreated: 1435531209 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: + - TextPopup_Prefab_01: {fileID: 22450954, guid: b06f0e6c1dfa4356ac918da1bb32c603, + type: 2} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_UiFrameRateCounter.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_UiFrameRateCounter.cs new file mode 100644 index 0000000..4de16fe --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_UiFrameRateCounter.cs @@ -0,0 +1,125 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class TMP_UiFrameRateCounter : MonoBehaviour + { + public float UpdateInterval = 5.0f; + private float m_LastInterval = 0; + private int m_Frames = 0; + + public enum FpsCounterAnchorPositions { TopLeft, BottomLeft, TopRight, BottomRight }; + + public FpsCounterAnchorPositions AnchorPosition = FpsCounterAnchorPositions.TopRight; + + private string htmlColorTag; + private const string fpsLabel = "{0:2} <#8080ff>FPS \n<#FF8000>{1:2} <#8080ff>MS"; + + private TextMeshProUGUI m_TextMeshPro; + private RectTransform m_frameCounter_transform; + + private FpsCounterAnchorPositions last_AnchorPosition; + + void Awake() + { + if (!enabled) + return; + + Application.targetFrameRate = 1000; + + GameObject frameCounter = new GameObject("Frame Counter"); + m_frameCounter_transform = frameCounter.AddComponent(); + + m_frameCounter_transform.SetParent(this.transform, false); + + m_TextMeshPro = frameCounter.AddComponent(); + m_TextMeshPro.font = Resources.Load("Fonts & Materials/LiberationSans SDF"); + m_TextMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/LiberationSans SDF - Overlay"); + + m_TextMeshPro.textWrappingMode = TextWrappingModes.NoWrap; + m_TextMeshPro.fontSize = 36; + + m_TextMeshPro.isOverlay = true; + + Set_FrameCounter_Position(AnchorPosition); + last_AnchorPosition = AnchorPosition; + } + + + void Start() + { + m_LastInterval = Time.realtimeSinceStartup; + m_Frames = 0; + } + + + void Update() + { + if (AnchorPosition != last_AnchorPosition) + Set_FrameCounter_Position(AnchorPosition); + + last_AnchorPosition = AnchorPosition; + + m_Frames += 1; + float timeNow = Time.realtimeSinceStartup; + + if (timeNow > m_LastInterval + UpdateInterval) + { + // display two fractional digits (f2 format) + float fps = m_Frames / (timeNow - m_LastInterval); + float ms = 1000.0f / Mathf.Max(fps, 0.00001f); + + if (fps < 30) + htmlColorTag = ""; + else if (fps < 10) + htmlColorTag = ""; + else + htmlColorTag = ""; + + m_TextMeshPro.SetText(htmlColorTag + fpsLabel, fps, ms); + + m_Frames = 0; + m_LastInterval = timeNow; + } + } + + + void Set_FrameCounter_Position(FpsCounterAnchorPositions anchor_position) + { + switch (anchor_position) + { + case FpsCounterAnchorPositions.TopLeft: + m_TextMeshPro.alignment = TextAlignmentOptions.TopLeft; + m_frameCounter_transform.pivot = new Vector2(0, 1); + m_frameCounter_transform.anchorMin = new Vector2(0.01f, 0.99f); + m_frameCounter_transform.anchorMax = new Vector2(0.01f, 0.99f); + m_frameCounter_transform.anchoredPosition = new Vector2(0, 1); + break; + case FpsCounterAnchorPositions.BottomLeft: + m_TextMeshPro.alignment = TextAlignmentOptions.BottomLeft; + m_frameCounter_transform.pivot = new Vector2(0, 0); + m_frameCounter_transform.anchorMin = new Vector2(0.01f, 0.01f); + m_frameCounter_transform.anchorMax = new Vector2(0.01f, 0.01f); + m_frameCounter_transform.anchoredPosition = new Vector2(0, 0); + break; + case FpsCounterAnchorPositions.TopRight: + m_TextMeshPro.alignment = TextAlignmentOptions.TopRight; + m_frameCounter_transform.pivot = new Vector2(1, 1); + m_frameCounter_transform.anchorMin = new Vector2(0.99f, 0.99f); + m_frameCounter_transform.anchorMax = new Vector2(0.99f, 0.99f); + m_frameCounter_transform.anchoredPosition = new Vector2(1, 1); + break; + case FpsCounterAnchorPositions.BottomRight: + m_TextMeshPro.alignment = TextAlignmentOptions.BottomRight; + m_frameCounter_transform.pivot = new Vector2(1, 0); + m_frameCounter_transform.anchorMin = new Vector2(0.99f, 0.01f); + m_frameCounter_transform.anchorMax = new Vector2(0.99f, 0.01f); + m_frameCounter_transform.anchoredPosition = new Vector2(1, 0); + break; + } + } + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_UiFrameRateCounter.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_UiFrameRateCounter.cs.meta new file mode 100644 index 0000000..baad0f6 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_UiFrameRateCounter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 24b0dc2d1d494adbbec1f4db26b4cf83 +timeCreated: 1448607572 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMPro_InstructionOverlay.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMPro_InstructionOverlay.cs new file mode 100644 index 0000000..2367dcf --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMPro_InstructionOverlay.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class TMPro_InstructionOverlay : MonoBehaviour + { + + public enum FpsCounterAnchorPositions { TopLeft, BottomLeft, TopRight, BottomRight }; + + public FpsCounterAnchorPositions AnchorPosition = FpsCounterAnchorPositions.BottomLeft; + + private const string instructions = "Camera Control - <#ffff00>Shift + RMB\nZoom - <#ffff00>Mouse wheel."; + + private TextMeshPro m_TextMeshPro; + private TextContainer m_textContainer; + private Transform m_frameCounter_transform; + private Camera m_camera; + + //private FpsCounterAnchorPositions last_AnchorPosition; + + void Awake() + { + if (!enabled) + return; + + m_camera = Camera.main; + + GameObject frameCounter = new GameObject("Frame Counter"); + m_frameCounter_transform = frameCounter.transform; + m_frameCounter_transform.parent = m_camera.transform; + m_frameCounter_transform.localRotation = Quaternion.identity; + + + m_TextMeshPro = frameCounter.AddComponent(); + m_TextMeshPro.font = Resources.Load("Fonts & Materials/LiberationSans SDF"); + m_TextMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/LiberationSans SDF - Overlay"); + + m_TextMeshPro.fontSize = 30; + + m_TextMeshPro.isOverlay = true; + m_textContainer = frameCounter.GetComponent(); + + Set_FrameCounter_Position(AnchorPosition); + //last_AnchorPosition = AnchorPosition; + + m_TextMeshPro.text = instructions; + + } + + + + + void Set_FrameCounter_Position(FpsCounterAnchorPositions anchor_position) + { + + switch (anchor_position) + { + case FpsCounterAnchorPositions.TopLeft: + //m_TextMeshPro.anchor = AnchorPositions.TopLeft; + m_textContainer.anchorPosition = TextContainerAnchors.TopLeft; + m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(0, 1, 100.0f)); + break; + case FpsCounterAnchorPositions.BottomLeft: + //m_TextMeshPro.anchor = AnchorPositions.BottomLeft; + m_textContainer.anchorPosition = TextContainerAnchors.BottomLeft; + m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(0, 0, 100.0f)); + break; + case FpsCounterAnchorPositions.TopRight: + //m_TextMeshPro.anchor = AnchorPositions.TopRight; + m_textContainer.anchorPosition = TextContainerAnchors.TopRight; + m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(1, 1, 100.0f)); + break; + case FpsCounterAnchorPositions.BottomRight: + //m_TextMeshPro.anchor = AnchorPositions.BottomRight; + m_textContainer.anchorPosition = TextContainerAnchors.BottomRight; + m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(1, 0, 100.0f)); + break; + } + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TMPro_InstructionOverlay.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMPro_InstructionOverlay.cs.meta new file mode 100644 index 0000000..d0e5e2c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMPro_InstructionOverlay.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: c3c1afeda5e545e0b19add5373896d2e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TeleType.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TeleType.cs new file mode 100644 index 0000000..7130cfc --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TeleType.cs @@ -0,0 +1,83 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class TeleType : MonoBehaviour + { + + + //[Range(0, 100)] + //public int RevealSpeed = 50; + + private string label01 = "Example of using <#ffa000>Graphics Inline with Text in TextMesh<#40a0ff>Pro and Unity"; + private string label02 = "Example of using <#ffa000>Graphics Inline with Text in TextMesh<#40a0ff>Pro and Unity"; + + + private TMP_Text m_textMeshPro; + + + void Awake() + { + // Get Reference to TextMeshPro Component + m_textMeshPro = GetComponent(); + m_textMeshPro.text = label01; + m_textMeshPro.textWrappingMode = TextWrappingModes.Normal; + m_textMeshPro.alignment = TextAlignmentOptions.Top; + + + + //if (GetComponentInParent(typeof(Canvas)) as Canvas == null) + //{ + // GameObject canvas = new GameObject("Canvas", typeof(Canvas)); + // gameObject.transform.SetParent(canvas.transform); + // canvas.GetComponent().renderMode = RenderMode.ScreenSpaceOverlay; + + // // Set RectTransform Size + // gameObject.GetComponent().sizeDelta = new Vector2(500, 300); + // m_textMeshPro.fontSize = 48; + //} + + + } + + + IEnumerator Start() + { + + // Force and update of the mesh to get valid information. + m_textMeshPro.ForceMeshUpdate(); + + + int totalVisibleCharacters = m_textMeshPro.textInfo.characterCount; // Get # of Visible Character in text object + int counter = 0; + int visibleCount = 0; + + while (true) + { + visibleCount = counter % (totalVisibleCharacters + 1); + + m_textMeshPro.maxVisibleCharacters = visibleCount; // How many characters should TextMeshPro display? + + // Once the last character has been revealed, wait 1.0 second and start over. + if (visibleCount >= totalVisibleCharacters) + { + yield return new WaitForSeconds(1.0f); + m_textMeshPro.text = label02; + yield return new WaitForSeconds(1.0f); + m_textMeshPro.text = label01; + yield return new WaitForSeconds(1.0f); + } + + counter += 1; + + yield return new WaitForSeconds(0.05f); + } + + //Debug.Log("Done revealing the text."); + } + + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TeleType.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TeleType.cs.meta new file mode 100644 index 0000000..562609b --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TeleType.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: e32c266ee6204b21a427753cb0694c81 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TextConsoleSimulator.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextConsoleSimulator.cs new file mode 100644 index 0000000..883990e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextConsoleSimulator.cs @@ -0,0 +1,121 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + public class TextConsoleSimulator : MonoBehaviour + { + private TMP_Text m_TextComponent; + private bool hasTextChanged; + + void Awake() + { + m_TextComponent = gameObject.GetComponent(); + } + + + void Start() + { + StartCoroutine(RevealCharacters(m_TextComponent)); + //StartCoroutine(RevealWords(m_TextComponent)); + } + + + void OnEnable() + { + // Subscribe to event fired when text object has been regenerated. + TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED); + } + + void OnDisable() + { + TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED); + } + + + // Event received when the text object has changed. + void ON_TEXT_CHANGED(Object obj) + { + hasTextChanged = true; + } + + + /// + /// Method revealing the text one character at a time. + /// + /// + IEnumerator RevealCharacters(TMP_Text textComponent) + { + textComponent.ForceMeshUpdate(); + + TMP_TextInfo textInfo = textComponent.textInfo; + + int totalVisibleCharacters = textInfo.characterCount; // Get # of Visible Character in text object + int visibleCount = 0; + + while (true) + { + if (hasTextChanged) + { + totalVisibleCharacters = textInfo.characterCount; // Update visible character count. + hasTextChanged = false; + } + + if (visibleCount > totalVisibleCharacters) + { + yield return new WaitForSeconds(1.0f); + visibleCount = 0; + } + + textComponent.maxVisibleCharacters = visibleCount; // How many characters should TextMeshPro display? + + visibleCount += 1; + + yield return null; + } + } + + + /// + /// Method revealing the text one word at a time. + /// + /// + IEnumerator RevealWords(TMP_Text textComponent) + { + textComponent.ForceMeshUpdate(); + + int totalWordCount = textComponent.textInfo.wordCount; + int totalVisibleCharacters = textComponent.textInfo.characterCount; // Get # of Visible Character in text object + int counter = 0; + int currentWord = 0; + int visibleCount = 0; + + while (true) + { + currentWord = counter % (totalWordCount + 1); + + // Get last character index for the current word. + if (currentWord == 0) // Display no words. + visibleCount = 0; + else if (currentWord < totalWordCount) // Display all other words with the exception of the last one. + visibleCount = textComponent.textInfo.wordInfo[currentWord - 1].lastCharacterIndex + 1; + else if (currentWord == totalWordCount) // Display last word and all remaining characters. + visibleCount = totalVisibleCharacters; + + textComponent.maxVisibleCharacters = visibleCount; // How many characters should TextMeshPro display? + + // Once the last character has been revealed, wait 1.0 second and start over. + if (visibleCount >= totalVisibleCharacters) + { + yield return new WaitForSeconds(1.0f); + } + + counter += 1; + + yield return new WaitForSeconds(0.1f); + } + } + + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TextConsoleSimulator.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextConsoleSimulator.cs.meta new file mode 100644 index 0000000..3d83e76 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextConsoleSimulator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 43bcd35a1c0c40ccb6d472893fe2093f +timeCreated: 1435298333 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshProFloatingText.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshProFloatingText.cs new file mode 100644 index 0000000..a8872f8 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshProFloatingText.cs @@ -0,0 +1,223 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class TextMeshProFloatingText : MonoBehaviour + { + public Font TheFont; + + private GameObject m_floatingText; + private TextMeshPro m_textMeshPro; + private TextMesh m_textMesh; + + private Transform m_transform; + private Transform m_floatingText_Transform; + private Transform m_cameraTransform; + + Vector3 lastPOS = Vector3.zero; + Quaternion lastRotation = Quaternion.identity; + + public int SpawnType; + public bool IsTextObjectScaleStatic; + + //private int m_frame = 0; + + static WaitForEndOfFrame k_WaitForEndOfFrame = new WaitForEndOfFrame(); + static WaitForSeconds[] k_WaitForSecondsRandom = new WaitForSeconds[] + { + new WaitForSeconds(0.05f), new WaitForSeconds(0.1f), new WaitForSeconds(0.15f), new WaitForSeconds(0.2f), new WaitForSeconds(0.25f), + new WaitForSeconds(0.3f), new WaitForSeconds(0.35f), new WaitForSeconds(0.4f), new WaitForSeconds(0.45f), new WaitForSeconds(0.5f), + new WaitForSeconds(0.55f), new WaitForSeconds(0.6f), new WaitForSeconds(0.65f), new WaitForSeconds(0.7f), new WaitForSeconds(0.75f), + new WaitForSeconds(0.8f), new WaitForSeconds(0.85f), new WaitForSeconds(0.9f), new WaitForSeconds(0.95f), new WaitForSeconds(1.0f), + }; + + void Awake() + { + m_transform = transform; + m_floatingText = new GameObject(this.name + " floating text"); + + // Reference to Transform is lost when TMP component is added since it replaces it by a RectTransform. + //m_floatingText_Transform = m_floatingText.transform; + //m_floatingText_Transform.position = m_transform.position + new Vector3(0, 15f, 0); + + m_cameraTransform = Camera.main.transform; + } + + void Start() + { + if (SpawnType == 0) + { + // TextMesh Pro Implementation + m_textMeshPro = m_floatingText.AddComponent(); + m_textMeshPro.rectTransform.sizeDelta = new Vector2(3, 3); + + m_floatingText_Transform = m_floatingText.transform; + m_floatingText_Transform.position = m_transform.position + new Vector3(0, 15f, 0); + + //m_textMeshPro.fontAsset = Resources.Load("Fonts & Materials/JOKERMAN SDF", typeof(TextMeshProFont)) as TextMeshProFont; // User should only provide a string to the resource. + //m_textMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/LiberationSans SDF", typeof(Material)) as Material; + + m_textMeshPro.alignment = TextAlignmentOptions.Center; + m_textMeshPro.color = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255); + m_textMeshPro.fontSize = 24; + //m_textMeshPro.enableExtraPadding = true; + //m_textMeshPro.enableShadows = false; + m_textMeshPro.fontFeatures.Clear(); + m_textMeshPro.text = string.Empty; + m_textMeshPro.isTextObjectScaleStatic = IsTextObjectScaleStatic; + + StartCoroutine(DisplayTextMeshProFloatingText()); + } + else if (SpawnType == 1) + { + //Debug.Log("Spawning TextMesh Objects."); + + m_floatingText_Transform = m_floatingText.transform; + m_floatingText_Transform.position = m_transform.position + new Vector3(0, 15f, 0); + + m_textMesh = m_floatingText.AddComponent(); + m_textMesh.font = Resources.Load("Fonts/ARIAL"); + m_textMesh.GetComponent().sharedMaterial = m_textMesh.font.material; + m_textMesh.color = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255); + m_textMesh.anchor = TextAnchor.LowerCenter; + m_textMesh.fontSize = 24; + + StartCoroutine(DisplayTextMeshFloatingText()); + } + else if (SpawnType == 2) + { + + } + + } + + + //void Update() + //{ + // if (SpawnType == 0) + // { + // m_textMeshPro.SetText("{0}", m_frame); + // } + // else + // { + // m_textMesh.text = m_frame.ToString(); + // } + // m_frame = (m_frame + 1) % 1000; + + //} + + + public IEnumerator DisplayTextMeshProFloatingText() + { + float CountDuration = 2.0f; // How long is the countdown alive. + float starting_Count = Random.Range(5f, 20f); // At what number is the counter starting at. + float current_Count = starting_Count; + + Vector3 start_pos = m_floatingText_Transform.position; + Color32 start_color = m_textMeshPro.color; + float alpha = 255; + int int_counter = 0; + + + float fadeDuration = 3 / starting_Count * CountDuration; + + while (current_Count > 0) + { + current_Count -= (Time.deltaTime / CountDuration) * starting_Count; + + if (current_Count <= 3) + { + //Debug.Log("Fading Counter ... " + current_Count.ToString("f2")); + alpha = Mathf.Clamp(alpha - (Time.deltaTime / fadeDuration) * 255, 0, 255); + } + + int_counter = (int)current_Count; + m_textMeshPro.text = int_counter.ToString(); + //m_textMeshPro.SetText("{0}", (int)current_Count); + + m_textMeshPro.color = new Color32(start_color.r, start_color.g, start_color.b, (byte)alpha); + + // Move the floating text upward each update + m_floatingText_Transform.position += new Vector3(0, starting_Count * Time.deltaTime, 0); + + // Align floating text perpendicular to Camera. + if (!lastPOS.Compare(m_cameraTransform.position, 1000) || !lastRotation.Compare(m_cameraTransform.rotation, 1000)) + { + lastPOS = m_cameraTransform.position; + lastRotation = m_cameraTransform.rotation; + m_floatingText_Transform.rotation = lastRotation; + Vector3 dir = m_transform.position - lastPOS; + m_transform.forward = new Vector3(dir.x, 0, dir.z); + } + + yield return k_WaitForEndOfFrame; + } + + //Debug.Log("Done Counting down."); + + yield return k_WaitForSecondsRandom[Random.Range(0, 19)]; + + m_floatingText_Transform.position = start_pos; + + StartCoroutine(DisplayTextMeshProFloatingText()); + } + + + public IEnumerator DisplayTextMeshFloatingText() + { + float CountDuration = 2.0f; // How long is the countdown alive. + float starting_Count = Random.Range(5f, 20f); // At what number is the counter starting at. + float current_Count = starting_Count; + + Vector3 start_pos = m_floatingText_Transform.position; + Color32 start_color = m_textMesh.color; + float alpha = 255; + int int_counter = 0; + + float fadeDuration = 3 / starting_Count * CountDuration; + + while (current_Count > 0) + { + current_Count -= (Time.deltaTime / CountDuration) * starting_Count; + + if (current_Count <= 3) + { + //Debug.Log("Fading Counter ... " + current_Count.ToString("f2")); + alpha = Mathf.Clamp(alpha - (Time.deltaTime / fadeDuration) * 255, 0, 255); + } + + int_counter = (int)current_Count; + m_textMesh.text = int_counter.ToString(); + //Debug.Log("Current Count:" + current_Count.ToString("f2")); + + m_textMesh.color = new Color32(start_color.r, start_color.g, start_color.b, (byte)alpha); + + // Move the floating text upward each update + m_floatingText_Transform.position += new Vector3(0, starting_Count * Time.deltaTime, 0); + + // Align floating text perpendicular to Camera. + if (!lastPOS.Compare(m_cameraTransform.position, 1000) || !lastRotation.Compare(m_cameraTransform.rotation, 1000)) + { + lastPOS = m_cameraTransform.position; + lastRotation = m_cameraTransform.rotation; + m_floatingText_Transform.rotation = lastRotation; + Vector3 dir = m_transform.position - lastPOS; + m_transform.forward = new Vector3(dir.x, 0, dir.z); + } + + yield return k_WaitForEndOfFrame; + } + + //Debug.Log("Done Counting down."); + + yield return k_WaitForSecondsRandom[Random.Range(0, 20)]; + + m_floatingText_Transform.position = start_pos; + + StartCoroutine(DisplayTextMeshFloatingText()); + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshProFloatingText.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshProFloatingText.cs.meta new file mode 100644 index 0000000..da60e2f --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshProFloatingText.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4d4c76e63944cba8c7d00f56334b98c +MonoImporter: + serializedVersion: 2 + defaultReferences: + - TheFont: {instanceID: 0} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshSpawner.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshSpawner.cs new file mode 100644 index 0000000..0aa450d --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshSpawner.cs @@ -0,0 +1,79 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class TextMeshSpawner : MonoBehaviour + { + + public int SpawnType = 0; + public int NumberOfNPC = 12; + + public Font TheFont; + + private TextMeshProFloatingText floatingText_Script; + + void Awake() + { + + } + + void Start() + { + + for (int i = 0; i < NumberOfNPC; i++) + { + if (SpawnType == 0) + { + // TextMesh Pro Implementation + //go.transform.localScale = new Vector3(2, 2, 2); + GameObject go = new GameObject(); //"NPC " + i); + go.transform.position = new Vector3(Random.Range(-95f, 95f), 0.5f, Random.Range(-95f, 95f)); + + //go.transform.position = new Vector3(0, 1.01f, 0); + //go.renderer.castShadows = false; + //go.renderer.receiveShadows = false; + //go.transform.rotation = Quaternion.Euler(0, Random.Range(0, 360), 0); + + TextMeshPro textMeshPro = go.AddComponent(); + //textMeshPro.FontAsset = Resources.Load("Fonts & Materials/LiberationSans SDF", typeof(TextMeshProFont)) as TextMeshProFont; + //textMeshPro.anchor = AnchorPositions.Bottom; + textMeshPro.fontSize = 96; + + textMeshPro.text = "!"; + textMeshPro.color = new Color32(255, 255, 0, 255); + //textMeshPro.Text = "!"; + + + // Spawn Floating Text + floatingText_Script = go.AddComponent(); + floatingText_Script.SpawnType = 0; + } + else + { + // TextMesh Implementation + GameObject go = new GameObject(); //"NPC " + i); + go.transform.position = new Vector3(Random.Range(-95f, 95f), 0.5f, Random.Range(-95f, 95f)); + + //go.transform.position = new Vector3(0, 1.01f, 0); + + TextMesh textMesh = go.AddComponent(); + textMesh.GetComponent().sharedMaterial = TheFont.material; + textMesh.font = TheFont; + textMesh.anchor = TextAnchor.LowerCenter; + textMesh.fontSize = 96; + + textMesh.color = new Color32(255, 255, 0, 255); + textMesh.text = "!"; + + // Spawn Floating Text + floatingText_Script = go.AddComponent(); + floatingText_Script.SpawnType = 1; + } + } + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshSpawner.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshSpawner.cs.meta new file mode 100644 index 0000000..dd5a8cb --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TextMeshSpawner.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 76c11bbcfddf44e0ba17d6c2751c8d84 +MonoImporter: + serializedVersion: 2 + defaultReferences: + - TheFont: {instanceID: 0} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexColorCycler.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexColorCycler.cs new file mode 100644 index 0000000..ac66647 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexColorCycler.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class VertexColorCycler : MonoBehaviour + { + + private TMP_Text m_TextComponent; + + void Awake() + { + m_TextComponent = GetComponent(); + } + + + void Start() + { + StartCoroutine(AnimateVertexColors()); + } + + + /// + /// Method to animate vertex colors of a TMP Text object. + /// + /// + IEnumerator AnimateVertexColors() + { + // Force the text object to update right away so we can have geometry to modify right from the start. + m_TextComponent.ForceMeshUpdate(); + + TMP_TextInfo textInfo = m_TextComponent.textInfo; + int currentCharacter = 0; + + Color32[] newVertexColors; + Color32 c0 = m_TextComponent.color; + + while (true) + { + int characterCount = textInfo.characterCount; + + // If No Characters then just yield and wait for some text to be added + if (characterCount == 0) + { + yield return new WaitForSeconds(0.25f); + continue; + } + + // Get the index of the material used by the current character. + int materialIndex = textInfo.characterInfo[currentCharacter].materialReferenceIndex; + + // Get the vertex colors of the mesh used by this text element (character or sprite). + newVertexColors = textInfo.meshInfo[materialIndex].colors32; + + // Get the index of the first vertex used by this text element. + int vertexIndex = textInfo.characterInfo[currentCharacter].vertexIndex; + + // Only change the vertex color if the text element is visible. + if (textInfo.characterInfo[currentCharacter].isVisible) + { + c0 = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255); + + newVertexColors[vertexIndex + 0] = c0; + newVertexColors[vertexIndex + 1] = c0; + newVertexColors[vertexIndex + 2] = c0; + newVertexColors[vertexIndex + 3] = c0; + + // New function which pushes (all) updated vertex data to the appropriate meshes when using either the Mesh Renderer or CanvasRenderer. + m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32); + + // This last process could be done to only update the vertex data that has changed as opposed to all of the vertex data but it would require extra steps and knowing what type of renderer is used. + // These extra steps would be a performance optimization but it is unlikely that such optimization will be necessary. + } + + currentCharacter = (currentCharacter + 1) % characterCount; + + yield return new WaitForSeconds(0.05f); + } + } + + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexColorCycler.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexColorCycler.cs.meta new file mode 100644 index 0000000..7ba50b8 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexColorCycler.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 91b8ba3d52e041fab2d0e0f169855539 +timeCreated: 1457047157 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexJitter.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexJitter.cs new file mode 100644 index 0000000..7ed8230 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexJitter.cs @@ -0,0 +1,175 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class VertexJitter : MonoBehaviour + { + + public float AngleMultiplier = 1.0f; + public float SpeedMultiplier = 1.0f; + public float CurveScale = 1.0f; + + private TMP_Text m_TextComponent; + private bool hasTextChanged; + + /// + /// Structure to hold pre-computed animation data. + /// + private struct VertexAnim + { + public float angleRange; + public float angle; + public float speed; + } + + void Awake() + { + m_TextComponent = GetComponent(); + } + + void OnEnable() + { + // Subscribe to event fired when text object has been regenerated. + TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED); + } + + void OnDisable() + { + TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED); + } + + + void Start() + { + StartCoroutine(AnimateVertexColors()); + } + + + void ON_TEXT_CHANGED(Object obj) + { + if (obj == m_TextComponent) + hasTextChanged = true; + } + + /// + /// Method to animate vertex colors of a TMP Text object. + /// + /// + IEnumerator AnimateVertexColors() + { + + // We force an update of the text object since it would only be updated at the end of the frame. Ie. before this code is executed on the first frame. + // Alternatively, we could yield and wait until the end of the frame when the text object will be generated. + m_TextComponent.ForceMeshUpdate(); + + TMP_TextInfo textInfo = m_TextComponent.textInfo; + + Matrix4x4 matrix; + + int loopCount = 0; + hasTextChanged = true; + + // Create an Array which contains pre-computed Angle Ranges and Speeds for a bunch of characters. + VertexAnim[] vertexAnim = new VertexAnim[1024]; + for (int i = 0; i < 1024; i++) + { + vertexAnim[i].angleRange = Random.Range(10f, 25f); + vertexAnim[i].speed = Random.Range(1f, 3f); + } + + // Cache the vertex data of the text object as the Jitter FX is applied to the original position of the characters. + TMP_MeshInfo[] cachedMeshInfo = textInfo.CopyMeshInfoVertexData(); + + while (true) + { + // Get new copy of vertex data if the text has changed. + if (hasTextChanged) + { + // Update the copy of the vertex data for the text object. + cachedMeshInfo = textInfo.CopyMeshInfoVertexData(); + + hasTextChanged = false; + } + + int characterCount = textInfo.characterCount; + + // If No Characters then just yield and wait for some text to be added + if (characterCount == 0) + { + yield return new WaitForSeconds(0.25f); + continue; + } + + + for (int i = 0; i < characterCount; i++) + { + TMP_CharacterInfo charInfo = textInfo.characterInfo[i]; + + // Skip characters that are not visible and thus have no geometry to manipulate. + if (!charInfo.isVisible) + continue; + + // Retrieve the pre-computed animation data for the given character. + VertexAnim vertAnim = vertexAnim[i]; + + // Get the index of the material used by the current character. + int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; + + // Get the index of the first vertex used by this text element. + int vertexIndex = textInfo.characterInfo[i].vertexIndex; + + // Get the cached vertices of the mesh used by this text element (character or sprite). + Vector3[] sourceVertices = cachedMeshInfo[materialIndex].vertices; + + // Determine the center point of each character at the baseline. + //Vector2 charMidBasline = new Vector2((sourceVertices[vertexIndex + 0].x + sourceVertices[vertexIndex + 2].x) / 2, charInfo.baseLine); + // Determine the center point of each character. + Vector2 charMidBasline = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2; + + // Need to translate all 4 vertices of each quad to aligned with middle of character / baseline. + // This is needed so the matrix TRS is applied at the origin for each character. + Vector3 offset = charMidBasline; + + Vector3[] destinationVertices = textInfo.meshInfo[materialIndex].vertices; + + destinationVertices[vertexIndex + 0] = sourceVertices[vertexIndex + 0] - offset; + destinationVertices[vertexIndex + 1] = sourceVertices[vertexIndex + 1] - offset; + destinationVertices[vertexIndex + 2] = sourceVertices[vertexIndex + 2] - offset; + destinationVertices[vertexIndex + 3] = sourceVertices[vertexIndex + 3] - offset; + + vertAnim.angle = Mathf.SmoothStep(-vertAnim.angleRange, vertAnim.angleRange, Mathf.PingPong(loopCount / 25f * vertAnim.speed, 1f)); + Vector3 jitterOffset = new Vector3(Random.Range(-.25f, .25f), Random.Range(-.25f, .25f), 0); + + matrix = Matrix4x4.TRS(jitterOffset * CurveScale, Quaternion.Euler(0, 0, Random.Range(-5f, 5f) * AngleMultiplier), Vector3.one); + + destinationVertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 0]); + destinationVertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 1]); + destinationVertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 2]); + destinationVertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 3]); + + destinationVertices[vertexIndex + 0] += offset; + destinationVertices[vertexIndex + 1] += offset; + destinationVertices[vertexIndex + 2] += offset; + destinationVertices[vertexIndex + 3] += offset; + + vertexAnim[i] = vertAnim; + } + + // Push changes into meshes + for (int i = 0; i < textInfo.meshInfo.Length; i++) + { + textInfo.meshInfo[i].mesh.vertices = textInfo.meshInfo[i].vertices; + m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i); + } + + loopCount += 1; + + yield return new WaitForSeconds(0.1f); + } + } + + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexJitter.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexJitter.cs.meta new file mode 100644 index 0000000..2ba768c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexJitter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2ed57967c52645d390a89dcf8f61ba73 +timeCreated: 1461286718 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeA.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeA.cs new file mode 100644 index 0000000..a4022a5 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeA.cs @@ -0,0 +1,161 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class VertexShakeA : MonoBehaviour + { + + public float AngleMultiplier = 1.0f; + public float SpeedMultiplier = 1.0f; + public float ScaleMultiplier = 1.0f; + public float RotationMultiplier = 1.0f; + + private TMP_Text m_TextComponent; + private bool hasTextChanged; + + + void Awake() + { + m_TextComponent = GetComponent(); + } + + void OnEnable() + { + // Subscribe to event fired when text object has been regenerated. + TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED); + } + + void OnDisable() + { + TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED); + } + + + void Start() + { + StartCoroutine(AnimateVertexColors()); + } + + + void ON_TEXT_CHANGED(Object obj) + { + if (obj = m_TextComponent) + hasTextChanged = true; + } + + /// + /// Method to animate vertex colors of a TMP Text object. + /// + /// + IEnumerator AnimateVertexColors() + { + + // We force an update of the text object since it would only be updated at the end of the frame. Ie. before this code is executed on the first frame. + // Alternatively, we could yield and wait until the end of the frame when the text object will be generated. + m_TextComponent.ForceMeshUpdate(); + + TMP_TextInfo textInfo = m_TextComponent.textInfo; + + Matrix4x4 matrix; + Vector3[][] copyOfVertices = new Vector3[0][]; + + hasTextChanged = true; + + while (true) + { + // Allocate new vertices + if (hasTextChanged) + { + if (copyOfVertices.Length < textInfo.meshInfo.Length) + copyOfVertices = new Vector3[textInfo.meshInfo.Length][]; + + for (int i = 0; i < textInfo.meshInfo.Length; i++) + { + int length = textInfo.meshInfo[i].vertices.Length; + copyOfVertices[i] = new Vector3[length]; + } + + hasTextChanged = false; + } + + int characterCount = textInfo.characterCount; + + // If No Characters then just yield and wait for some text to be added + if (characterCount == 0) + { + yield return new WaitForSeconds(0.25f); + continue; + } + + int lineCount = textInfo.lineCount; + + // Iterate through each line of the text. + for (int i = 0; i < lineCount; i++) + { + + int first = textInfo.lineInfo[i].firstCharacterIndex; + int last = textInfo.lineInfo[i].lastCharacterIndex; + + // Determine the center of each line + Vector3 centerOfLine = (textInfo.characterInfo[first].bottomLeft + textInfo.characterInfo[last].topRight) / 2; + Quaternion rotation = Quaternion.Euler(0, 0, Random.Range(-0.25f, 0.25f) * RotationMultiplier); + + // Iterate through each character of the line. + for (int j = first; j <= last; j++) + { + // Skip characters that are not visible and thus have no geometry to manipulate. + if (!textInfo.characterInfo[j].isVisible) + continue; + + // Get the index of the material used by the current character. + int materialIndex = textInfo.characterInfo[j].materialReferenceIndex; + + // Get the index of the first vertex used by this text element. + int vertexIndex = textInfo.characterInfo[j].vertexIndex; + + // Get the vertices of the mesh used by this text element (character or sprite). + Vector3[] sourceVertices = textInfo.meshInfo[materialIndex].vertices; + + // Need to translate all 4 vertices of each quad to aligned with center of character. + // This is needed so the matrix TRS is applied at the origin for each character. + copyOfVertices[materialIndex][vertexIndex + 0] = sourceVertices[vertexIndex + 0] - centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 1] = sourceVertices[vertexIndex + 1] - centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 2] = sourceVertices[vertexIndex + 2] - centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 3] = sourceVertices[vertexIndex + 3] - centerOfLine; + + // Determine the random scale change for each character. + float randomScale = Random.Range(0.995f - 0.001f * ScaleMultiplier, 1.005f + 0.001f * ScaleMultiplier); + + // Setup the matrix rotation. + matrix = Matrix4x4.TRS(Vector3.one, rotation, Vector3.one * randomScale); + + // Apply the matrix TRS to the individual characters relative to the center of the current line. + copyOfVertices[materialIndex][vertexIndex + 0] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 0]); + copyOfVertices[materialIndex][vertexIndex + 1] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 1]); + copyOfVertices[materialIndex][vertexIndex + 2] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 2]); + copyOfVertices[materialIndex][vertexIndex + 3] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 3]); + + // Revert the translation change. + copyOfVertices[materialIndex][vertexIndex + 0] += centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 1] += centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 2] += centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 3] += centerOfLine; + } + } + + // Push changes into meshes + for (int i = 0; i < textInfo.meshInfo.Length; i++) + { + textInfo.meshInfo[i].mesh.vertices = copyOfVertices[i]; + m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i); + } + + yield return new WaitForSeconds(0.1f); + } + } + + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeA.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeA.cs.meta new file mode 100644 index 0000000..25aceb5 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeA.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f7cfa58e417a46ea8889989684c2522e +timeCreated: 1462089320 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeB.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeB.cs new file mode 100644 index 0000000..fd3b1c4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeB.cs @@ -0,0 +1,185 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class VertexShakeB : MonoBehaviour + { + + public float AngleMultiplier = 1.0f; + public float SpeedMultiplier = 1.0f; + public float CurveScale = 1.0f; + + private TMP_Text m_TextComponent; + private bool hasTextChanged; + + + void Awake() + { + m_TextComponent = GetComponent(); + } + + void OnEnable() + { + // Subscribe to event fired when text object has been regenerated. + TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED); + } + + void OnDisable() + { + TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED); + } + + + void Start() + { + StartCoroutine(AnimateVertexColors()); + } + + + void ON_TEXT_CHANGED(Object obj) + { + if (obj = m_TextComponent) + hasTextChanged = true; + } + + /// + /// Method to animate vertex colors of a TMP Text object. + /// + /// + IEnumerator AnimateVertexColors() + { + + // We force an update of the text object since it would only be updated at the end of the frame. Ie. before this code is executed on the first frame. + // Alternatively, we could yield and wait until the end of the frame when the text object will be generated. + m_TextComponent.ForceMeshUpdate(); + + TMP_TextInfo textInfo = m_TextComponent.textInfo; + + Matrix4x4 matrix; + Vector3[][] copyOfVertices = new Vector3[0][]; + + hasTextChanged = true; + + while (true) + { + // Allocate new vertices + if (hasTextChanged) + { + if (copyOfVertices.Length < textInfo.meshInfo.Length) + copyOfVertices = new Vector3[textInfo.meshInfo.Length][]; + + for (int i = 0; i < textInfo.meshInfo.Length; i++) + { + int length = textInfo.meshInfo[i].vertices.Length; + copyOfVertices[i] = new Vector3[length]; + } + + hasTextChanged = false; + } + + int characterCount = textInfo.characterCount; + + // If No Characters then just yield and wait for some text to be added + if (characterCount == 0) + { + yield return new WaitForSeconds(0.25f); + continue; + } + + int lineCount = textInfo.lineCount; + + // Iterate through each line of the text. + for (int i = 0; i < lineCount; i++) + { + + int first = textInfo.lineInfo[i].firstCharacterIndex; + int last = textInfo.lineInfo[i].lastCharacterIndex; + + // Determine the center of each line + Vector3 centerOfLine = (textInfo.characterInfo[first].bottomLeft + textInfo.characterInfo[last].topRight) / 2; + Quaternion rotation = Quaternion.Euler(0, 0, Random.Range(-0.25f, 0.25f)); + + // Iterate through each character of the line. + for (int j = first; j <= last; j++) + { + // Skip characters that are not visible and thus have no geometry to manipulate. + if (!textInfo.characterInfo[j].isVisible) + continue; + + // Get the index of the material used by the current character. + int materialIndex = textInfo.characterInfo[j].materialReferenceIndex; + + // Get the index of the first vertex used by this text element. + int vertexIndex = textInfo.characterInfo[j].vertexIndex; + + // Get the vertices of the mesh used by this text element (character or sprite). + Vector3[] sourceVertices = textInfo.meshInfo[materialIndex].vertices; + + // Determine the center point of each character at the baseline. + Vector3 charCenter = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2; + + // Need to translate all 4 vertices of each quad to aligned with center of character. + // This is needed so the matrix TRS is applied at the origin for each character. + copyOfVertices[materialIndex][vertexIndex + 0] = sourceVertices[vertexIndex + 0] - charCenter; + copyOfVertices[materialIndex][vertexIndex + 1] = sourceVertices[vertexIndex + 1] - charCenter; + copyOfVertices[materialIndex][vertexIndex + 2] = sourceVertices[vertexIndex + 2] - charCenter; + copyOfVertices[materialIndex][vertexIndex + 3] = sourceVertices[vertexIndex + 3] - charCenter; + + // Determine the random scale change for each character. + float randomScale = Random.Range(0.95f, 1.05f); + + // Setup the matrix for the scale change. + matrix = Matrix4x4.TRS(Vector3.one, Quaternion.identity, Vector3.one * randomScale); + + // Apply the scale change relative to the center of each character. + copyOfVertices[materialIndex][vertexIndex + 0] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 0]); + copyOfVertices[materialIndex][vertexIndex + 1] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 1]); + copyOfVertices[materialIndex][vertexIndex + 2] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 2]); + copyOfVertices[materialIndex][vertexIndex + 3] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 3]); + + // Revert the translation change. + copyOfVertices[materialIndex][vertexIndex + 0] += charCenter; + copyOfVertices[materialIndex][vertexIndex + 1] += charCenter; + copyOfVertices[materialIndex][vertexIndex + 2] += charCenter; + copyOfVertices[materialIndex][vertexIndex + 3] += charCenter; + + // Need to translate all 4 vertices of each quad to aligned with the center of the line. + // This is needed so the matrix TRS is applied from the center of the line. + copyOfVertices[materialIndex][vertexIndex + 0] -= centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 1] -= centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 2] -= centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 3] -= centerOfLine; + + // Setup the matrix rotation. + matrix = Matrix4x4.TRS(Vector3.one, rotation, Vector3.one); + + // Apply the matrix TRS to the individual characters relative to the center of the current line. + copyOfVertices[materialIndex][vertexIndex + 0] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 0]); + copyOfVertices[materialIndex][vertexIndex + 1] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 1]); + copyOfVertices[materialIndex][vertexIndex + 2] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 2]); + copyOfVertices[materialIndex][vertexIndex + 3] = matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 3]); + + // Revert the translation change. + copyOfVertices[materialIndex][vertexIndex + 0] += centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 1] += centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 2] += centerOfLine; + copyOfVertices[materialIndex][vertexIndex + 3] += centerOfLine; + } + } + + // Push changes into meshes + for (int i = 0; i < textInfo.meshInfo.Length; i++) + { + textInfo.meshInfo[i].mesh.vertices = copyOfVertices[i]; + m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i); + } + + yield return new WaitForSeconds(0.1f); + } + } + + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeB.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeB.cs.meta new file mode 100644 index 0000000..f1fcf32 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexShakeB.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e4e0d9ccee5f4950be8979268c9014e0 +timeCreated: 1462093319 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexZoom.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexZoom.cs new file mode 100644 index 0000000..4ca9119 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexZoom.cs @@ -0,0 +1,192 @@ +using UnityEngine; +using System.Linq; +using System.Collections; +using System.Collections.Generic; + + +namespace TMPro.Examples +{ + + public class VertexZoom : MonoBehaviour + { + public float AngleMultiplier = 1.0f; + public float SpeedMultiplier = 1.0f; + public float CurveScale = 1.0f; + + private TMP_Text m_TextComponent; + private bool hasTextChanged; + + + void Awake() + { + m_TextComponent = GetComponent(); + } + + void OnEnable() + { + // Subscribe to event fired when text object has been regenerated. + TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED); + } + + void OnDisable() + { + // UnSubscribe to event fired when text object has been regenerated. + TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED); + } + + + void Start() + { + StartCoroutine(AnimateVertexColors()); + } + + + void ON_TEXT_CHANGED(Object obj) + { + if (obj == m_TextComponent) + hasTextChanged = true; + } + + /// + /// Method to animate vertex colors of a TMP Text object. + /// + /// + IEnumerator AnimateVertexColors() + { + + // We force an update of the text object since it would only be updated at the end of the frame. Ie. before this code is executed on the first frame. + // Alternatively, we could yield and wait until the end of the frame when the text object will be generated. + m_TextComponent.ForceMeshUpdate(); + + TMP_TextInfo textInfo = m_TextComponent.textInfo; + + Matrix4x4 matrix; + TMP_MeshInfo[] cachedMeshInfoVertexData = textInfo.CopyMeshInfoVertexData(); + + // Allocations for sorting of the modified scales + List modifiedCharScale = new List(); + List scaleSortingOrder = new List(); + + hasTextChanged = true; + + while (true) + { + // Allocate new vertices + if (hasTextChanged) + { + // Get updated vertex data + cachedMeshInfoVertexData = textInfo.CopyMeshInfoVertexData(); + + hasTextChanged = false; + } + + int characterCount = textInfo.characterCount; + + // If No Characters then just yield and wait for some text to be added + if (characterCount == 0) + { + yield return new WaitForSeconds(0.25f); + continue; + } + + // Clear list of character scales + modifiedCharScale.Clear(); + scaleSortingOrder.Clear(); + + for (int i = 0; i < characterCount; i++) + { + TMP_CharacterInfo charInfo = textInfo.characterInfo[i]; + + // Skip characters that are not visible and thus have no geometry to manipulate. + if (!charInfo.isVisible) + continue; + + // Get the index of the material used by the current character. + int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; + + // Get the index of the first vertex used by this text element. + int vertexIndex = textInfo.characterInfo[i].vertexIndex; + + // Get the cached vertices of the mesh used by this text element (character or sprite). + Vector3[] sourceVertices = cachedMeshInfoVertexData[materialIndex].vertices; + + // Determine the center point of each character at the baseline. + //Vector2 charMidBasline = new Vector2((sourceVertices[vertexIndex + 0].x + sourceVertices[vertexIndex + 2].x) / 2, charInfo.baseLine); + // Determine the center point of each character. + Vector2 charMidBasline = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2; + + // Need to translate all 4 vertices of each quad to aligned with middle of character / baseline. + // This is needed so the matrix TRS is applied at the origin for each character. + Vector3 offset = charMidBasline; + + Vector3[] destinationVertices = textInfo.meshInfo[materialIndex].vertices; + + destinationVertices[vertexIndex + 0] = sourceVertices[vertexIndex + 0] - offset; + destinationVertices[vertexIndex + 1] = sourceVertices[vertexIndex + 1] - offset; + destinationVertices[vertexIndex + 2] = sourceVertices[vertexIndex + 2] - offset; + destinationVertices[vertexIndex + 3] = sourceVertices[vertexIndex + 3] - offset; + + //Vector3 jitterOffset = new Vector3(Random.Range(-.25f, .25f), Random.Range(-.25f, .25f), 0); + + // Determine the random scale change for each character. + float randomScale = Random.Range(1f, 1.5f); + + // Add modified scale and index + modifiedCharScale.Add(randomScale); + scaleSortingOrder.Add(modifiedCharScale.Count - 1); + + // Setup the matrix for the scale change. + //matrix = Matrix4x4.TRS(jitterOffset, Quaternion.Euler(0, 0, Random.Range(-5f, 5f)), Vector3.one * randomScale); + matrix = Matrix4x4.TRS(new Vector3(0, 0, 0), Quaternion.identity, Vector3.one * randomScale); + + destinationVertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 0]); + destinationVertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 1]); + destinationVertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 2]); + destinationVertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 3]); + + destinationVertices[vertexIndex + 0] += offset; + destinationVertices[vertexIndex + 1] += offset; + destinationVertices[vertexIndex + 2] += offset; + destinationVertices[vertexIndex + 3] += offset; + + // Restore Source UVS which have been modified by the sorting + Vector4[] sourceUVs0 = cachedMeshInfoVertexData[materialIndex].uvs0; + Vector4[] destinationUVs0 = textInfo.meshInfo[materialIndex].uvs0; + + destinationUVs0[vertexIndex + 0] = sourceUVs0[vertexIndex + 0]; + destinationUVs0[vertexIndex + 1] = sourceUVs0[vertexIndex + 1]; + destinationUVs0[vertexIndex + 2] = sourceUVs0[vertexIndex + 2]; + destinationUVs0[vertexIndex + 3] = sourceUVs0[vertexIndex + 3]; + + // Restore Source Vertex Colors + Color32[] sourceColors32 = cachedMeshInfoVertexData[materialIndex].colors32; + Color32[] destinationColors32 = textInfo.meshInfo[materialIndex].colors32; + + destinationColors32[vertexIndex + 0] = sourceColors32[vertexIndex + 0]; + destinationColors32[vertexIndex + 1] = sourceColors32[vertexIndex + 1]; + destinationColors32[vertexIndex + 2] = sourceColors32[vertexIndex + 2]; + destinationColors32[vertexIndex + 3] = sourceColors32[vertexIndex + 3]; + } + + // Push changes into meshes + for (int i = 0; i < textInfo.meshInfo.Length; i++) + { + //// Sort Quads based modified scale + scaleSortingOrder.Sort((a, b) => modifiedCharScale[a].CompareTo(modifiedCharScale[b])); + + textInfo.meshInfo[i].SortGeometry(scaleSortingOrder); + + // Updated modified vertex attributes + textInfo.meshInfo[i].mesh.vertices = textInfo.meshInfo[i].vertices; + textInfo.meshInfo[i].mesh.SetUVs(0, textInfo.meshInfo[i].uvs0); + textInfo.meshInfo[i].mesh.colors32 = textInfo.meshInfo[i].colors32; + + m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i); + } + + yield return new WaitForSeconds(0.1f); + } + } + + } +} \ No newline at end of file diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexZoom.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexZoom.cs.meta new file mode 100644 index 0000000..d9e3f96 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/VertexZoom.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 52ec835d14bd486f900952b77698b7eb +timeCreated: 1466280202 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/WarpTextExample.cs b/Assets/TextMesh Pro/Examples & Extras/Scripts/WarpTextExample.cs new file mode 100644 index 0000000..18dba4c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/WarpTextExample.cs @@ -0,0 +1,144 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class WarpTextExample : MonoBehaviour + { + + private TMP_Text m_TextComponent; + + public AnimationCurve VertexCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.25f, 2.0f), new Keyframe(0.5f, 0), new Keyframe(0.75f, 2.0f), new Keyframe(1, 0f)); + public float AngleMultiplier = 1.0f; + public float SpeedMultiplier = 1.0f; + public float CurveScale = 1.0f; + + void Awake() + { + m_TextComponent = gameObject.GetComponent(); + } + + + void Start() + { + StartCoroutine(WarpText()); + } + + + private AnimationCurve CopyAnimationCurve(AnimationCurve curve) + { + AnimationCurve newCurve = new AnimationCurve(); + + newCurve.keys = curve.keys; + + return newCurve; + } + + + /// + /// Method to curve text along a Unity animation curve. + /// + /// + /// + IEnumerator WarpText() + { + VertexCurve.preWrapMode = WrapMode.Clamp; + VertexCurve.postWrapMode = WrapMode.Clamp; + + //Mesh mesh = m_TextComponent.textInfo.meshInfo[0].mesh; + + Vector3[] vertices; + Matrix4x4 matrix; + + m_TextComponent.havePropertiesChanged = true; // Need to force the TextMeshPro Object to be updated. + CurveScale *= 10; + float old_CurveScale = CurveScale; + AnimationCurve old_curve = CopyAnimationCurve(VertexCurve); + + while (true) + { + if (!m_TextComponent.havePropertiesChanged && old_CurveScale == CurveScale && old_curve.keys[1].value == VertexCurve.keys[1].value) + { + yield return null; + continue; + } + + old_CurveScale = CurveScale; + old_curve = CopyAnimationCurve(VertexCurve); + + m_TextComponent.ForceMeshUpdate(); // Generate the mesh and populate the textInfo with data we can use and manipulate. + + TMP_TextInfo textInfo = m_TextComponent.textInfo; + int characterCount = textInfo.characterCount; + + + if (characterCount == 0) continue; + + //vertices = textInfo.meshInfo[0].vertices; + //int lastVertexIndex = textInfo.characterInfo[characterCount - 1].vertexIndex; + + float boundsMinX = m_TextComponent.bounds.min.x; //textInfo.meshInfo[0].mesh.bounds.min.x; + float boundsMaxX = m_TextComponent.bounds.max.x; //textInfo.meshInfo[0].mesh.bounds.max.x; + + + + for (int i = 0; i < characterCount; i++) + { + if (!textInfo.characterInfo[i].isVisible) + continue; + + int vertexIndex = textInfo.characterInfo[i].vertexIndex; + + // Get the index of the mesh used by this character. + int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; + + vertices = textInfo.meshInfo[materialIndex].vertices; + + // Compute the baseline mid point for each character + Vector3 offsetToMidBaseline = new Vector2((vertices[vertexIndex + 0].x + vertices[vertexIndex + 2].x) / 2, textInfo.characterInfo[i].baseLine); + //float offsetY = VertexCurve.Evaluate((float)i / characterCount + loopCount / 50f); // Random.Range(-0.25f, 0.25f); + + // Apply offset to adjust our pivot point. + vertices[vertexIndex + 0] += -offsetToMidBaseline; + vertices[vertexIndex + 1] += -offsetToMidBaseline; + vertices[vertexIndex + 2] += -offsetToMidBaseline; + vertices[vertexIndex + 3] += -offsetToMidBaseline; + + // Compute the angle of rotation for each character based on the animation curve + float x0 = (offsetToMidBaseline.x - boundsMinX) / (boundsMaxX - boundsMinX); // Character's position relative to the bounds of the mesh. + float x1 = x0 + 0.0001f; + float y0 = VertexCurve.Evaluate(x0) * CurveScale; + float y1 = VertexCurve.Evaluate(x1) * CurveScale; + + Vector3 horizontal = new Vector3(1, 0, 0); + //Vector3 normal = new Vector3(-(y1 - y0), (x1 * (boundsMaxX - boundsMinX) + boundsMinX) - offsetToMidBaseline.x, 0); + Vector3 tangent = new Vector3(x1 * (boundsMaxX - boundsMinX) + boundsMinX, y1) - new Vector3(offsetToMidBaseline.x, y0); + + float dot = Mathf.Acos(Vector3.Dot(horizontal, tangent.normalized)) * 57.2957795f; + Vector3 cross = Vector3.Cross(horizontal, tangent); + float angle = cross.z > 0 ? dot : 360 - dot; + + matrix = Matrix4x4.TRS(new Vector3(0, y0, 0), Quaternion.Euler(0, 0, angle), Vector3.one); + + vertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]); + vertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]); + vertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]); + vertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]); + + vertices[vertexIndex + 0] += offsetToMidBaseline; + vertices[vertexIndex + 1] += offsetToMidBaseline; + vertices[vertexIndex + 2] += offsetToMidBaseline; + vertices[vertexIndex + 3] += offsetToMidBaseline; + } + + + // Upload the mesh with the revised information + m_TextComponent.UpdateVertexData(); + + yield return new WaitForSeconds(0.025f); + } + } + } +} diff --git a/Assets/TextMesh Pro/Examples & Extras/Scripts/WarpTextExample.cs.meta b/Assets/TextMesh Pro/Examples & Extras/Scripts/WarpTextExample.cs.meta new file mode 100644 index 0000000..7b7958a --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/WarpTextExample.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 790744c462254b7ba8038e6ed28b3db2 +timeCreated: 1458801336 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Sprites.meta b/Assets/TextMesh Pro/Examples & Extras/Sprites.meta new file mode 100644 index 0000000..bafd122 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Sprites.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 701e577af2ba48b689972d42efb95456 +folderAsset: yes +timeCreated: 1488176891 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Sprites/Default Sprites.png b/Assets/TextMesh Pro/Examples & Extras/Sprites/Default Sprites.png new file mode 100644 index 0000000..313fd00 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Sprites/Default Sprites.png differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Sprites/Default Sprites.png.meta b/Assets/TextMesh Pro/Examples & Extras/Sprites/Default Sprites.png.meta new file mode 100644 index 0000000..a3f6762 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Sprites/Default Sprites.png.meta @@ -0,0 +1,437 @@ +fileFormatVersion: 2 +guid: a0fc465d6cf04254a2938578735e2383 +TextureImporter: + fileIDToRecycleName: + 21300000: Default Sprite Asset_0 + 21300002: Default Sprite Asset_1 + 21300004: Default Sprite Asset_2 + 21300006: Default Sprite Asset_3 + 21300008: Default Sprite Asset_4 + 21300010: Default Sprite Asset_5 + 21300012: Default Sprite Asset_6 + 21300014: Default Sprite Asset_7 + 21300016: Default Sprite Asset_8 + 21300018: Default Sprite Asset_11 + 21300020: Default Sprite Asset_12 + 21300022: Default Sprite Asset_13 + 21300024: Default Sprite Asset_14 + 21300026: Default Sprite Asset_15 + externalObjects: {} + serializedVersion: 7 + 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: 512 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 16 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 2 + 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: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: WebGL + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: Default Sprite Asset_0 + rect: + serializedVersion: 2 + x: 0 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: a09de5b73098b2247921a5d8566535e9 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_1 + rect: + serializedVersion: 2 + x: 128 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 6f23aaeaabde92743b6e764e7373d24e + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_2 + rect: + serializedVersion: 2 + x: 256 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 7a53700b4f8ee664dbc6d96f6897dcca + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_3 + rect: + serializedVersion: 2 + x: 384 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 8aee68303a75a5240a3bfb6295e83c8d + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_4 + rect: + serializedVersion: 2 + x: 0 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 62b55056d79f32242863dd4585a55f00 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_5 + rect: + serializedVersion: 2 + x: 128 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 40e7bb1e441a02942a5912eb1bd6beb0 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_6 + rect: + serializedVersion: 2 + x: 256 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 264af04cf7ba9a6499d6605e8546b922 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_7 + rect: + serializedVersion: 2 + x: 384 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 5df87e7d9c18ccf4eab4728947f9d93c + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_8 + rect: + serializedVersion: 2 + x: 0 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 7670512dd461b8940a38efcf24a8081d + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_11 + rect: + serializedVersion: 2 + x: 128 + y: 128 + width: 384 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 8d2f6b0f97da03b43a92ce0dc86fc195 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_12 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: c22fab65c0b72cf43bad23754277ed43 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_13 + rect: + serializedVersion: 2 + x: 128 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: e669cb3dece225c4c80a6260a92e44a4 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_14 + rect: + serializedVersion: 2 + x: 256 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: fc45a1c7b06b45d43aec543c9d13ac11 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: Default Sprite Asset_15 + rect: + serializedVersion: 2 + x: 384 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 81d0fca21c1e3dd46889168e33cda991 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Sprites/DropCap Numbers.psd b/Assets/TextMesh Pro/Examples & Extras/Sprites/DropCap Numbers.psd new file mode 100644 index 0000000..ab06bad Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Sprites/DropCap Numbers.psd differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Sprites/DropCap Numbers.psd.meta b/Assets/TextMesh Pro/Examples & Extras/Sprites/DropCap Numbers.psd.meta new file mode 100644 index 0000000..3c7f8cc --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Sprites/DropCap Numbers.psd.meta @@ -0,0 +1,166 @@ +fileFormatVersion: 2 +guid: fd09957580ac4326916010f1f260975b +timeCreated: 1464163332 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: + 21300000: 0 + 21300002: 1 + 21300004: 2 + 21300006: 3 + 21300008: 4 + 21300010: 5 + 21300012: 6 + 21300014: 7 + 21300016: 8 + 21300018: 9 + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 512 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: 0 + buildTargetSettings: [] + spriteSheet: + sprites: + - name: 0 + rect: + serializedVersion: 2 + x: 0 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 1 + rect: + serializedVersion: 2 + x: 128 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 2 + rect: + serializedVersion: 2 + x: 256 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 3 + rect: + serializedVersion: 2 + x: 384 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 4 + rect: + serializedVersion: 2 + x: 0 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 5 + rect: + serializedVersion: 2 + x: 128 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 6 + rect: + serializedVersion: 2 + x: 256 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 7 + rect: + serializedVersion: 2 + x: 384 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 8 + rect: + serializedVersion: 2 + x: 0 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + - name: 9 + rect: + serializedVersion: 2 + x: 128 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: .5, y: .5} + border: {x: 0, y: 0, z: 0, w: 0} + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures.meta b/Assets/TextMesh Pro/Examples & Extras/Textures.meta new file mode 100644 index 0000000..2a358f6 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6e5c6d5e25574122a7a12dbdbbeed156 +folderAsset: yes +timeCreated: 1436068007 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Brushed Metal 3.jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Brushed Metal 3.jpg new file mode 100644 index 0000000..6c25312 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Brushed Metal 3.jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Brushed Metal 3.jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Brushed Metal 3.jpg.meta new file mode 100644 index 0000000..7bbd971 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Brushed Metal 3.jpg.meta @@ -0,0 +1,53 @@ +fileFormatVersion: 2 +guid: f88677df267a41d6be1e7a6133e7d227 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Cement.jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Cement.jpg new file mode 100644 index 0000000..f096cb6 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Cement.jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Cement.jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Cement.jpg.meta new file mode 100644 index 0000000..6de0305 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Cement.jpg.meta @@ -0,0 +1,53 @@ +fileFormatVersion: 2 +guid: 283f897e4925411ebbaa758b4cb13fc2 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Tiles 1 - diffuse.jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Tiles 1 - diffuse.jpg new file mode 100644 index 0000000..14acfc5 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Tiles 1 - diffuse.jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Tiles 1 - diffuse.jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Tiles 1 - diffuse.jpg.meta new file mode 100644 index 0000000..e8a4de0 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Floor Tiles 1 - diffuse.jpg.meta @@ -0,0 +1,53 @@ +fileFormatVersion: 2 +guid: 85ac55597b97403c82fc6601a93cf241 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Fruit Jelly (B&W).jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Fruit Jelly (B&W).jpg new file mode 100644 index 0000000..e89901d Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Fruit Jelly (B&W).jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Fruit Jelly (B&W).jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Fruit Jelly (B&W).jpg.meta new file mode 100644 index 0000000..a1540be --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Fruit Jelly (B&W).jpg.meta @@ -0,0 +1,53 @@ +fileFormatVersion: 2 +guid: 1cdc5b506b1a4a33a53c30669ced1f51 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Diagonal (Color).jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Diagonal (Color).jpg new file mode 100644 index 0000000..cfe9fc5 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Diagonal (Color).jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Diagonal (Color).jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Diagonal (Color).jpg.meta new file mode 100644 index 0000000..895b793 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Diagonal (Color).jpg.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 2ce5c55e85304b819a1826ecbc839aa5 +timeCreated: 1430290669 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 0 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: 0 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Horizontal (Color).jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Horizontal (Color).jpg new file mode 100644 index 0000000..d71067d Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Horizontal (Color).jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Horizontal (Color).jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Horizontal (Color).jpg.meta new file mode 100644 index 0000000..0dbab5c --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Horizontal (Color).jpg.meta @@ -0,0 +1,53 @@ +fileFormatVersion: 2 +guid: 6eb184de103d4b3f812b38561065192f +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Vertical (Color).jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Vertical (Color).jpg new file mode 100644 index 0000000..2dab6f2 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Vertical (Color).jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Vertical (Color).jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Vertical (Color).jpg.meta new file mode 100644 index 0000000..9e0f415 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Gradient Vertical (Color).jpg.meta @@ -0,0 +1,53 @@ +fileFormatVersion: 2 +guid: 03d0538de6e24c0f819bfc9ce084dfa9 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Mask Zig-n-Zag.psd b/Assets/TextMesh Pro/Examples & Extras/Textures/Mask Zig-n-Zag.psd new file mode 100644 index 0000000..1f488f7 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Mask Zig-n-Zag.psd differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Mask Zig-n-Zag.psd.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Mask Zig-n-Zag.psd.meta new file mode 100644 index 0000000..73b46cb --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Mask Zig-n-Zag.psd.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: bb8dfcd263ad4eb383a33d74a720be6f +timeCreated: 1441529862 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 128 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: 5 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_diffuse.jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_diffuse.jpg new file mode 100644 index 0000000..c3442fc Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_diffuse.jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_diffuse.jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_diffuse.jpg.meta new file mode 100644 index 0000000..09ad972 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_diffuse.jpg.meta @@ -0,0 +1,132 @@ +fileFormatVersion: 2 +guid: 602cb87b6a29443b8636370ea0751574 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 7 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + 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: 512 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 16 + 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: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: WebGL + maxTextureSize: 512 + 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/TextMesh Pro/Examples & Extras/Textures/Small Crate_normal.jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_normal.jpg new file mode 100644 index 0000000..2a1f9c6 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_normal.jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_normal.jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_normal.jpg.meta new file mode 100644 index 0000000..a3993f4 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Small Crate_normal.jpg.meta @@ -0,0 +1,132 @@ +fileFormatVersion: 2 +guid: 8878a782f4334ecbbcf683b3ac780966 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 7 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 1 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 512 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 16 + 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: 0 + spriteTessellationDetail: -1 + textureType: 1 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: WebGL + maxTextureSize: 512 + 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/TextMesh Pro/Examples & Extras/Textures/Sunny Days - Seamless.jpg b/Assets/TextMesh Pro/Examples & Extras/Textures/Sunny Days - Seamless.jpg new file mode 100644 index 0000000..bc785e7 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Sunny Days - Seamless.jpg differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Sunny Days - Seamless.jpg.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Sunny Days - Seamless.jpg.meta new file mode 100644 index 0000000..c51513e --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Sunny Days - Seamless.jpg.meta @@ -0,0 +1,132 @@ +fileFormatVersion: 2 +guid: 17c350171f7a3ca479f830547c66d187 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 7 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + 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: 16 + mipBias: -100 + wrapU: 0 + wrapV: 0 + wrapW: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: WebGL + maxTextureSize: 512 + 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/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text Image 1.png b/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text Image 1.png new file mode 100644 index 0000000..43b611a Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text Image 1.png differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text Image 1.png.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text Image 1.png.meta new file mode 100644 index 0000000..71a1176 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text Image 1.png.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: 4ccf43d26c4748c792174516f4a8fcef +timeCreated: 1480389342 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text UI Screenshot.png b/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text UI Screenshot.png new file mode 100644 index 0000000..63b8c30 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text UI Screenshot.png differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text UI Screenshot.png.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text UI Screenshot.png.meta new file mode 100644 index 0000000..c924443 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Text Overflow - Linked Text UI Screenshot.png.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: c76d18757a194d618355f05f815cb0a1 +timeCreated: 1480388035 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 512 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 5 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Circle.psd b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Circle.psd new file mode 100644 index 0000000..afb8cdb Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Circle.psd differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Circle.psd.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Circle.psd.meta new file mode 100644 index 0000000..99471f0 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Circle.psd.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: 10c49fcd9c64421db7c0133e61e55f97 +timeCreated: 1464390678 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 64 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 5 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Diagonal.psd b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Diagonal.psd new file mode 100644 index 0000000..327901c Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Diagonal.psd differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Diagonal.psd.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Diagonal.psd.meta new file mode 100644 index 0000000..3e15dca --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Diagonal.psd.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: ed5290d8df18488780e2996b9b882f01 +timeCreated: 1464392250 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 64 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: 0 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Double.psd b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Double.psd new file mode 100644 index 0000000..cd206d6 Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Double.psd differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Double.psd.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Double.psd.meta new file mode 100644 index 0000000..847b0e5 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Double.psd.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: 7631f4eff8f74ed38eb3eb9db17134e1 +timeCreated: 1464390110 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 64 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: 0 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Quad.psd b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Quad.psd new file mode 100644 index 0000000..c34ee4e Binary files /dev/null and b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Quad.psd differ diff --git a/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Quad.psd.meta b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Quad.psd.meta new file mode 100644 index 0000000..bc138bc --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Textures/Wipe Pattern - Radial Quad.psd.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: 2b5e9ae96c5644d8bae932f8b4ca68a2 +timeCreated: 1464390481 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 64 + textureSettings: + filterMode: 1 + aniso: 16 + mipBias: -1 + wrapMode: 0 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 5 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Fonts.meta b/Assets/TextMesh Pro/Fonts.meta new file mode 100644 index 0000000..f0c2972 --- /dev/null +++ b/Assets/TextMesh Pro/Fonts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6ab70aee4d56447429c680537fbf93ed +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Fonts/LiberationSans - OFL.txt b/Assets/TextMesh Pro/Fonts/LiberationSans - OFL.txt new file mode 100644 index 0000000..f2473f9 --- /dev/null +++ b/Assets/TextMesh Pro/Fonts/LiberationSans - OFL.txt @@ -0,0 +1,46 @@ +Digitized data copyright (c) 2010 Google Corporation + with Reserved Font Arimo, Tinos and Cousine. +Copyright (c) 2012 Red Hat, Inc. + with Reserved Font Name Liberation. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. + +5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/Assets/TextMesh Pro/Fonts/LiberationSans - OFL.txt.meta b/Assets/TextMesh Pro/Fonts/LiberationSans - OFL.txt.meta new file mode 100644 index 0000000..fa60cea --- /dev/null +++ b/Assets/TextMesh Pro/Fonts/LiberationSans - OFL.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6e59c59b81ab47f9b6ec5781fa725d2c +timeCreated: 1484171296 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Fonts/LiberationSans.ttf b/Assets/TextMesh Pro/Fonts/LiberationSans.ttf new file mode 100644 index 0000000..626dd93 Binary files /dev/null and b/Assets/TextMesh Pro/Fonts/LiberationSans.ttf differ diff --git a/Assets/TextMesh Pro/Fonts/LiberationSans.ttf.meta b/Assets/TextMesh Pro/Fonts/LiberationSans.ttf.meta new file mode 100644 index 0000000..f2fc814 --- /dev/null +++ b/Assets/TextMesh Pro/Fonts/LiberationSans.ttf.meta @@ -0,0 +1,19 @@ +fileFormatVersion: 2 +guid: e3265ab4bf004d28a9537516768c1c75 +timeCreated: 1484171297 +licenseType: Pro +TrueTypeFontImporter: + serializedVersion: 2 + fontSize: 16 + forceTextureCase: -2 + characterSpacing: 1 + characterPadding: 0 + includeFontData: 1 + use2xBehaviour: 0 + fontNames: [] + fallbackFontReferences: [] + customCharacters: + fontRenderingMode: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources.meta b/Assets/TextMesh Pro/Resources.meta new file mode 100644 index 0000000..cfc142f --- /dev/null +++ b/Assets/TextMesh Pro/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 243e06394e614e5d99fab26083b707fa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials.meta new file mode 100644 index 0000000..8a01112 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 731f1baa9d144a9897cb1d341c2092b8 +folderAsset: yes +timeCreated: 1442040525 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat new file mode 100644 index 0000000..5bc142c --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat @@ -0,0 +1,106 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF - Drop Shadow + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON UNDERLAY_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _DiffusePower: 1 + - _FaceDilate: 0.1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.64125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0.5 + - _UnderlayOffsetY: -0.5 + - _UnderlaySoftness: 0.05 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat.meta new file mode 100644 index 0000000..fbd2cdb --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Drop Shadow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e73a58f6e2794ae7b1b7e50b7fb811b0 +timeCreated: 1484172806 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset new file mode 100644 index 0000000..9463cdf --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset @@ -0,0 +1,499 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2180264 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF Material + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Cube: + 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} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28268798066460806} + 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} + - _OutlineTex: + 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: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _BumpScale: 1 + - _ColorMask: 15 + - _CullMode: 0 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _Diffuse: 0.5 + - _DstBlend: 0 + - _FaceDilate: 0 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0 + - _Parallax: 0.02 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SpecularPower: 2 + - _SrcBlend: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 512 + - _TextureWidth: 512 + - _UVSec: 0 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + - _ZWrite: 1 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: LiberationSans SDF - Fallback + m_EditorClassIdentifier: + m_Version: 1.1.0 + m_FaceInfo: + m_FaceIndex: 0 + m_FamilyName: Liberation Sans + m_StyleName: Regular + m_PointSize: 86 + m_Scale: 1 + m_UnitsPerEM: 2048 + m_LineHeight: 98.8916 + m_AscentLine: 77.853516 + m_CapLine: 59 + m_MeanLine: 45 + m_Baseline: 0 + m_DescentLine: -18.22461 + m_SuperscriptOffset: 77.853516 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -18.22461 + m_SubscriptSize: 0.5 + m_UnderlineOffset: -12.261719 + m_UnderlineThickness: 6.298828 + m_StrikethroughOffset: 18 + m_StrikethroughThickness: 6.298828 + m_TabWidth: 24 + m_Material: {fileID: 2180264} + m_SourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 + faceIndex: 0 + pointSizeSamplingMode: 0 + pointSize: 86 + padding: 9 + paddingMode: 0 + packingMode: 4 + atlasWidth: 512 + atlasHeight: 512 + characterSetSelectionMode: 1 + characterSequence: 32 - 126, 160 - 255, 8192 - 8303, 8364, 8482, 9633 + referencedFontAssetGUID: 8f586378b4e144a9851e7b34d9b748ee + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4169 + includeFontFeatures: 1 + m_SourceFontFile: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3} + m_SourceFontFilePath: + m_AtlasPopulationMode: 1 + InternalDynamicOS: 0 + m_GlyphTable: [] + m_CharacterTable: [] + m_AtlasTextures: + - {fileID: 28268798066460806} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 1 + m_GetFontFeatures: 1 + m_ClearDynamicDataOnBuild: 1 + m_AtlasWidth: 512 + m_AtlasHeight: 512 + m_AtlasPadding: 9 + m_AtlasRenderMode: 4169 + m_UsedGlyphRects: [] + m_FreeGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 511 + m_Height: 511 + m_FontFeatureTable: + m_MultipleSubstitutionRecords: [] + m_LigatureSubstitutionRecords: [] + m_GlyphPairAdjustmentRecords: + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -0.9658203 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 994 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.8896484 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 997 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -0.9658203 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 999 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.8896484 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 1000 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -2.8554688 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 1004 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -2.8554688 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 1011 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -0.9658203 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 1012 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.8896484 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 1014 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 998 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -2.8554688 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 1016 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + m_MarkToBaseAdjustmentRecords: [] + m_MarkToMarkAdjustmentRecords: [] + m_ShouldReimportFontFeatures: 0 + m_FallbackFontAssetTable: [] + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 + m_fontInfo: + Name: Liberation Sans + PointSize: 86 + Scale: 1 + CharacterCount: 250 + LineHeight: 98.90625 + Baseline: 0 + Ascender: 77.84375 + CapHeight: 59.1875 + Descender: -18.21875 + CenterLine: 0 + SuperscriptOffset: 77.84375 + SubscriptOffset: -12.261719 + SubSize: 0.5 + Underline: -12.261719 + UnderlineThickness: 6.298828 + strikethrough: 23.675 + strikethroughThickness: 0 + TabWidth: 239.0625 + Padding: 9 + AtlasWidth: 1024 + AtlasHeight: 1024 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + fallbackFontAssets: [] + atlas: {fileID: 0} +--- !u!28 &28268798066460806 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_IsAlphaChannelOptional: 0 + serializedVersion: 3 + m_Width: 1 + m_Height: 1 + m_CompleteImageSize: 1 + m_MipsStripped: 0 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 1 + m_IsPreProcessed: 0 + m_IgnoreMipmapLimit: 0 + m_MipmapLimitGroupName: + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_VTOnly: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + m_PlatformBlob: + image data: 1 + _typelessdata: 00 + m_StreamData: + serializedVersion: 2 + offset: 0 + size: 0 + path: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset.meta new file mode 100644 index 0000000..42dd6ac --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2e498d1c8094910479dc3e1b768306a4 +timeCreated: 1484171803 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat new file mode 100644 index 0000000..cca8ce8 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat @@ -0,0 +1,104 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF - Outline + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: OUTLINE_ON + m_LightmapFlags: 5 + 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} + - _Cube: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee, + type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Ambient: 0.5 + - _Bevel: 0.5 + - _BevelClamp: 0 + - _BevelOffset: 0 + - _BevelRoundness: 0 + - _BevelWidth: 0 + - _BumpFace: 0 + - _BumpOutline: 0 + - _ColorMask: 15 + - _Diffuse: 0.5 + - _FaceDilate: 0.1 + - _FaceUVSpeedX: 0 + - _FaceUVSpeedY: 0 + - _GlowInner: 0.05 + - _GlowOffset: 0 + - _GlowOuter: 0.05 + - _GlowPower: 0.75 + - _GradientScale: 10 + - _LightAngle: 3.1416 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineUVSpeedX: 0 + - _OutlineUVSpeedY: 0 + - _OutlineWidth: 0.1 + - _PerspectiveFilter: 0.875 + - _Reflectivity: 10 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.64125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _SpecularPower: 2 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _GlowColor: {r: 0, g: 1, b: 0, a: 0.5} + - _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1} + - _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat.meta new file mode 100644 index 0000000..88d6334 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Outline.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 79459efec17a4d00a321bdcc27bbc385 +timeCreated: 1484172856 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset new file mode 100644 index 0000000..c7b0771 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset @@ -0,0 +1,7821 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2180264 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF Material + m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 28684132378477856} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _ColorMask: 15 + - _FaceDilate: 0 + - _GradientScale: 10 + - _MaskSoftnessX: 0 + - _MaskSoftnessY: 0 + - _OutlineSoftness: 0 + - _OutlineWidth: 0 + - _PerspectiveFilter: 0.875 + - _ScaleRatioA: 0.9 + - _ScaleRatioB: 1 + - _ScaleRatioC: 0.73125 + - _ScaleX: 1 + - _ScaleY: 1 + - _ShaderFlags: 0 + - _Sharpness: 0 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _TextureHeight: 1024 + - _TextureWidth: 1024 + - _UnderlayDilate: 0 + - _UnderlayOffsetX: 0 + - _UnderlayOffsetY: 0 + - _UnderlaySoftness: 0 + - _VertexOffsetX: 0 + - _VertexOffsetY: 0 + - _WeightBold: 0.75 + - _WeightNormal: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _FaceColor: {r: 1, g: 1, b: 1, a: 1} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} + m_Name: LiberationSans SDF + m_EditorClassIdentifier: + hashCode: 231247347 + material: {fileID: 2180264} + materialHashCode: -1183942120 + m_Version: 1.1.0 + m_SourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, + type: 3} + m_SourceFontFile: {fileID: 0} + m_AtlasPopulationMode: 0 + m_FaceInfo: + m_FamilyName: Liberation Sans + m_StyleName: Regular + m_PointSize: 86 + m_Scale: 1 + m_LineHeight: 98.8916 + m_AscentLine: 77.853516 + m_CapLine: 59 + m_MeanLine: 45 + m_Baseline: 0 + m_DescentLine: -18.22461 + m_SuperscriptOffset: 77.853516 + m_SuperscriptSize: 0.5 + m_SubscriptOffset: -18.22461 + m_SubscriptSize: 0.5 + m_UnderlineOffset: -12.261719 + m_UnderlineThickness: 6.298828 + m_StrikethroughOffset: 18 + m_StrikethroughThickness: 6.298828 + m_TabWidth: 24 + m_GlyphTable: + - m_Index: 3 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 4 + m_Metrics: + m_Width: 9 + m_Height: 59 + m_HorizontalBearingX: 9 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 28 + m_GlyphRect: + m_X: 555 + m_Y: 816 + m_Width: 9 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 5 + m_Metrics: + m_Width: 25 + m_Height: 19 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 31 + m_GlyphRect: + m_X: 775 + m_Y: 922 + m_Width: 25 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 6 + m_Metrics: + m_Width: 48 + m_Height: 59 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 471 + m_Y: 170 + m_Width: 48 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 7 + m_Metrics: + m_Width: 47 + m_Height: 70 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 64 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 161 + m_Y: 212 + m_Width: 47 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 8 + m_Metrics: + m_Width: 70 + m_Height: 61 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 76 + m_GlyphRect: + m_X: 409 + m_Y: 10 + m_Width: 70 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 9 + m_Metrics: + m_Width: 53 + m_Height: 61 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 437 + m_Y: 90 + m_Width: 53 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 10 + m_Metrics: + m_Width: 8 + m_Height: 19 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 16 + m_GlyphRect: + m_X: 975 + m_Y: 961 + m_Width: 8 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 11 + m_Metrics: + m_Width: 24 + m_Height: 80 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 146 + m_Y: 673 + m_Width: 24 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 12 + m_Metrics: + m_Width: 24 + m_Height: 80 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 189 + m_Y: 671 + m_Width: 24 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 13 + m_Metrics: + m_Width: 31 + m_Height: 30 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 33 + m_GlyphRect: + m_X: 495 + m_Y: 984 + m_Width: 31 + m_Height: 30 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 14 + m_Metrics: + m_Width: 42 + m_Height: 43 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 50 + m_HorizontalAdvance: 50 + m_GlyphRect: + m_X: 972 + m_Y: 330 + m_Width: 42 + m_Height: 43 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 15 + m_Metrics: + m_Width: 10 + m_Height: 20 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 9 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 583 + m_Y: 992 + m_Width: 10 + m_Height: 20 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 16 + m_Metrics: + m_Width: 23 + m_Height: 7 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 26 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 399 + m_Y: 925 + m_Width: 23 + m_Height: 7 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 17 + m_Metrics: + m_Width: 10 + m_Height: 9 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 9 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 657 + m_Y: 958 + m_Width: 10 + m_Height: 9 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 18 + m_Metrics: + m_Width: 24 + m_Height: 63 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 695 + m_Y: 409 + m_Width: 24 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 19 + m_Metrics: + m_Width: 42 + m_Height: 61 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 532 + m_Y: 249 + m_Width: 42 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 20 + m_Metrics: + m_Width: 38 + m_Height: 59 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 915 + m_Y: 501 + m_Width: 38 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 21 + m_Metrics: + m_Width: 40 + m_Height: 60 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 596 + m_Y: 329 + m_Width: 40 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 22 + m_Metrics: + m_Width: 42 + m_Height: 61 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 417 + m_Y: 503 + m_Width: 42 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 23 + m_Metrics: + m_Width: 45 + m_Height: 59 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 725 + m_Y: 252 + m_Width: 45 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 24 + m_Metrics: + m_Width: 42 + m_Height: 60 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 724 + m_Y: 330 + m_Width: 42 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 25 + m_Metrics: + m_Width: 41 + m_Height: 61 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 912 + m_Y: 262 + m_Width: 41 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 26 + m_Metrics: + m_Width: 40 + m_Height: 59 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 438 + m_Y: 830 + m_Width: 40 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 27 + m_Metrics: + m_Width: 42 + m_Height: 61 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 733 + m_Y: 648 + m_Width: 42 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 28 + m_Metrics: + m_Width: 40 + m_Height: 61 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 856 + m_Y: 484 + m_Width: 40 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 29 + m_Metrics: + m_Width: 10 + m_Height: 45 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 897 + m_Y: 819 + m_Width: 10 + m_Height: 45 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 30 + m_Metrics: + m_Width: 10 + m_Height: 57 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 429 + m_Y: 287 + m_Width: 10 + m_Height: 57 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 31 + m_Metrics: + m_Width: 42 + m_Height: 43 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 50 + m_HorizontalAdvance: 50 + m_GlyphRect: + m_X: 846 + m_Y: 341 + m_Width: 42 + m_Height: 43 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 32 + m_Metrics: + m_Width: 42 + m_Height: 29 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 42 + m_HorizontalAdvance: 50 + m_GlyphRect: + m_X: 227 + m_Y: 281 + m_Width: 42 + m_Height: 29 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 33 + m_Metrics: + m_Width: 42 + m_Height: 43 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 50 + m_HorizontalAdvance: 50 + m_GlyphRect: + m_X: 972 + m_Y: 392 + m_Width: 42 + m_Height: 43 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 34 + m_Metrics: + m_Width: 42 + m_Height: 60 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 733 + m_Y: 728 + m_Width: 42 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 35 + m_Metrics: + m_Width: 74 + m_Height: 74 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 87 + m_GlyphRect: + m_X: 10 + m_Y: 10 + m_Width: 74 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 36 + m_Metrics: + m_Width: 57 + m_Height: 59 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 828 + m_Y: 103 + m_Width: 57 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 37 + m_Metrics: + m_Width: 46 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 542 + m_Y: 486 + m_Width: 46 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 38 + m_Metrics: + m_Width: 55 + m_Height: 61 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 509 + m_Y: 88 + m_Width: 55 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 39 + m_Metrics: + m_Width: 51 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 655 + m_Y: 252 + m_Width: 51 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 40 + m_Metrics: + m_Width: 47 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 629 + m_Y: 409 + m_Width: 47 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 41 + m_Metrics: + m_Width: 43 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 53 + m_GlyphRect: + m_X: 789 + m_Y: 259 + m_Width: 43 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 42 + m_Metrics: + m_Width: 57 + m_Height: 61 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 904 + m_Y: 103 + m_Width: 57 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 43 + m_Metrics: + m_Width: 48 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 495 + m_Y: 407 + m_Width: 48 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 44 + m_Metrics: + m_Width: 9 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 552 + m_Y: 919 + m_Width: 9 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 45 + m_Metrics: + m_Width: 36 + m_Height: 60 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 797 + m_Y: 569 + m_Width: 36 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 46 + m_Metrics: + m_Width: 50 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 458 + m_Y: 326 + m_Width: 50 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 47 + m_Metrics: + m_Width: 39 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 497 + m_Y: 816 + m_Width: 39 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 48 + m_Metrics: + m_Width: 59 + m_Height: 59 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 71 + m_GlyphRect: + m_X: 97 + m_Y: 955 + m_Width: 59 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 49 + m_Metrics: + m_Width: 48 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 562 + m_Y: 408 + m_Width: 48 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 50 + m_Metrics: + m_Width: 59 + m_Height: 61 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 583 + m_Y: 89 + m_Width: 59 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 51 + m_Metrics: + m_Width: 46 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 669 + m_Y: 491 + m_Width: 46 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 52 + m_Metrics: + m_Width: 59 + m_Height: 76 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 10 + m_Y: 103 + m_Width: 59 + m_Height: 76 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 53 + m_Metrics: + m_Width: 52 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 461 + m_Y: 248 + m_Width: 52 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 54 + m_Metrics: + m_Width: 51 + m_Height: 61 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 288 + m_Y: 273 + m_Width: 51 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 55 + m_Metrics: + m_Width: 50 + m_Height: 59 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 52 + m_GlyphRect: + m_X: 527 + m_Y: 329 + m_Width: 50 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 56 + m_Metrics: + m_Width: 50 + m_Height: 60 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 655 + m_Y: 330 + m_Width: 50 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 57 + m_Metrics: + m_Width: 57 + m_Height: 59 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 273 + m_Y: 195 + m_Width: 57 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 58 + m_Metrics: + m_Width: 85 + m_Height: 59 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 85 + m_GlyphRect: + m_X: 103 + m_Y: 10 + m_Width: 85 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 59 + m_Metrics: + m_Width: 56 + m_Height: 59 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 58 + m_GlyphRect: + m_X: 175 + m_Y: 955 + m_Width: 56 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 60 + m_Metrics: + m_Width: 54 + m_Height: 59 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 56 + m_GlyphRect: + m_X: 582 + m_Y: 169 + m_Width: 54 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 61 + m_Metrics: + m_Width: 49 + m_Height: 59 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 53 + m_GlyphRect: + m_X: 427 + m_Y: 404 + m_Width: 49 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 62 + m_Metrics: + m_Width: 18 + m_Height: 80 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 232 + m_Y: 671 + m_Width: 18 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 63 + m_Metrics: + m_Width: 24 + m_Height: 63 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 375 + m_Y: 951 + m_Width: 24 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 64 + m_Metrics: + m_Width: 18 + m_Height: 80 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 223 + m_Y: 393 + m_Width: 18 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 65 + m_Metrics: + m_Width: 38 + m_Height: 31 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 38 + m_GlyphRect: + m_X: 630 + m_Y: 870 + m_Width: 38 + m_Height: 31 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 66 + m_Metrics: + m_Width: 51 + m_Height: 6 + m_HorizontalBearingX: -2 + m_HorizontalBearingY: -12 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 497 + m_Y: 894 + m_Width: 51 + m_Height: 6 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 67 + m_Metrics: + m_Width: 19 + m_Height: 13 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 456 + m_Y: 997 + m_Width: 19 + m_Height: 13 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 68 + m_Metrics: + m_Width: 45 + m_Height: 47 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 669 + m_Y: 648 + m_Width: 45 + m_Height: 47 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 69 + m_Metrics: + m_Width: 40 + m_Height: 63 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 738 + m_Y: 409 + m_Width: 40 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 70 + m_Metrics: + m_Width: 38 + m_Height: 47 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 908 + m_Y: 579 + m_Width: 38 + m_Height: 47 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 71 + m_Metrics: + m_Width: 40 + m_Height: 63 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 797 + m_Y: 403 + m_Width: 40 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 72 + m_Metrics: + m_Width: 42 + m_Height: 47 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 785 + m_Y: 337 + m_Width: 42 + m_Height: 47 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 73 + m_Metrics: + m_Width: 25 + m_Height: 62 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 25 + m_GlyphRect: + m_X: 538 + m_Y: 168 + m_Width: 25 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 74 + m_Metrics: + m_Width: 40 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 86 + m_Y: 872 + m_Width: 40 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 75 + m_Metrics: + m_Width: 38 + m_Height: 62 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 430 + m_Y: 666 + m_Width: 38 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 76 + m_Metrics: + m_Width: 9 + m_Height: 62 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 19 + m_GlyphRect: + m_X: 852 + m_Y: 567 + m_Width: 9 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 77 + m_Metrics: + m_Width: 17 + m_Height: 80 + m_HorizontalBearingX: -3 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 20 + m_GlyphRect: + m_X: 145 + m_Y: 773 + m_Width: 17 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 78 + m_Metrics: + m_Width: 40 + m_Height: 62 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 44 + m_GlyphRect: + m_X: 856 + m_Y: 403 + m_Width: 40 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 79 + m_Metrics: + m_Width: 9 + m_Height: 62 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 19 + m_GlyphRect: + m_X: 880 + m_Y: 564 + m_Width: 9 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 80 + m_Metrics: + m_Width: 64 + m_Height: 46 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 74 + m_GlyphRect: + m_X: 378 + m_Y: 222 + m_Width: 64 + m_Height: 46 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 81 + m_Metrics: + m_Width: 38 + m_Height: 46 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 630 + m_Y: 805 + m_Width: 38 + m_Height: 46 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 82 + m_Metrics: + m_Width: 42 + m_Height: 47 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 972 + m_Y: 264 + m_Width: 42 + m_Height: 47 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 83 + m_Metrics: + m_Width: 40 + m_Height: 64 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 145 + m_Y: 872 + m_Width: 40 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 84 + m_Metrics: + m_Width: 40 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 329 + m_Y: 666 + m_Width: 40 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 85 + m_Metrics: + m_Width: 23 + m_Height: 46 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 926 + m_Y: 816 + m_Width: 23 + m_Height: 46 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 86 + m_Metrics: + m_Width: 38 + m_Height: 47 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 956 + m_Y: 740 + m_Width: 38 + m_Height: 47 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 87 + m_Metrics: + m_Width: 23 + m_Height: 56 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 55 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 388 + m_Y: 672 + m_Width: 23 + m_Height: 56 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 88 + m_Metrics: + m_Width: 38 + m_Height: 46 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 495 + m_Y: 919 + m_Width: 38 + m_Height: 46 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 89 + m_Metrics: + m_Width: 43 + m_Height: 45 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 226 + m_Y: 329 + m_Width: 43 + m_Height: 45 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 90 + m_Metrics: + m_Width: 63 + m_Height: 45 + m_HorizontalBearingX: -1 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 61 + m_GlyphRect: + m_X: 655 + m_Y: 188 + m_Width: 63 + m_Height: 45 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 91 + m_Metrics: + m_Width: 43 + m_Height: 45 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 737 + m_Y: 188 + m_Width: 43 + m_Height: 45 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 92 + m_Metrics: + m_Width: 41 + m_Height: 63 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 41 + m_GlyphRect: + m_X: 609 + m_Y: 640 + m_Width: 41 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 93 + m_Metrics: + m_Width: 35 + m_Height: 45 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 42 + m_GlyphRect: + m_X: 968 + m_Y: 806 + m_Width: 35 + m_Height: 45 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 94 + m_Metrics: + m_Width: 27 + m_Height: 80 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 164 + m_Y: 113 + m_Width: 27 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 95 + m_Metrics: + m_Width: 8 + m_Height: 80 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 22 + m_GlyphRect: + m_X: 181 + m_Y: 772 + m_Width: 8 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 96 + m_Metrics: + m_Width: 27 + m_Height: 80 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 227 + m_Y: 182 + m_Width: 27 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 97 + m_Metrics: + m_Width: 44 + m_Height: 11 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 34 + m_HorizontalAdvance: 50 + m_GlyphRect: + m_X: 333 + m_Y: 832 + m_Width: 44 + m_Height: 11 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 98 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 99 + m_Metrics: + m_Width: 10 + m_Height: 59 + m_HorizontalBearingX: 9 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 28 + m_GlyphRect: + m_X: 349 + m_Y: 195 + m_Width: 10 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 100 + m_Metrics: + m_Width: 38 + m_Height: 60 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 915 + m_Y: 422 + m_Width: 38 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 101 + m_Metrics: + m_Width: 45 + m_Height: 60 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 669 + m_Y: 569 + m_Width: 45 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 102 + m_Metrics: + m_Width: 40 + m_Height: 40 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 48 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 733 + m_Y: 807 + m_Width: 40 + m_Height: 40 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 103 + m_Metrics: + m_Width: 50 + m_Height: 59 + m_HorizontalBearingX: -1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 358 + m_Y: 357 + m_Width: 50 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 104 + m_Metrics: + m_Width: 8 + m_Height: 80 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 22 + m_GlyphRect: + m_X: 306 + m_Y: 766 + m_Width: 8 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 105 + m_Metrics: + m_Width: 40 + m_Height: 69 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 223 + m_Y: 492 + m_Width: 40 + m_Height: 69 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 106 + m_Metrics: + m_Width: 25 + m_Height: 8 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 931 + m_Y: 961 + m_Width: 25 + m_Height: 8 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 107 + m_Metrics: + m_Width: 61 + m_Height: 61 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 63 + m_GlyphRect: + m_X: 277 + m_Y: 90 + m_Width: 61 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 108 + m_Metrics: + m_Width: 32 + m_Height: 33 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 32 + m_GlyphRect: + m_X: 784 + m_Y: 870 + m_Width: 32 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 109 + m_Metrics: + m_Width: 42 + m_Height: 34 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 39 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 972 + m_Y: 454 + m_Width: 42 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 110 + m_Metrics: + m_Width: 42 + m_Height: 24 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 32 + m_HorizontalAdvance: 50 + m_GlyphRect: + m_X: 972 + m_Y: 560 + m_Width: 42 + m_Height: 24 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 111 + m_Metrics: + m_Width: 23 + m_Height: 7 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 26 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 583 + m_Y: 890 + m_Width: 23 + m_Height: 7 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 112 + m_Metrics: + m_Width: 61 + m_Height: 61 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 63 + m_GlyphRect: + m_X: 357 + m_Y: 90 + m_Width: 61 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 113 + m_Metrics: + m_Width: 50 + m_Height: 4 + m_HorizontalBearingX: -1 + m_HorizontalBearingY: 65 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 862 + m_Y: 961 + m_Width: 50 + m_Height: 4 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 114 + m_Metrics: + m_Width: 24 + m_Height: 24 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 34 + m_GlyphRect: + m_X: 687 + m_Y: 906 + m_Width: 24 + m_Height: 24 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 115 + m_Metrics: + m_Width: 43 + m_Height: 52 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 52 + m_HorizontalAdvance: 47 + m_GlyphRect: + m_X: 607 + m_Y: 487 + m_Width: 43 + m_Height: 52 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 116 + m_Metrics: + m_Width: 27 + m_Height: 36 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 792 + m_Y: 815 + m_Width: 27 + m_Height: 36 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 117 + m_Metrics: + m_Width: 27 + m_Height: 37 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 687 + m_Y: 796 + m_Width: 27 + m_Height: 37 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 118 + m_Metrics: + m_Width: 19 + m_Height: 13 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 545 + m_Y: 997 + m_Width: 19 + m_Height: 13 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 119 + m_Metrics: + m_Width: 43 + m_Height: 63 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 50 + m_GlyphRect: + m_X: 593 + m_Y: 247 + m_Width: 43 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 120 + m_Metrics: + m_Width: 40 + m_Height: 70 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 46 + m_GlyphRect: + m_X: 208 + m_Y: 770 + m_Width: 40 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 121 + m_Metrics: + m_Width: 10 + m_Height: 10 + m_HorizontalBearingX: 9 + m_HorizontalBearingY: 28 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 996 + m_Y: 932 + m_Width: 10 + m_Height: 10 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 122 + m_Metrics: + m_Width: 16 + m_Height: 18 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 622 + m_Y: 958 + m_Width: 16 + m_Height: 18 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 123 + m_Metrics: + m_Width: 24 + m_Height: 35 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 687 + m_Y: 852 + m_Width: 24 + m_Height: 35 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 124 + m_Metrics: + m_Width: 29 + m_Height: 33 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 31 + m_GlyphRect: + m_X: 835 + m_Y: 877 + m_Width: 29 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 125 + m_Metrics: + m_Width: 42 + m_Height: 34 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 39 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 972 + m_Y: 507 + m_Width: 42 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 126 + m_Metrics: + m_Width: 67 + m_Height: 59 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 72 + m_GlyphRect: + m_X: 498 + m_Y: 10 + m_Width: 67 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 127 + m_Metrics: + m_Width: 68 + m_Height: 59 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 72 + m_GlyphRect: + m_X: 10 + m_Y: 955 + m_Width: 68 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 128 + m_Metrics: + m_Width: 66 + m_Height: 60 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 72 + m_GlyphRect: + m_X: 584 + m_Y: 10 + m_Width: 66 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 129 + m_Metrics: + m_Width: 43 + m_Height: 60 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 45 + m_HorizontalAdvance: 53 + m_GlyphRect: + m_X: 903 + m_Y: 183 + m_Width: 43 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 130 + m_Metrics: + m_Width: 57 + m_Height: 74 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 829 + m_Y: 10 + m_Width: 57 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 131 + m_Metrics: + m_Width: 57 + m_Height: 74 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 905 + m_Y: 10 + m_Width: 57 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 132 + m_Metrics: + m_Width: 57 + m_Height: 75 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 10 + m_Y: 673 + m_Width: 57 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 133 + m_Metrics: + m_Width: 57 + m_Height: 75 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 10 + m_Y: 767 + m_Width: 57 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 134 + m_Metrics: + m_Width: 57 + m_Height: 72 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 72 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 88 + m_Y: 113 + m_Width: 57 + m_Height: 72 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 135 + m_Metrics: + m_Width: 57 + m_Height: 75 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 10 + m_Y: 861 + m_Width: 57 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 136 + m_Metrics: + m_Width: 82 + m_Height: 59 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 86 + m_GlyphRect: + m_X: 207 + m_Y: 10 + m_Width: 82 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 137 + m_Metrics: + m_Width: 55 + m_Height: 78 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 10 + m_Y: 576 + m_Width: 55 + m_Height: 78 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 138 + m_Metrics: + m_Width: 47 + m_Height: 74 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 84 + m_Y: 580 + m_Width: 47 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 139 + m_Metrics: + m_Width: 47 + m_Height: 74 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 157 + m_Y: 487 + m_Width: 47 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 140 + m_Metrics: + m_Width: 47 + m_Height: 75 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 157 + m_Y: 393 + m_Width: 47 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 141 + m_Metrics: + m_Width: 47 + m_Height: 72 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 72 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 150 + m_Y: 580 + m_Width: 47 + m_Height: 72 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 142 + m_Metrics: + m_Width: 19 + m_Height: 74 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 227 + m_Y: 859 + m_Width: 19 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 143 + m_Metrics: + m_Width: 19 + m_Height: 74 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 265 + m_Y: 859 + m_Width: 19 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 144 + m_Metrics: + m_Width: 28 + m_Height: 75 + m_HorizontalBearingX: -2 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 981 + m_Y: 10 + m_Width: 28 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 145 + m_Metrics: + m_Width: 25 + m_Height: 72 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 72 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 216 + m_Y: 580 + m_Width: 25 + m_Height: 72 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 146 + m_Metrics: + m_Width: 58 + m_Height: 59 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 751 + m_Y: 102 + m_Width: 58 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 147 + m_Metrics: + m_Width: 48 + m_Height: 75 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 210 + m_Y: 88 + m_Width: 48 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 148 + m_Metrics: + m_Width: 59 + m_Height: 75 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 10 + m_Y: 388 + m_Width: 59 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 149 + m_Metrics: + m_Width: 59 + m_Height: 75 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 10 + m_Y: 482 + m_Width: 59 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 150 + m_Metrics: + m_Width: 59 + m_Height: 76 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 10 + m_Y: 198 + m_Width: 59 + m_Height: 76 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 151 + m_Metrics: + m_Width: 59 + m_Height: 76 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 10 + m_Y: 293 + m_Width: 59 + m_Height: 76 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 152 + m_Metrics: + m_Width: 59 + m_Height: 73 + m_HorizontalBearingX: 4 + m_HorizontalBearingY: 72 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 751 + m_Y: 10 + m_Width: 59 + m_Height: 73 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 153 + m_Metrics: + m_Width: 40 + m_Height: 39 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 48 + m_HorizontalAdvance: 50 + m_GlyphRect: + m_X: 838 + m_Y: 819 + m_Width: 40 + m_Height: 39 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 154 + m_Metrics: + m_Width: 63 + m_Height: 65 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 67 + m_GlyphRect: + m_X: 669 + m_Y: 10 + m_Width: 63 + m_Height: 65 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 155 + m_Metrics: + m_Width: 50 + m_Height: 75 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 88 + m_Y: 392 + m_Width: 50 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 156 + m_Metrics: + m_Width: 50 + m_Height: 75 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 88 + m_Y: 486 + m_Width: 50 + m_Height: 75 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 157 + m_Metrics: + m_Width: 50 + m_Height: 76 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 75 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 88 + m_Y: 297 + m_Width: 50 + m_Height: 76 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 158 + m_Metrics: + m_Width: 50 + m_Height: 73 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 72 + m_HorizontalAdvance: 62 + m_GlyphRect: + m_X: 157 + m_Y: 301 + m_Width: 50 + m_Height: 73 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 159 + m_Metrics: + m_Width: 54 + m_Height: 74 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 74 + m_HorizontalAdvance: 56 + m_GlyphRect: + m_X: 88 + m_Y: 204 + m_Width: 54 + m_Height: 74 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 160 + m_Metrics: + m_Width: 46 + m_Height: 59 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 57 + m_GlyphRect: + m_X: 734 + m_Y: 491 + m_Width: 46 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 161 + m_Metrics: + m_Width: 44 + m_Height: 63 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 53 + m_GlyphRect: + m_X: 545 + m_Y: 564 + m_Width: 44 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 162 + m_Metrics: + m_Width: 45 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 324 + m_Y: 583 + m_Width: 45 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 163 + m_Metrics: + m_Width: 45 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 333 + m_Y: 749 + m_Width: 45 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 164 + m_Metrics: + m_Width: 45 + m_Height: 63 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 478 + m_Y: 485 + m_Width: 45 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 165 + m_Metrics: + m_Width: 45 + m_Height: 62 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 61 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 250 + m_Y: 952 + m_Width: 45 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 166 + m_Metrics: + m_Width: 45 + m_Height: 60 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 733 + m_Y: 569 + m_Width: 45 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 167 + m_Metrics: + m_Width: 45 + m_Height: 71 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 70 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 260 + m_Y: 580 + m_Width: 45 + m_Height: 71 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 168 + m_Metrics: + m_Width: 71 + m_Height: 47 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 76 + m_GlyphRect: + m_X: 661 + m_Y: 94 + m_Width: 71 + m_Height: 47 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 169 + m_Metrics: + m_Width: 38 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 46 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 427 + m_Y: 583 + m_Width: 38 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 170 + m_Metrics: + m_Width: 42 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 436 + m_Y: 747 + m_Width: 42 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 171 + m_Metrics: + m_Width: 42 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 484 + m_Y: 567 + m_Width: 42 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 172 + m_Metrics: + m_Width: 42 + m_Height: 63 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 608 + m_Y: 558 + m_Width: 42 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 173 + m_Metrics: + m_Width: 42 + m_Height: 60 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 851 + m_Y: 262 + m_Width: 42 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 174 + m_Metrics: + m_Width: 19 + m_Height: 63 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 838 + m_Y: 737 + m_Width: 19 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 175 + m_Metrics: + m_Width: 19 + m_Height: 63 + m_HorizontalBearingX: 6 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 418 + m_Y: 951 + m_Width: 19 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 176 + m_Metrics: + m_Width: 29 + m_Height: 62 + m_HorizontalBearingX: -2 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 980 + m_Y: 104 + m_Width: 29 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 177 + m_Metrics: + m_Width: 25 + m_Height: 59 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 794 + m_Y: 737 + m_Width: 25 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 178 + m_Metrics: + m_Width: 42 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 487 + m_Y: 650 + m_Width: 42 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 179 + m_Metrics: + m_Width: 38 + m_Height: 61 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 61 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 915 + m_Y: 342 + m_Width: 38 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 180 + m_Metrics: + m_Width: 42 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 548 + m_Y: 646 + m_Width: 42 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 181 + m_Metrics: + m_Width: 42 + m_Height: 64 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 497 + m_Y: 733 + m_Width: 42 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 182 + m_Metrics: + m_Width: 42 + m_Height: 63 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 672 + m_Y: 714 + m_Width: 42 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 183 + m_Metrics: + m_Width: 42 + m_Height: 62 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 61 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 314 + m_Y: 952 + m_Width: 42 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 184 + m_Metrics: + m_Width: 42 + m_Height: 60 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 972 + m_Y: 185 + m_Width: 42 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 185 + m_Metrics: + m_Width: 43 + m_Height: 39 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 48 + m_HorizontalAdvance: 47 + m_GlyphRect: + m_X: 965 + m_Y: 603 + m_Width: 43 + m_Height: 39 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 186 + m_Metrics: + m_Width: 50 + m_Height: 49 + m_HorizontalBearingX: 1 + m_HorizontalBearingY: 47 + m_HorizontalAdvance: 53 + m_GlyphRect: + m_X: 357 + m_Y: 435 + m_Width: 50 + m_Height: 49 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 187 + m_Metrics: + m_Width: 38 + m_Height: 64 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 558 + m_Y: 729 + m_Width: 38 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 188 + m_Metrics: + m_Width: 38 + m_Height: 64 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 615 + m_Y: 722 + m_Width: 38 + m_Height: 64 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 189 + m_Metrics: + m_Width: 38 + m_Height: 63 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 799 + m_Y: 485 + m_Width: 38 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 190 + m_Metrics: + m_Width: 38 + m_Height: 60 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 956 + m_Y: 661 + m_Width: 38 + m_Height: 60 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 191 + m_Metrics: + m_Width: 41 + m_Height: 81 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 63 + m_HorizontalAdvance: 41 + m_GlyphRect: + m_X: 86 + m_Y: 673 + m_Width: 41 + m_Height: 81 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 192 + m_Metrics: + m_Width: 40 + m_Height: 80 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 86 + m_Y: 773 + m_Width: 40 + m_Height: 80 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 193 + m_Metrics: + m_Width: 41 + m_Height: 77 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 41 + m_GlyphRect: + m_X: 269 + m_Y: 670 + m_Width: 41 + m_Height: 77 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 1997 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 1998 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 86 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 1999 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2000 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 86 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2001 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2002 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 22 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2003 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 14 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2004 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2005 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2006 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 17 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2007 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 7 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2008 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2009 + m_Metrics: + m_Width: 4 + m_Height: 65 + m_HorizontalBearingX: -2 + m_HorizontalBearingY: 54 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 204 + m_Y: 871 + m_Width: 4 + m_Height: 65 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2010 + m_Metrics: + m_Width: 20 + m_Height: 70 + m_HorizontalBearingX: -10 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 267 + m_Y: 770 + m_Width: 20 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2011 + m_Metrics: + m_Width: 21 + m_Height: 70 + m_HorizontalBearingX: -2 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 260 + m_Y: 393 + m_Width: 21 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2012 + m_Metrics: + m_Width: 21 + m_Height: 70 + m_HorizontalBearingX: -19 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 282 + m_Y: 482 + m_Width: 21 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2013 + m_Metrics: + m_Width: 48 + m_Height: 6 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 25 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 862 + m_Y: 936 + m_Width: 48 + m_Height: 6 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2014 + m_Metrics: + m_Width: 48 + m_Height: 6 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 25 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 929 + m_Y: 936 + m_Width: 48 + m_Height: 6 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2015 + m_Metrics: + m_Width: 86 + m_Height: 6 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 25 + m_HorizontalAdvance: 86 + m_GlyphRect: + m_X: 103 + m_Y: 88 + m_Width: 86 + m_Height: 6 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2016 + m_Metrics: + m_Width: 86 + m_Height: 6 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 25 + m_HorizontalAdvance: 86 + m_GlyphRect: + m_X: 277 + m_Y: 170 + m_Width: 86 + m_Height: 6 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2017 + m_Metrics: + m_Width: 22 + m_Height: 62 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 36 + m_GlyphRect: + m_X: 862 + m_Y: 181 + m_Width: 22 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2018 + m_Metrics: + m_Width: 51 + m_Height: 15 + m_HorizontalBearingX: -2 + m_HorizontalBearingY: -4 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 288 + m_Y: 353 + m_Width: 51 + m_Height: 15 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2019 + m_Metrics: + m_Width: 9 + m_Height: 19 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 19 + m_GlyphRect: + m_X: 612 + m_Y: 995 + m_Width: 9 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2020 + m_Metrics: + m_Width: 9 + m_Height: 19 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 19 + m_GlyphRect: + m_X: 640 + m_Y: 995 + m_Width: 9 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2021 + m_Metrics: + m_Width: 9 + m_Height: 19 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 8 + m_HorizontalAdvance: 19 + m_GlyphRect: + m_X: 1002 + m_Y: 961 + m_Width: 9 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2022 + m_Metrics: + m_Width: 9 + m_Height: 19 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 19 + m_GlyphRect: + m_X: 686 + m_Y: 949 + m_Width: 9 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2023 + m_Metrics: + m_Width: 23 + m_Height: 19 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 967 + m_Y: 894 + m_Width: 23 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2024 + m_Metrics: + m_Width: 23 + m_Height: 19 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 580 + m_Y: 916 + m_Width: 23 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2025 + m_Metrics: + m_Width: 23 + m_Height: 19 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 8 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 580 + m_Y: 954 + m_Width: 23 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2026 + m_Metrics: + m_Width: 22 + m_Height: 19 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 622 + m_Y: 920 + m_Width: 22 + m_Height: 19 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2027 + m_Metrics: + m_Width: 38 + m_Height: 68 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 303 + m_Y: 865 + m_Width: 38 + m_Height: 68 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2028 + m_Metrics: + m_Width: 38 + m_Height: 68 + m_HorizontalBearingX: 5 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 300 + m_Y: 387 + m_Width: 38 + m_Height: 68 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2029 + m_Metrics: + m_Width: 24 + m_Height: 23 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 40 + m_HorizontalAdvance: 30 + m_GlyphRect: + m_X: 819 + m_Y: 929 + m_Width: 24 + m_Height: 23 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2030 + m_Metrics: + m_Width: 64 + m_Height: 9 + m_HorizontalBearingX: 11 + m_HorizontalBearingY: 9 + m_HorizontalAdvance: 86 + m_GlyphRect: + m_X: 661 + m_Y: 160 + m_Width: 64 + m_Height: 9 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2031 + m_Metrics: + m_Width: 21 + m_Height: 63 + m_HorizontalBearingX: -2 + m_HorizontalBearingY: 52 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 876 + m_Y: 737 + m_Width: 21 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2032 + m_Metrics: + m_Width: 21 + m_Height: 63 + m_HorizontalBearingX: -19 + m_HorizontalBearingY: 52 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 916 + m_Y: 734 + m_Width: 21 + m_Height: 63 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2033 + m_Metrics: + m_Width: 20 + m_Height: 70 + m_HorizontalBearingX: -10 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 388 + m_Y: 583 + m_Width: 20 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2034 + m_Metrics: + m_Width: 20 + m_Height: 70 + m_HorizontalBearingX: -10 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 397 + m_Y: 747 + m_Width: 20 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2035 + m_Metrics: + m_Width: 20 + m_Height: 70 + m_HorizontalBearingX: -10 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 360 + m_Y: 862 + m_Width: 20 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2036 + m_Metrics: + m_Width: 0 + m_Height: 0 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 0 + m_HorizontalAdvance: 17 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 0 + m_Height: 0 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2037 + m_Metrics: + m_Width: 82 + m_Height: 61 + m_HorizontalBearingX: 2 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 86 + m_GlyphRect: + m_X: 308 + m_Y: 10 + m_Width: 82 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2038 + m_Metrics: + m_Width: 12 + m_Height: 22 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 16 + m_GlyphRect: + m_X: 427 + m_Y: 363 + m_Width: 12 + m_Height: 22 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2039 + m_Metrics: + m_Width: 26 + m_Height: 22 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 30 + m_GlyphRect: + m_X: 730 + m_Y: 907 + m_Width: 26 + m_Height: 22 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2040 + m_Metrics: + m_Width: 35 + m_Height: 22 + m_HorizontalBearingX: -4 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 30 + m_GlyphRect: + m_X: 730 + m_Y: 866 + m_Width: 35 + m_Height: 22 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2041 + m_Metrics: + m_Width: 23 + m_Height: 34 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 39 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 883 + m_Y: 883 + m_Width: 23 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2042 + m_Metrics: + m_Width: 23 + m_Height: 34 + m_HorizontalBearingX: 3 + m_HorizontalBearingY: 39 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 925 + m_Y: 883 + m_Width: 23 + m_Height: 34 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2043 + m_Metrics: + m_Width: 28 + m_Height: 59 + m_HorizontalBearingX: 9 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 43 + m_GlyphRect: + m_X: 583 + m_Y: 812 + m_Width: 28 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2044 + m_Metrics: + m_Width: 35 + m_Height: 5 + m_HorizontalBearingX: -3 + m_HorizontalBearingY: 68 + m_HorizontalAdvance: 29 + m_GlyphRect: + m_X: 968 + m_Y: 870 + m_Width: 35 + m_Height: 5 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2045 + m_Metrics: + m_Width: 44 + m_Height: 59 + m_HorizontalBearingX: -18 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 14 + m_GlyphRect: + m_X: 799 + m_Y: 181 + m_Width: 44 + m_Height: 59 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2046 + m_Metrics: + m_Width: 10 + m_Height: 62 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 62 + m_HorizontalAdvance: 24 + m_GlyphRect: + m_X: 322 + m_Y: 474 + m_Width: 10 + m_Height: 62 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2047 + m_Metrics: + m_Width: 20 + m_Height: 70 + m_HorizontalBearingX: -10 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 399 + m_Y: 836 + m_Width: 20 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2048 + m_Metrics: + m_Width: 20 + m_Height: 70 + m_HorizontalBearingX: -10 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 794 + m_Y: 648 + m_Width: 20 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2049 + m_Metrics: + m_Width: 22 + m_Height: 70 + m_HorizontalBearingX: -11 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 833 + m_Y: 648 + m_Width: 22 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2050 + m_Metrics: + m_Width: 22 + m_Height: 70 + m_HorizontalBearingX: -11 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 874 + m_Y: 648 + m_Width: 22 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2051 + m_Metrics: + m_Width: 22 + m_Height: 70 + m_HorizontalBearingX: -11 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 915 + m_Y: 645 + m_Width: 22 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2052 + m_Metrics: + m_Width: 20 + m_Height: 70 + m_HorizontalBearingX: -10 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 0 + m_GlyphRect: + m_X: 456 + m_Y: 908 + m_Width: 20 + m_Height: 70 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2075 + m_Metrics: + m_Width: 47 + m_Height: 61 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 60 + m_HorizontalAdvance: 48 + m_GlyphRect: + m_X: 351 + m_Y: 503 + m_Width: 47 + m_Height: 61 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2090 + m_Metrics: + m_Width: 70 + m_Height: 33 + m_HorizontalBearingX: 7 + m_HorizontalBearingY: 59 + m_HorizontalAdvance: 86 + m_GlyphRect: + m_X: 382 + m_Y: 170 + m_Width: 70 + m_Height: 33 + m_Scale: 1 + m_AtlasIndex: 0 + - m_Index: 2179 + m_Metrics: + m_Width: 52 + m_Height: 51 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 51 + m_HorizontalAdvance: 52 + m_GlyphRect: + m_X: 358 + m_Y: 287 + m_Width: 52 + m_Height: 51 + m_Scale: 1 + m_AtlasIndex: 0 + m_CharacterTable: + - m_ElementType: 1 + m_Unicode: 32 + m_GlyphIndex: 3 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 33 + m_GlyphIndex: 4 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 34 + m_GlyphIndex: 5 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 35 + m_GlyphIndex: 6 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 36 + m_GlyphIndex: 7 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 37 + m_GlyphIndex: 8 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 38 + m_GlyphIndex: 9 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 39 + m_GlyphIndex: 10 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 40 + m_GlyphIndex: 11 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 41 + m_GlyphIndex: 12 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 42 + m_GlyphIndex: 13 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 43 + m_GlyphIndex: 14 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 44 + m_GlyphIndex: 15 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 45 + m_GlyphIndex: 16 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 46 + m_GlyphIndex: 17 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 47 + m_GlyphIndex: 18 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 48 + m_GlyphIndex: 19 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 49 + m_GlyphIndex: 20 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 50 + m_GlyphIndex: 21 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 51 + m_GlyphIndex: 22 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 52 + m_GlyphIndex: 23 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 53 + m_GlyphIndex: 24 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 54 + m_GlyphIndex: 25 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 55 + m_GlyphIndex: 26 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 56 + m_GlyphIndex: 27 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 57 + m_GlyphIndex: 28 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 58 + m_GlyphIndex: 29 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 59 + m_GlyphIndex: 30 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 60 + m_GlyphIndex: 31 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 61 + m_GlyphIndex: 32 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 62 + m_GlyphIndex: 33 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 63 + m_GlyphIndex: 34 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 64 + m_GlyphIndex: 35 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 65 + m_GlyphIndex: 36 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 66 + m_GlyphIndex: 37 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 67 + m_GlyphIndex: 38 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 68 + m_GlyphIndex: 39 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 69 + m_GlyphIndex: 40 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 70 + m_GlyphIndex: 41 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 71 + m_GlyphIndex: 42 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 72 + m_GlyphIndex: 43 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 73 + m_GlyphIndex: 44 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 74 + m_GlyphIndex: 45 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 75 + m_GlyphIndex: 46 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 76 + m_GlyphIndex: 47 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 77 + m_GlyphIndex: 48 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 78 + m_GlyphIndex: 49 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 79 + m_GlyphIndex: 50 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 80 + m_GlyphIndex: 51 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 81 + m_GlyphIndex: 52 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 82 + m_GlyphIndex: 53 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 83 + m_GlyphIndex: 54 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 84 + m_GlyphIndex: 55 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 85 + m_GlyphIndex: 56 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 86 + m_GlyphIndex: 57 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 87 + m_GlyphIndex: 58 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 88 + m_GlyphIndex: 59 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 89 + m_GlyphIndex: 60 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 90 + m_GlyphIndex: 61 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 91 + m_GlyphIndex: 62 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 92 + m_GlyphIndex: 63 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 93 + m_GlyphIndex: 64 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 94 + m_GlyphIndex: 65 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 95 + m_GlyphIndex: 66 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 96 + m_GlyphIndex: 67 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 97 + m_GlyphIndex: 68 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 98 + m_GlyphIndex: 69 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 99 + m_GlyphIndex: 70 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 100 + m_GlyphIndex: 71 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 101 + m_GlyphIndex: 72 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 102 + m_GlyphIndex: 73 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 103 + m_GlyphIndex: 74 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 104 + m_GlyphIndex: 75 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 105 + m_GlyphIndex: 76 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 106 + m_GlyphIndex: 77 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 107 + m_GlyphIndex: 78 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 108 + m_GlyphIndex: 79 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 109 + m_GlyphIndex: 80 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 110 + m_GlyphIndex: 81 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 111 + m_GlyphIndex: 82 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 112 + m_GlyphIndex: 83 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 113 + m_GlyphIndex: 84 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 114 + m_GlyphIndex: 85 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 115 + m_GlyphIndex: 86 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 116 + m_GlyphIndex: 87 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 117 + m_GlyphIndex: 88 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 118 + m_GlyphIndex: 89 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 119 + m_GlyphIndex: 90 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 120 + m_GlyphIndex: 91 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 121 + m_GlyphIndex: 92 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 122 + m_GlyphIndex: 93 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 123 + m_GlyphIndex: 94 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 124 + m_GlyphIndex: 95 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 125 + m_GlyphIndex: 96 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 126 + m_GlyphIndex: 97 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 160 + m_GlyphIndex: 98 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 161 + m_GlyphIndex: 99 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 162 + m_GlyphIndex: 100 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 163 + m_GlyphIndex: 101 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 164 + m_GlyphIndex: 102 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 165 + m_GlyphIndex: 103 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 166 + m_GlyphIndex: 104 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 167 + m_GlyphIndex: 105 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 168 + m_GlyphIndex: 106 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 169 + m_GlyphIndex: 107 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 170 + m_GlyphIndex: 108 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 171 + m_GlyphIndex: 109 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 172 + m_GlyphIndex: 110 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 173 + m_GlyphIndex: 111 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 174 + m_GlyphIndex: 112 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 175 + m_GlyphIndex: 113 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 176 + m_GlyphIndex: 114 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 177 + m_GlyphIndex: 115 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 178 + m_GlyphIndex: 116 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 179 + m_GlyphIndex: 117 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 180 + m_GlyphIndex: 118 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 181 + m_GlyphIndex: 119 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 182 + m_GlyphIndex: 120 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 183 + m_GlyphIndex: 121 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 184 + m_GlyphIndex: 122 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 185 + m_GlyphIndex: 123 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 186 + m_GlyphIndex: 124 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 187 + m_GlyphIndex: 125 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 188 + m_GlyphIndex: 126 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 189 + m_GlyphIndex: 127 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 190 + m_GlyphIndex: 128 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 191 + m_GlyphIndex: 129 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 192 + m_GlyphIndex: 130 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 193 + m_GlyphIndex: 131 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 194 + m_GlyphIndex: 132 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 195 + m_GlyphIndex: 133 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 196 + m_GlyphIndex: 134 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 197 + m_GlyphIndex: 135 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 198 + m_GlyphIndex: 136 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 199 + m_GlyphIndex: 137 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 200 + m_GlyphIndex: 138 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 201 + m_GlyphIndex: 139 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 202 + m_GlyphIndex: 140 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 203 + m_GlyphIndex: 141 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 204 + m_GlyphIndex: 142 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 205 + m_GlyphIndex: 143 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 206 + m_GlyphIndex: 144 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 207 + m_GlyphIndex: 145 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 208 + m_GlyphIndex: 146 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 209 + m_GlyphIndex: 147 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 210 + m_GlyphIndex: 148 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 211 + m_GlyphIndex: 149 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 212 + m_GlyphIndex: 150 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 213 + m_GlyphIndex: 151 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 214 + m_GlyphIndex: 152 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 215 + m_GlyphIndex: 153 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 216 + m_GlyphIndex: 154 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 217 + m_GlyphIndex: 155 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 218 + m_GlyphIndex: 156 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 219 + m_GlyphIndex: 157 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 220 + m_GlyphIndex: 158 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 221 + m_GlyphIndex: 159 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 222 + m_GlyphIndex: 160 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 223 + m_GlyphIndex: 161 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 224 + m_GlyphIndex: 162 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 225 + m_GlyphIndex: 163 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 226 + m_GlyphIndex: 164 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 227 + m_GlyphIndex: 165 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 228 + m_GlyphIndex: 166 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 229 + m_GlyphIndex: 167 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 230 + m_GlyphIndex: 168 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 231 + m_GlyphIndex: 169 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 232 + m_GlyphIndex: 170 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 233 + m_GlyphIndex: 171 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 234 + m_GlyphIndex: 172 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 235 + m_GlyphIndex: 173 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 236 + m_GlyphIndex: 174 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 237 + m_GlyphIndex: 175 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 238 + m_GlyphIndex: 176 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 239 + m_GlyphIndex: 177 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 240 + m_GlyphIndex: 178 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 241 + m_GlyphIndex: 179 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 242 + m_GlyphIndex: 180 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 243 + m_GlyphIndex: 181 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 244 + m_GlyphIndex: 182 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 245 + m_GlyphIndex: 183 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 246 + m_GlyphIndex: 184 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 247 + m_GlyphIndex: 185 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 248 + m_GlyphIndex: 186 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 249 + m_GlyphIndex: 187 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 250 + m_GlyphIndex: 188 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 251 + m_GlyphIndex: 189 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 252 + m_GlyphIndex: 190 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 253 + m_GlyphIndex: 191 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 254 + m_GlyphIndex: 192 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 255 + m_GlyphIndex: 193 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8192 + m_GlyphIndex: 1997 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8193 + m_GlyphIndex: 1998 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8194 + m_GlyphIndex: 1999 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8195 + m_GlyphIndex: 2000 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8196 + m_GlyphIndex: 2001 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8197 + m_GlyphIndex: 2002 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8198 + m_GlyphIndex: 2003 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8199 + m_GlyphIndex: 2004 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8200 + m_GlyphIndex: 2005 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8201 + m_GlyphIndex: 2006 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8202 + m_GlyphIndex: 2007 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8203 + m_GlyphIndex: 2008 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8204 + m_GlyphIndex: 2009 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8205 + m_GlyphIndex: 2010 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8206 + m_GlyphIndex: 2011 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8207 + m_GlyphIndex: 2012 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8210 + m_GlyphIndex: 2013 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8211 + m_GlyphIndex: 2014 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8212 + m_GlyphIndex: 2015 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8213 + m_GlyphIndex: 2016 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8214 + m_GlyphIndex: 2017 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8215 + m_GlyphIndex: 2018 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8216 + m_GlyphIndex: 2019 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8217 + m_GlyphIndex: 2020 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8218 + m_GlyphIndex: 2021 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8219 + m_GlyphIndex: 2022 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8220 + m_GlyphIndex: 2023 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8221 + m_GlyphIndex: 2024 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8222 + m_GlyphIndex: 2025 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8223 + m_GlyphIndex: 2026 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8224 + m_GlyphIndex: 2027 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8225 + m_GlyphIndex: 2028 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8226 + m_GlyphIndex: 2029 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8230 + m_GlyphIndex: 2030 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8234 + m_GlyphIndex: 2031 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8235 + m_GlyphIndex: 2032 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8236 + m_GlyphIndex: 2033 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8237 + m_GlyphIndex: 2034 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8238 + m_GlyphIndex: 2035 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8239 + m_GlyphIndex: 2036 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8240 + m_GlyphIndex: 2037 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8242 + m_GlyphIndex: 2038 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8243 + m_GlyphIndex: 2039 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8244 + m_GlyphIndex: 2040 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8249 + m_GlyphIndex: 2041 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8250 + m_GlyphIndex: 2042 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8252 + m_GlyphIndex: 2043 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8254 + m_GlyphIndex: 2044 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8260 + m_GlyphIndex: 2045 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8286 + m_GlyphIndex: 2046 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8298 + m_GlyphIndex: 2047 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8299 + m_GlyphIndex: 2048 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8300 + m_GlyphIndex: 2049 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8301 + m_GlyphIndex: 2050 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8302 + m_GlyphIndex: 2051 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8303 + m_GlyphIndex: 2052 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8364 + m_GlyphIndex: 2075 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 8482 + m_GlyphIndex: 2090 + m_Scale: 1 + - m_ElementType: 1 + m_Unicode: 9633 + m_GlyphIndex: 2179 + m_Scale: 1 + m_AtlasTextures: + - {fileID: 28684132378477856} + m_AtlasTextureIndex: 0 + m_UsedGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 93 + m_Height: 93 + - m_X: 93 + m_Y: 0 + m_Width: 104 + m_Height: 78 + - m_X: 197 + m_Y: 0 + m_Width: 101 + m_Height: 78 + - m_X: 298 + m_Y: 0 + m_Width: 101 + m_Height: 80 + - m_X: 0 + m_Y: 93 + m_Width: 78 + m_Height: 95 + - m_X: 0 + m_Y: 188 + m_Width: 78 + m_Height: 95 + - m_X: 0 + m_Y: 283 + m_Width: 78 + m_Height: 95 + - m_X: 0 + m_Y: 378 + m_Width: 78 + m_Height: 94 + - m_X: 0 + m_Y: 472 + m_Width: 78 + m_Height: 94 + - m_X: 0 + m_Y: 566 + m_Width: 74 + m_Height: 97 + - m_X: 399 + m_Y: 0 + m_Width: 89 + m_Height: 80 + - m_X: 0 + m_Y: 663 + m_Width: 76 + m_Height: 94 + - m_X: 0 + m_Y: 757 + m_Width: 76 + m_Height: 94 + - m_X: 0 + m_Y: 851 + m_Width: 76 + m_Height: 94 + - m_X: 0 + m_Y: 945 + m_Width: 87 + m_Height: 78 + - m_X: 488 + m_Y: 0 + m_Width: 86 + m_Height: 78 + - m_X: 574 + m_Y: 0 + m_Width: 85 + m_Height: 79 + - m_X: 659 + m_Y: 0 + m_Width: 82 + m_Height: 84 + - m_X: 741 + m_Y: 0 + m_Width: 78 + m_Height: 92 + - m_X: 819 + m_Y: 0 + m_Width: 76 + m_Height: 93 + - m_X: 895 + m_Y: 0 + m_Width: 76 + m_Height: 93 + - m_X: 971 + m_Y: 0 + m_Width: 47 + m_Height: 94 + - m_X: 93 + m_Y: 78 + m_Width: 105 + m_Height: 25 + - m_X: 78 + m_Y: 103 + m_Width: 76 + m_Height: 91 + - m_X: 78 + m_Y: 194 + m_Width: 73 + m_Height: 93 + - m_X: 78 + m_Y: 287 + m_Width: 69 + m_Height: 95 + - m_X: 78 + m_Y: 382 + m_Width: 69 + m_Height: 94 + - m_X: 78 + m_Y: 476 + m_Width: 69 + m_Height: 94 + - m_X: 74 + m_Y: 570 + m_Width: 66 + m_Height: 93 + - m_X: 76 + m_Y: 663 + m_Width: 60 + m_Height: 100 + - m_X: 76 + m_Y: 763 + m_Width: 59 + m_Height: 99 + - m_X: 76 + m_Y: 862 + m_Width: 59 + m_Height: 83 + - m_X: 87 + m_Y: 945 + m_Width: 78 + m_Height: 78 + - m_X: 154 + m_Y: 103 + m_Width: 46 + m_Height: 99 + - m_X: 200 + m_Y: 78 + m_Width: 67 + m_Height: 94 + - m_X: 151 + m_Y: 202 + m_Width: 66 + m_Height: 89 + - m_X: 147 + m_Y: 291 + m_Width: 69 + m_Height: 92 + - m_X: 147 + m_Y: 383 + m_Width: 66 + m_Height: 94 + - m_X: 147 + m_Y: 477 + m_Width: 66 + m_Height: 93 + - m_X: 140 + m_Y: 570 + m_Width: 66 + m_Height: 91 + - m_X: 267 + m_Y: 80 + m_Width: 80 + m_Height: 80 + - m_X: 347 + m_Y: 80 + m_Width: 80 + m_Height: 80 + - m_X: 427 + m_Y: 80 + m_Width: 72 + m_Height: 80 + - m_X: 499 + m_Y: 78 + m_Width: 74 + m_Height: 80 + - m_X: 573 + m_Y: 79 + m_Width: 78 + m_Height: 80 + - m_X: 651 + m_Y: 84 + m_Width: 90 + m_Height: 66 + - m_X: 741 + m_Y: 92 + m_Width: 77 + m_Height: 78 + - m_X: 818 + m_Y: 93 + m_Width: 76 + m_Height: 78 + - m_X: 894 + m_Y: 93 + m_Width: 76 + m_Height: 80 + - m_X: 970 + m_Y: 94 + m_Width: 48 + m_Height: 81 + - m_X: 267 + m_Y: 160 + m_Width: 105 + m_Height: 25 + - m_X: 217 + m_Y: 172 + m_Width: 46 + m_Height: 99 + - m_X: 263 + m_Y: 185 + m_Width: 76 + m_Height: 78 + - m_X: 372 + m_Y: 160 + m_Width: 89 + m_Height: 52 + - m_X: 339 + m_Y: 185 + m_Width: 29 + m_Height: 78 + - m_X: 368 + m_Y: 212 + m_Width: 83 + m_Height: 65 + - m_X: 136 + m_Y: 663 + m_Width: 43 + m_Height: 99 + - m_X: 179 + m_Y: 661 + m_Width: 43 + m_Height: 99 + - m_X: 206 + m_Y: 570 + m_Width: 44 + m_Height: 91 + - m_X: 222 + m_Y: 661 + m_Width: 37 + m_Height: 99 + - m_X: 213 + m_Y: 383 + m_Width: 37 + m_Height: 99 + - m_X: 213 + m_Y: 482 + m_Width: 59 + m_Height: 88 + - m_X: 250 + m_Y: 570 + m_Width: 64 + m_Height: 90 + - m_X: 259 + m_Y: 660 + m_Width: 60 + m_Height: 96 + - m_X: 135 + m_Y: 763 + m_Width: 36 + m_Height: 99 + - m_X: 135 + m_Y: 862 + m_Width: 59 + m_Height: 83 + - m_X: 165 + m_Y: 945 + m_Width: 75 + m_Height: 78 + - m_X: 171 + m_Y: 762 + m_Width: 27 + m_Height: 99 + - m_X: 198 + m_Y: 760 + m_Width: 59 + m_Height: 89 + - m_X: 194 + m_Y: 861 + m_Width: 23 + m_Height: 84 + - m_X: 217 + m_Y: 849 + m_Width: 38 + m_Height: 93 + - m_X: 240 + m_Y: 942 + m_Width: 64 + m_Height: 81 + - m_X: 255 + m_Y: 849 + m_Width: 38 + m_Height: 93 + - m_X: 257 + m_Y: 760 + m_Width: 39 + m_Height: 89 + - m_X: 296 + m_Y: 756 + m_Width: 27 + m_Height: 99 + - m_X: 293 + m_Y: 855 + m_Width: 57 + m_Height: 87 + - m_X: 304 + m_Y: 942 + m_Width: 61 + m_Height: 81 + - m_X: 651 + m_Y: 150 + m_Width: 83 + m_Height: 28 + - m_X: 461 + m_Y: 160 + m_Width: 67 + m_Height: 78 + - m_X: 528 + m_Y: 158 + m_Width: 44 + m_Height: 81 + - m_X: 572 + m_Y: 159 + m_Width: 73 + m_Height: 78 + - m_X: 645 + m_Y: 178 + m_Width: 82 + m_Height: 64 + - m_X: 451 + m_Y: 238 + m_Width: 71 + m_Height: 78 + - m_X: 522 + m_Y: 239 + m_Width: 61 + m_Height: 80 + - m_X: 583 + m_Y: 237 + m_Width: 62 + m_Height: 82 + - m_X: 645 + m_Y: 242 + m_Width: 70 + m_Height: 78 + - m_X: 216 + m_Y: 319 + m_Width: 62 + m_Height: 64 + - m_X: 217 + m_Y: 271 + m_Width: 61 + m_Height: 48 + - m_X: 278 + m_Y: 263 + m_Width: 70 + m_Height: 80 + - m_X: 250 + m_Y: 383 + m_Width: 40 + m_Height: 89 + - m_X: 348 + m_Y: 277 + m_Width: 71 + m_Height: 70 + - m_X: 278 + m_Y: 343 + m_Width: 70 + m_Height: 34 + - m_X: 290 + m_Y: 377 + m_Width: 57 + m_Height: 87 + - m_X: 419 + m_Y: 277 + m_Width: 29 + m_Height: 76 + - m_X: 448 + m_Y: 316 + m_Width: 69 + m_Height: 78 + - m_X: 517 + m_Y: 319 + m_Width: 69 + m_Height: 78 + - m_X: 586 + m_Y: 319 + m_Width: 59 + m_Height: 79 + - m_X: 645 + m_Y: 320 + m_Width: 69 + m_Height: 79 + - m_X: 348 + m_Y: 347 + m_Width: 69 + m_Height: 78 + - m_X: 417 + m_Y: 353 + m_Width: 31 + m_Height: 41 + - m_X: 347 + m_Y: 425 + m_Width: 69 + m_Height: 68 + - m_X: 417 + m_Y: 394 + m_Width: 68 + m_Height: 78 + - m_X: 485 + m_Y: 397 + m_Width: 67 + m_Height: 78 + - m_X: 552 + m_Y: 398 + m_Width: 67 + m_Height: 78 + - m_X: 619 + m_Y: 399 + m_Width: 66 + m_Height: 78 + - m_X: 685 + m_Y: 399 + m_Width: 43 + m_Height: 82 + - m_X: 272 + m_Y: 472 + m_Width: 40 + m_Height: 89 + - m_X: 312 + m_Y: 464 + m_Width: 29 + m_Height: 81 + - m_X: 341 + m_Y: 493 + m_Width: 66 + m_Height: 80 + - m_X: 314 + m_Y: 573 + m_Width: 64 + m_Height: 83 + - m_X: 319 + m_Y: 656 + m_Width: 59 + m_Height: 83 + - m_X: 323 + m_Y: 739 + m_Width: 64 + m_Height: 83 + - m_X: 378 + m_Y: 573 + m_Width: 39 + m_Height: 89 + - m_X: 378 + m_Y: 662 + m_Width: 42 + m_Height: 75 + - m_X: 387 + m_Y: 737 + m_Width: 39 + m_Height: 89 + - m_X: 407 + m_Y: 493 + m_Width: 61 + m_Height: 80 + - m_X: 417 + m_Y: 573 + m_Width: 57 + m_Height: 83 + - m_X: 420 + m_Y: 656 + m_Width: 57 + m_Height: 81 + - m_X: 426 + m_Y: 737 + m_Width: 61 + m_Height: 83 + - m_X: 468 + m_Y: 475 + m_Width: 64 + m_Height: 82 + - m_X: 474 + m_Y: 557 + m_Width: 61 + m_Height: 83 + - m_X: 477 + m_Y: 640 + m_Width: 61 + m_Height: 83 + - m_X: 532 + m_Y: 476 + m_Width: 65 + m_Height: 78 + - m_X: 535 + m_Y: 554 + m_Width: 63 + m_Height: 82 + - m_X: 538 + m_Y: 636 + m_Width: 61 + m_Height: 83 + - m_X: 487 + m_Y: 723 + m_Width: 61 + m_Height: 83 + - m_X: 548 + m_Y: 719 + m_Width: 57 + m_Height: 83 + - m_X: 597 + m_Y: 477 + m_Width: 62 + m_Height: 71 + - m_X: 598 + m_Y: 548 + m_Width: 61 + m_Height: 82 + - m_X: 599 + m_Y: 630 + m_Width: 60 + m_Height: 82 + - m_X: 605 + m_Y: 712 + m_Width: 57 + m_Height: 83 + - m_X: 659 + m_Y: 481 + m_Width: 65 + m_Height: 78 + - m_X: 659 + m_Y: 559 + m_Width: 64 + m_Height: 79 + - m_X: 659 + m_Y: 638 + m_Width: 64 + m_Height: 66 + - m_X: 662 + m_Y: 704 + m_Width: 61 + m_Height: 82 + - m_X: 714 + m_Y: 320 + m_Width: 61 + m_Height: 79 + - m_X: 715 + m_Y: 242 + m_Width: 64 + m_Height: 78 + - m_X: 728 + m_Y: 399 + m_Width: 59 + m_Height: 82 + - m_X: 724 + m_Y: 481 + m_Width: 65 + m_Height: 78 + - m_X: 723 + m_Y: 559 + m_Width: 64 + m_Height: 79 + - m_X: 723 + m_Y: 638 + m_Width: 61 + m_Height: 80 + - m_X: 723 + m_Y: 718 + m_Width: 61 + m_Height: 79 + - m_X: 727 + m_Y: 178 + m_Width: 62 + m_Height: 64 + - m_X: 789 + m_Y: 171 + m_Width: 63 + m_Height: 78 + - m_X: 779 + m_Y: 249 + m_Width: 62 + m_Height: 78 + - m_X: 775 + m_Y: 327 + m_Width: 61 + m_Height: 66 + - m_X: 787 + m_Y: 393 + m_Width: 59 + m_Height: 82 + - m_X: 789 + m_Y: 475 + m_Width: 57 + m_Height: 82 + - m_X: 852 + m_Y: 171 + m_Width: 41 + m_Height: 81 + - m_X: 893 + m_Y: 173 + m_Width: 62 + m_Height: 79 + - m_X: 841 + m_Y: 252 + m_Width: 61 + m_Height: 79 + - m_X: 902 + m_Y: 252 + m_Width: 60 + m_Height: 80 + - m_X: 962 + m_Y: 175 + m_Width: 61 + m_Height: 79 + - m_X: 962 + m_Y: 254 + m_Width: 61 + m_Height: 66 + - m_X: 962 + m_Y: 320 + m_Width: 61 + m_Height: 62 + - m_X: 836 + m_Y: 331 + m_Width: 61 + m_Height: 62 + - m_X: 846 + m_Y: 393 + m_Width: 59 + m_Height: 81 + - m_X: 846 + m_Y: 474 + m_Width: 59 + m_Height: 80 + - m_X: 905 + m_Y: 332 + m_Width: 57 + m_Height: 80 + - m_X: 962 + m_Y: 382 + m_Width: 61 + m_Height: 62 + - m_X: 905 + m_Y: 412 + m_Width: 57 + m_Height: 79 + - m_X: 962 + m_Y: 444 + m_Width: 61 + m_Height: 53 + - m_X: 905 + m_Y: 491 + m_Width: 57 + m_Height: 78 + - m_X: 962 + m_Y: 497 + m_Width: 61 + m_Height: 53 + - m_X: 962 + m_Y: 550 + m_Width: 61 + m_Height: 43 + - m_X: 323 + m_Y: 822 + m_Width: 63 + m_Height: 30 + - m_X: 350 + m_Y: 852 + m_Width: 39 + m_Height: 89 + - m_X: 365 + m_Y: 941 + m_Width: 43 + m_Height: 82 + - m_X: 389 + m_Y: 826 + m_Width: 39 + m_Height: 89 + - m_X: 428 + m_Y: 820 + m_Width: 59 + m_Height: 78 + - m_X: 487 + m_Y: 806 + m_Width: 58 + m_Height: 78 + - m_X: 784 + m_Y: 638 + m_Width: 39 + m_Height: 89 + - m_X: 787 + m_Y: 559 + m_Width: 55 + m_Height: 79 + - m_X: 784 + m_Y: 727 + m_Width: 44 + m_Height: 78 + - m_X: 823 + m_Y: 638 + m_Width: 41 + m_Height: 89 + - m_X: 828 + m_Y: 727 + m_Width: 38 + m_Height: 82 + - m_X: 842 + m_Y: 557 + m_Width: 28 + m_Height: 81 + - m_X: 870 + m_Y: 554 + m_Width: 28 + m_Height: 81 + - m_X: 898 + m_Y: 569 + m_Width: 57 + m_Height: 66 + - m_X: 955 + m_Y: 593 + m_Width: 62 + m_Height: 58 + - m_X: 864 + m_Y: 638 + m_Width: 41 + m_Height: 89 + - m_X: 905 + m_Y: 635 + m_Width: 41 + m_Height: 89 + - m_X: 946 + m_Y: 651 + m_Width: 57 + m_Height: 79 + - m_X: 866 + m_Y: 727 + m_Width: 40 + m_Height: 82 + - m_X: 906 + m_Y: 724 + m_Width: 40 + m_Height: 82 + - m_X: 946 + m_Y: 730 + m_Width: 57 + m_Height: 66 + - m_X: 389 + m_Y: 915 + m_Width: 42 + m_Height: 26 + - m_X: 408 + m_Y: 941 + m_Width: 38 + m_Height: 82 + - m_X: 446 + m_Y: 898 + m_Width: 39 + m_Height: 89 + - m_X: 545 + m_Y: 806 + m_Width: 28 + m_Height: 78 + - m_X: 573 + m_Y: 802 + m_Width: 47 + m_Height: 78 + - m_X: 620 + m_Y: 795 + m_Width: 57 + m_Height: 65 + - m_X: 677 + m_Y: 786 + m_Width: 46 + m_Height: 56 + - m_X: 723 + m_Y: 797 + m_Width: 59 + m_Height: 59 + - m_X: 782 + m_Y: 805 + m_Width: 46 + m_Height: 55 + - m_X: 828 + m_Y: 809 + m_Width: 59 + m_Height: 58 + - m_X: 487 + m_Y: 884 + m_Width: 70 + m_Height: 25 + - m_X: 485 + m_Y: 909 + m_Width: 57 + m_Height: 65 + - m_X: 485 + m_Y: 974 + m_Width: 50 + m_Height: 49 + - m_X: 542 + m_Y: 909 + m_Width: 28 + m_Height: 78 + - m_X: 887 + m_Y: 809 + m_Width: 29 + m_Height: 64 + - m_X: 916 + m_Y: 806 + m_Width: 42 + m_Height: 65 + - m_X: 958 + m_Y: 796 + m_Width: 54 + m_Height: 64 + - m_X: 620 + m_Y: 860 + m_Width: 57 + m_Height: 50 + - m_X: 677 + m_Y: 842 + m_Width: 43 + m_Height: 54 + - m_X: 720 + m_Y: 856 + m_Width: 54 + m_Height: 41 + - m_X: 774 + m_Y: 860 + m_Width: 51 + m_Height: 52 + - m_X: 825 + m_Y: 867 + m_Width: 48 + m_Height: 52 + - m_X: 873 + m_Y: 873 + m_Width: 42 + m_Height: 53 + - m_X: 446 + m_Y: 987 + m_Width: 38 + m_Height: 32 + - m_X: 958 + m_Y: 860 + m_Width: 54 + m_Height: 24 + - m_X: 535 + m_Y: 987 + m_Width: 38 + m_Height: 32 + - m_X: 677 + m_Y: 896 + m_Width: 43 + m_Height: 43 + - m_X: 720 + m_Y: 897 + m_Width: 45 + m_Height: 41 + - m_X: 765 + m_Y: 912 + m_Width: 44 + m_Height: 38 + - m_X: 809 + m_Y: 919 + m_Width: 43 + m_Height: 42 + - m_X: 852 + m_Y: 926 + m_Width: 67 + m_Height: 25 + - m_X: 852 + m_Y: 951 + m_Width: 69 + m_Height: 23 + - m_X: 915 + m_Y: 873 + m_Width: 42 + m_Height: 53 + - m_X: 957 + m_Y: 884 + m_Width: 42 + m_Height: 38 + - m_X: 919 + m_Y: 926 + m_Width: 67 + m_Height: 25 + - m_X: 921 + m_Y: 951 + m_Width: 44 + m_Height: 27 + - m_X: 965 + m_Y: 951 + m_Width: 27 + m_Height: 38 + - m_X: 573 + m_Y: 880 + m_Width: 42 + m_Height: 26 + - m_X: 570 + m_Y: 906 + m_Width: 42 + m_Height: 38 + - m_X: 570 + m_Y: 944 + m_Width: 42 + m_Height: 38 + - m_X: 612 + m_Y: 910 + m_Width: 41 + m_Height: 38 + - m_X: 612 + m_Y: 948 + m_Width: 35 + m_Height: 37 + - m_X: 573 + m_Y: 982 + m_Width: 29 + m_Height: 39 + - m_X: 602 + m_Y: 985 + m_Width: 28 + m_Height: 38 + - m_X: 630 + m_Y: 985 + m_Width: 28 + m_Height: 38 + - m_X: 986 + m_Y: 922 + m_Width: 29 + m_Height: 29 + - m_X: 992 + m_Y: 951 + m_Width: 28 + m_Height: 38 + - m_X: 647 + m_Y: 948 + m_Width: 29 + m_Height: 28 + - m_X: 676 + m_Y: 939 + m_Width: 28 + m_Height: 38 + m_FreeGlyphRects: + - m_X: 78 + m_Y: 93 + m_Width: 15 + m_Height: 10 + - m_X: 74 + m_Y: 566 + m_Width: 4 + m_Height: 4 + - m_X: 198 + m_Y: 78 + m_Width: 2 + m_Height: 25 + - m_X: 151 + m_Y: 194 + m_Width: 3 + m_Height: 8 + - m_X: 147 + m_Y: 287 + m_Width: 4 + m_Height: 4 + - m_X: 267 + m_Y: 78 + m_Width: 31 + m_Height: 2 + - m_X: 488 + m_Y: 78 + m_Width: 11 + m_Height: 2 + - m_X: 573 + m_Y: 78 + m_Width: 1 + m_Height: 1 + - m_X: 651 + m_Y: 79 + m_Width: 8 + m_Height: 5 + - m_X: 818 + m_Y: 92 + m_Width: 1 + m_Height: 1 + - m_X: 970 + m_Y: 93 + m_Width: 1 + m_Height: 1 + - m_X: 200 + m_Y: 172 + m_Width: 17 + m_Height: 30 + - m_X: 263 + m_Y: 172 + m_Width: 4 + m_Height: 13 + - m_X: 368 + m_Y: 185 + m_Width: 4 + m_Height: 27 + - m_X: 140 + m_Y: 661 + m_Width: 39 + m_Height: 2 + - m_X: 250 + m_Y: 660 + m_Width: 9 + m_Height: 1 + - m_X: 136 + m_Y: 762 + m_Width: 35 + m_Height: 1 + - m_X: 179 + m_Y: 760 + m_Width: 19 + m_Height: 2 + - m_X: 171 + m_Y: 861 + m_Width: 23 + m_Height: 1 + - m_X: 198 + m_Y: 849 + m_Width: 19 + m_Height: 12 + - m_X: 217 + m_Y: 942 + m_Width: 23 + m_Height: 3 + - m_X: 259 + m_Y: 756 + m_Width: 37 + m_Height: 4 + - m_X: 293 + m_Y: 849 + m_Width: 3 + m_Height: 6 + - m_X: 499 + m_Y: 158 + m_Width: 29 + m_Height: 2 + - m_X: 572 + m_Y: 158 + m_Width: 1 + m_Height: 1 + - m_X: 645 + m_Y: 159 + m_Width: 6 + m_Height: 19 + - m_X: 451 + m_Y: 212 + m_Width: 10 + m_Height: 26 + - m_X: 522 + m_Y: 238 + m_Width: 6 + m_Height: 1 + - m_X: 572 + m_Y: 237 + m_Width: 11 + m_Height: 2 + - m_X: 216 + m_Y: 291 + m_Width: 1 + m_Height: 28 + - m_X: 263 + m_Y: 263 + m_Width: 15 + m_Height: 8 + - m_X: 348 + m_Y: 263 + m_Width: 20 + m_Height: 14 + - m_X: 278 + m_Y: 377 + m_Width: 12 + m_Height: 6 + - m_X: 448 + m_Y: 277 + m_Width: 3 + m_Height: 39 + - m_X: 517 + m_Y: 316 + m_Width: 5 + m_Height: 3 + - m_X: 417 + m_Y: 347 + m_Width: 2 + m_Height: 6 + - m_X: 347 + m_Y: 377 + m_Width: 1 + m_Height: 48 + - m_X: 485 + m_Y: 394 + m_Width: 32 + m_Height: 3 + - m_X: 552 + m_Y: 397 + m_Width: 34 + m_Height: 1 + - m_X: 619 + m_Y: 398 + m_Width: 26 + m_Height: 1 + - m_X: 250 + m_Y: 472 + m_Width: 22 + m_Height: 10 + - m_X: 290 + m_Y: 464 + m_Width: 22 + m_Height: 8 + - m_X: 272 + m_Y: 561 + m_Width: 69 + m_Height: 9 + - m_X: 341 + m_Y: 464 + m_Width: 6 + m_Height: 29 + - m_X: 312 + m_Y: 545 + m_Width: 29 + m_Height: 25 + - m_X: 314 + m_Y: 545 + m_Width: 27 + m_Height: 28 + - m_X: 314 + m_Y: 656 + m_Width: 5 + m_Height: 4 + - m_X: 319 + m_Y: 739 + m_Width: 4 + m_Height: 17 + - m_X: 378 + m_Y: 737 + m_Width: 9 + m_Height: 2 + - m_X: 416 + m_Y: 425 + m_Width: 1 + m_Height: 68 + - m_X: 417 + m_Y: 656 + m_Width: 3 + m_Height: 6 + - m_X: 416 + m_Y: 472 + m_Width: 69 + m_Height: 3 + - m_X: 416 + m_Y: 472 + m_Width: 52 + m_Height: 21 + - m_X: 468 + m_Y: 557 + m_Width: 6 + m_Height: 16 + - m_X: 474 + m_Y: 640 + m_Width: 3 + m_Height: 16 + - m_X: 532 + m_Y: 475 + m_Width: 20 + m_Height: 1 + - m_X: 532 + m_Y: 554 + m_Width: 3 + m_Height: 3 + - m_X: 535 + m_Y: 636 + m_Width: 3 + m_Height: 4 + - m_X: 477 + m_Y: 723 + m_Width: 10 + m_Height: 14 + - m_X: 538 + m_Y: 719 + m_Width: 10 + m_Height: 4 + - m_X: 597 + m_Y: 476 + m_Width: 22 + m_Height: 1 + - m_X: 597 + m_Y: 548 + m_Width: 1 + m_Height: 6 + - m_X: 598 + m_Y: 630 + m_Width: 1 + m_Height: 6 + - m_X: 599 + m_Y: 712 + m_Width: 6 + m_Height: 7 + - m_X: 659 + m_Y: 477 + m_Width: 26 + m_Height: 4 + - m_X: 659 + m_Y: 704 + m_Width: 3 + m_Height: 8 + - m_X: 734 + m_Y: 150 + m_Width: 7 + m_Height: 28 + - m_X: 734 + m_Y: 170 + m_Width: 84 + m_Height: 1 + - m_X: 734 + m_Y: 170 + m_Width: 55 + m_Height: 8 + - m_X: 779 + m_Y: 242 + m_Width: 10 + m_Height: 7 + - m_X: 775 + m_Y: 320 + m_Width: 4 + m_Height: 7 + - m_X: 775 + m_Y: 393 + m_Width: 12 + m_Height: 6 + - m_X: 787 + m_Y: 475 + m_Width: 2 + m_Height: 6 + - m_X: 893 + m_Y: 171 + m_Width: 1 + m_Height: 2 + - m_X: 841 + m_Y: 249 + m_Width: 11 + m_Height: 3 + - m_X: 1018 + m_Y: 0 + m_Width: 5 + m_Height: 175 + - m_X: 955 + m_Y: 173 + m_Width: 15 + m_Height: 2 + - m_X: 955 + m_Y: 173 + m_Width: 7 + m_Height: 79 + - m_X: 836 + m_Y: 327 + m_Width: 5 + m_Height: 4 + - m_X: 897 + m_Y: 331 + m_Width: 5 + m_Height: 62 + - m_X: 897 + m_Y: 332 + m_Width: 8 + m_Height: 61 + - m_X: 386 + m_Y: 822 + m_Width: 1 + m_Height: 30 + - m_X: 323 + m_Y: 852 + m_Width: 27 + m_Height: 3 + - m_X: 350 + m_Y: 941 + m_Width: 15 + m_Height: 1 + - m_X: 386 + m_Y: 826 + m_Width: 3 + m_Height: 26 + - m_X: 426 + m_Y: 820 + m_Width: 2 + m_Height: 6 + - m_X: 789 + m_Y: 557 + m_Width: 53 + m_Height: 2 + - m_X: 846 + m_Y: 554 + m_Width: 24 + m_Height: 3 + - m_X: 898 + m_Y: 554 + m_Width: 7 + m_Height: 15 + - m_X: 955 + m_Y: 569 + m_Width: 7 + m_Height: 24 + - m_X: 870 + m_Y: 635 + m_Width: 35 + m_Height: 3 + - m_X: 946 + m_Y: 635 + m_Width: 9 + m_Height: 16 + - m_X: 905 + m_Y: 724 + m_Width: 1 + m_Height: 3 + - m_X: 428 + m_Y: 898 + m_Width: 18 + m_Height: 17 + - m_X: 431 + m_Y: 898 + m_Width: 15 + m_Height: 43 + - m_X: 548 + m_Y: 802 + m_Width: 25 + m_Height: 4 + - m_X: 605 + m_Y: 795 + m_Width: 15 + m_Height: 7 + - m_X: 662 + m_Y: 786 + m_Width: 15 + m_Height: 9 + - m_X: 782 + m_Y: 797 + m_Width: 2 + m_Height: 8 + - m_X: 485 + m_Y: 898 + m_Width: 2 + m_Height: 11 + - m_X: 906 + m_Y: 806 + m_Width: 10 + m_Height: 3 + - m_X: 1003 + m_Y: 651 + m_Width: 20 + m_Height: 145 + - m_X: 946 + m_Y: 796 + m_Width: 12 + m_Height: 10 + - m_X: 720 + m_Y: 842 + m_Width: 3 + m_Height: 14 + - m_X: 774 + m_Y: 856 + m_Width: 8 + m_Height: 4 + - m_X: 825 + m_Y: 860 + m_Width: 3 + m_Height: 7 + - m_X: 873 + m_Y: 867 + m_Width: 14 + m_Height: 6 + - m_X: 446 + m_Y: 1019 + m_Width: 39 + m_Height: 4 + - m_X: 484 + m_Y: 987 + m_Width: 1 + m_Height: 36 + - m_X: 535 + m_Y: 974 + m_Width: 7 + m_Height: 13 + - m_X: 765 + m_Y: 897 + m_Width: 9 + m_Height: 15 + - m_X: 720 + m_Y: 938 + m_Width: 45 + m_Height: 85 + - m_X: 809 + m_Y: 912 + m_Width: 16 + m_Height: 7 + - m_X: 852 + m_Y: 919 + m_Width: 21 + m_Height: 7 + - m_X: 916 + m_Y: 871 + m_Width: 42 + m_Height: 2 + - m_X: 957 + m_Y: 871 + m_Width: 1 + m_Height: 13 + - m_X: 557 + m_Y: 884 + m_Width: 16 + m_Height: 22 + - m_X: 557 + m_Y: 884 + m_Width: 13 + m_Height: 25 + - m_X: 615 + m_Y: 880 + m_Width: 5 + m_Height: 30 + - m_X: 612 + m_Y: 906 + m_Width: 8 + m_Height: 4 + - m_X: 535 + m_Y: 1019 + m_Width: 38 + m_Height: 4 + - m_X: 570 + m_Y: 982 + m_Width: 3 + m_Height: 5 + - m_X: 535 + m_Y: 1021 + m_Width: 67 + m_Height: 2 + - m_X: 602 + m_Y: 982 + m_Width: 10 + m_Height: 3 + - m_X: 647 + m_Y: 978 + m_Width: 318 + m_Height: 7 + - m_X: 658 + m_Y: 978 + m_Width: 307 + m_Height: 45 + - m_X: 658 + m_Y: 989 + m_Width: 365 + m_Height: 34 + - m_X: 1012 + m_Y: 651 + m_Width: 11 + m_Height: 271 + - m_X: 999 + m_Y: 884 + m_Width: 24 + m_Height: 38 + - m_X: 957 + m_Y: 922 + m_Width: 29 + m_Height: 4 + - m_X: 1017 + m_Y: 593 + m_Width: 6 + m_Height: 358 + - m_X: 1020 + m_Y: 593 + m_Width: 3 + m_Height: 430 + - m_X: 1015 + m_Y: 651 + m_Width: 8 + m_Height: 300 + - m_X: 653 + m_Y: 910 + m_Width: 24 + m_Height: 29 + - m_X: 653 + m_Y: 910 + m_Width: 23 + m_Height: 38 + - m_X: 704 + m_Y: 939 + m_Width: 61 + m_Height: 84 + - m_X: 704 + m_Y: 950 + m_Width: 105 + m_Height: 73 + - m_X: 704 + m_Y: 961 + m_Width: 148 + m_Height: 62 + - m_X: 647 + m_Y: 977 + m_Width: 274 + m_Height: 8 + - m_X: 647 + m_Y: 976 + m_Width: 29 + m_Height: 9 + - m_X: 658 + m_Y: 977 + m_Width: 263 + m_Height: 46 + - m_X: 658 + m_Y: 976 + m_Width: 18 + m_Height: 47 + - m_X: 704 + m_Y: 974 + m_Width: 217 + m_Height: 49 + m_fontInfo: + Name: Liberation Sans + PointSize: 86 + Scale: 1 + CharacterCount: 250 + LineHeight: 98.90625 + Baseline: 0 + Ascender: 77.84375 + CapHeight: 59.1875 + Descender: -18.21875 + CenterLine: 0 + SuperscriptOffset: 77.84375 + SubscriptOffset: -12.261719 + SubSize: 0.5 + Underline: -12.261719 + UnderlineThickness: 6.298828 + strikethrough: 23.675 + strikethroughThickness: 0 + TabWidth: 239.0625 + Padding: 9 + AtlasWidth: 1024 + AtlasHeight: 1024 + atlas: {fileID: 0} + m_AtlasWidth: 1024 + m_AtlasHeight: 1024 + m_AtlasPadding: 9 + m_AtlasRenderMode: 4169 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_GlyphPairAdjustmentRecords: + - m_FirstAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 20 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 20 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 89 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 90 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 92 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 2020 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 41 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 41 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 41 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 47 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 47 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 47 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 47 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 47 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 47 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 92 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 47 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 2020 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 51 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 51 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -11.09375 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 51 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -11.09375 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 51 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 53 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 53 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 53 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 53 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 16 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 29 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 30 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 50 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 68 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 70 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 72 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 76 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 82 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 85 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -9.53125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 86 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 88 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 90 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 55 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 92 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -7.890625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 16 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -7.890625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 29 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 30 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 68 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 72 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 76 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 82 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 85 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 88 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 57 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 92 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 16 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 29 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 30 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 68 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 72 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 82 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 85 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 88 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 58 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -0.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 92 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -11.09375 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -7.890625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 16 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -11.09375 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 29 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -5.578125 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 30 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 36 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 68 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -7.890625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 72 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 76 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -7.890625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 82 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 83 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -7.890625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 84 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 88 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 60 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 89 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 73 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 73 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 73 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 2020 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 85 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 85 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 85 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 2020 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 89 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 89 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 90 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 90 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -4.75 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 92 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 15 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 92 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -6.390625 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 17 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 2019 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 2019 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 2020 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -3.1875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 3 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 2020 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 86 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + - m_FirstAdjustmentRecord: + m_GlyphIndex: 2020 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: -1.546875 + m_YAdvance: 0 + m_SecondAdjustmentRecord: + m_GlyphIndex: 2020 + m_GlyphValueRecord: + m_XPlacement: 0 + m_YPlacement: 0 + m_XAdvance: 0 + m_YAdvance: 0 + m_FeatureLookupFlags: 0 + fallbackFontAssets: [] + m_FallbackFontAssetTable: + - {fileID: 11400000, guid: 2e498d1c8094910479dc3e1b768306a4, type: 2} + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 + pointSizeSamplingMode: 0 + pointSize: 86 + padding: 9 + packingMode: 4 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 1 + characterSequence: 32 - 126, 160 - 255, 8192 - 8303, 8364, 8482, 9633 + referencedFontAssetGUID: 8f586378b4e144a9851e7b34d9b748ee + referencedTextAssetGUID: + fontStyle: 0 + fontStyleModifier: 0 + renderMode: 4169 + includeFontFeatures: 1 + m_FontWeightTable: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + fontWeights: + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + - regularTypeface: {fileID: 0} + italicTypeface: {fileID: 0} + normalStyle: 0 + normalSpacingOffset: 0 + boldStyle: 0.75 + boldSpacing: 7 + italicStyle: 35 + tabSize: 10 +--- !u!28 &28684132378477856 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LiberationSans SDF Atlas + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + serializedVersion: 2 + m_Width: 1024 + m_Height: 1024 + m_CompleteImageSize: 1048576 + m_TextureFormat: 1 + m_MipCount: 1 + m_IsReadable: 0 + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: -92 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 0 + m_WrapV: 0 + m_WrapW: 0 + m_LightmapFormat: 0 + m_ColorSpace: 0 + image data: 1048576 + _typelessdata: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040607090b0d0f101112121313131212100f0e0c0a08060603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407090a1313131313131313130e0d0b08030000000000000000000000000000000000000002070a0c0d1313131313131313130b0a0805000000000000000000000000000000000000000000000000000000000000050a0d0f10131313131313130e0d0b0803000000000000000000000000000000000000000000000004080a0a13131313131313131313131313131313131313131313131313131313131313131313131313131313130a09070400000000000000000000000000000000000000000006060606060600000000000000000000000000000000000000000000020507080c0f1112131211100c080806020000000000000000000000030607090d1011121312110e0a070604010000000000000000000000000000000000000000000000000000000000000000000000000606060606060000000000000000000000000000000000000000000000000000000000010507070c0f1112131312100c08080602000000000000000000000000000000000000000000000000000000000000000000030608091313131313120707050100000000000000000000000000000000000000000000000000000000000105070713131313130c0b09060100000000000000000000000000000000000000000000000000000000000306080913131313131207070501000000000000000000000000000000000000000000000000000000000105070713131313130c0b09060100000000000000000000000000000000000004080a0a0b0b0b0b0b0b0b07060401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030607090b0d0f1111121313121211100f0d0a0807050200000000000000000000000000000000000000000000000000000000000000000003080c0e0e131313131313130f0e0c09040000000000000000000000000000000000000000000000000000000000000003070b0d0e131313131313130e0e0c0803000000000000000000000003080c0e0e131313131313130f0e0c09040000000000000000000000000000000000000000000000000000000000000003070b0d0e131313131313130e0e0c080300000000000000000000000000000000000000000000040613131313131313131312110e09040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205070c10131315171a1c1d1e1e1f20201f1f1e1d1c1b19171513120f0b06060401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b101316172020202020202020201b1a18140f080100000000000000000000000000000000070e1317191a202020202020202020181715110c060000000000000000000000000000000000000000000000000000030a10161a1c1d202020202020201b1a18140f080100000000000000000000000000000000000000050b101416172020202020202020202020202020202020202020202020202020202020202020202020202020202020171614100b0500000000000000000000000000000106090b0c131313131313080705020000000000000000000000000000000002090e111414181c1e1f201f1e1c191514120e090300000000000000060b101213161a1d1e1f201e1d1b171413110d0701000000000000000000000000000000000000000000000000000000000000030608091313131313130b0a0805000000000000000000000000000000000000000000000002080d111314191c1e1f201f1e1c191514120e09030000000000000000000000000000000000000000000000000000000000040a0f12151520202020201f1413110d08020000000000000000000000000000000000000000000000000002080d1113142020202020191815120d060000000000000000000000000000000000000000000000000000040a0f12151520202020201f1413110d080200000000000000000000000000000000000000000000000002080d1113142020202020191815120d06000000000000000000000000000000050b10141617181818181818181413110d07010000000000000000000001030405060606060504040200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104060b10121315171a1c1d1e1f1f201f1f1e1d1b19171514120e0906030000000000000000000000000000000000000000000000000000000001090f14181a1b202020202020201c1b191510090200000000000000000000000000000000000000000000000000000001080e1317191a202020202020201b1a18140f09010000000000000001090f14181a1b202020202020201c1b191510090200000000000000000000000000000000000000000000000000000001080e1317191a202020202020201b1a18140f0901000000000000000000000000000000000001070c10132020202020202020201f1d1a150f0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104090e1214181c1f20222426282a2a2b2c2c2c2c2c2b2a2927262422201f1c171413110d0705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f161c2022232d2d2d2d2d2d2d2d2d282724201a130b0200000000000000000000000000010a12191f2326272d2d2d2d2d2d2d2d2d2424211d171009000000000000000000000000000000000000000000000000040d151c2126292a2d2d2d2d2d2d2d2727241f1a130b0200000000000000000000000000000000000810171c2023242d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423201c161008000000000000000000000000060d1215181920202020201f1514120e090300000000000000000000000002080e141a1e202125292a2b2c2c2b292622211e1a150e0903000000020a11171c1f2023272a2b2c2c2b2a282420201d18130c07000000000000000000000000000000000000000000000000000000030a0f121515202020202020181715110c060000000000000000000000000000000000000002080d13191e202125292b2c2d2c2b292622211e1a150e09030000000000000000000000000000000000000000000000000000060e151b1f21222c2d2d2d2d2c21201d19130c040000000000000000000000000000000000000000000000050c13191d20212d2d2d2d2d2524221e181109010000000000000000000000000000000000000000000000060e151b1f21222c2d2d2d2d2c21201d19130c0400000000000000000000000000000000000000000000050c13191d20212d2d2d2d2d2524221e181109010000000000000000000000000810171c2023242525252525252520201d18130c0400000000030607090b0e0f1112121313121211100f0d0a0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070d1113171c1f20222426292a2b2b2c2c2c2b2b2a28262422211e1a1312100c0600000000000000000000000000000000000000000000000000030b131a202427282d2d2d2d2d2d2d292825211b140c0300000000000000000000000000000000000000000000000000020b12191f2326272d2d2d2d2d2d2d282724201a130b030000000000030b131a202427282d2d2d2d2d2d2d292825211b140c0300000000000000000000000000000000000000000000000000020b12191f2326272d2d2d2d2d2d2d282724201a130b03000000000000000000000000000000030b12181c1f2d2d2d2d2d2d2d2d2c2c2a2620191209000000000000000000000000000000000000000000000000000000000000000000000000000000000001070d11141a1e2123282c2d2f31333537373838393939383837353433302e2d2b282221201d1814120e0904000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111921272c2f303939393939393939393433302b251d140b010000000000000000000000000a141c242a2f323339393939393939393931302d28221b120900000000000000000000000000000000000000000000030d161f262d323536393939393939393433302b251d140b0000000000000000000000000000000008111a22282d30313939393939393939393939393939393939393939393939393939393939393939393939393939393939302f2c28211a1108000000000000000000010911181e2224252d2d2d2d2d2c22211e1a140d0600000000000000000000050d14191f252a2d2e3235373839383736322f2e2b26201a150e0600070c141c23282b2d303336383939383734312d2c29241d18120b03000000000000000000000000000000000000000000000000060e151a1f21222c2d2d2d2d2d2424211d1710090000000000000000000000000000000000050c13191e252a2d2e3235373939393836332e2d2b261f1a150e0600000000000000000000000000000000000000000000000006101820262b2e2f3939393939382e2d29251e160e04000000000000000000000000000000000000000000050e161e252a2d2e393939393932312e29231b13090000000000000000000000000000000000000000000006101820262b2e2f3939393939382e2d29251e160e040000000000000000000000000000000000000000050e161e252a2d2e393939393932312e29231b1309000000000000000000000008121a22282d3031313131313131312d2c29241d160d0405060b10121316181a1c1d1f1f20201f1f1e1d1b19171514120e0906030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e13181d2023282b2d2f3133353737383939393837373533312e2d2a26201f1c17110d0802000000000000000000000000000000000000000000010b151d252b303435393939393939393534312c261e150c000000000000000000000000000000000000000000000000000b141d242b303334393939393939393534302b251d150b01000000010b151d252b303435393939393939393534312c261e150c000000000000000000000000000000000000000000000000000b141d242b303334393939393939393534302b251d150b0100000000000000000000000000030d151d23292c3939393939393939393836312b241b1208000000000000000000000000000000000000000000000000000000000000000000000000000003090e13181d20262a2d2e34383a3c3e40424344454546464645454342413f3d3b3938332d2d2c2924201e1a14100c070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f19232b33383c3d46464646464646464641403c362f261d1308000000000000000000000007121c262e353b3f404646464646464646463e3d39342c241b10060000000000000000000000000000000000000000000a151f2831383e42434646464646464641403c362f261d0f05000000000000000000000000000005101a232c33393c3d46464646464646464646464646464646464646464646464646464646464646464646464646464646463d3c38332c231a1005000000000000000009131b23292e31323939393939392e2d2a261f180f060000000000000000080e171e252a30363a3b3f424445464544433f3b3a37312b2620180f0b12181e262e34383a3c40434445464544413d3a39352f28231c150c050000000000000000000000000000000000000000000006101820262b2e2f39393939393931302d28221a1209000000000000000000000000000000070e161e252a3036393a3f424445464645433f3b3a37312b2620180f0900000000000000000000000000000000000000000000040e18222a31373a3c4646464646453a3935302820160c0200000000000000000000000000000000000000020c1620283036394646464646463f3e3a342d251b11060000000000000000000000000000000000000000040e18222a31373a3c4646464646453a3935302820160c02000000000000000000000000000000000000020c1620283036394646464646463f3e3a342d251b110600000000000000000005101a242c33393c3d3e3e3e3e3e3e3e3a39352f281f160b1113171c1f20222527292a2b2c2c2d2c2b2b2a28262422211e1a1312100c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f151a1d24292c2e34383a3c3e404244444546464545444342403d3b3a36312d2c28231c19130d08020000000000000000000000000000000000000009131d272f373c40414646464646464642413d3730271e0e050000000000000000000000000000000000000000000000030d1d262e363c3f414646464646464641403c372f271d130900000009131d272f373c40414646464646464642413d3730271e0e050000000000000000000000000000000000000000000000030d1d262e363c3f414646464646464641403c372f271d1309000000000000000000000000010b151f272f343846464646464646464645423d352d24190f04000000000000000000000000000000000000000000000000000000000000000000000001070c141a1d24292c31363a3b404546484a4d4f505151525353525251504f4e4c4a4846443f3d3a39352f2d2a251f1d18120e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212b353d44484a5353535353535353534e4c4841382f251a0f03000000000000000000020e19242e3840474b4d5353535353535353534b49453e362c22170c000000000000000000000000000000000000000005101c26313a43494e50535353535353534e4c4841382f21170d03000000000000000000000000000b17222c363e44494a53535353535353535353535353535353535353535353535353535353535353535353535353535353534a48443e352c21160b0000000000000006111b252d343a3e3f4646464646463b3a36312921180b0200000000000008111a202930363b4246474b4f51525352514f4c4847423c37312a211b151c232830383f4446494d5051525351504e4a4745403a342e271e170e050000000000000000000000000000000000000000030e18222a31373a3c4646464646463e3d39342c241a0e0500000000000000000000000000071019202830363a4146474c4f51525352514f4c4847423c37312a211b12090100000000000000000000000000000000000000000a15202a343c4347485353535353524746413a32281e13080000000000000000000000000000000000000008131e28323a41465353535353534c4a463f372d23180d01000000000000000000000000000000000000000a15202a343c4347485353535353524746413a32281e130800000000000000000000000000000000000008131e28323a41465353535353534c4a463f372d23180d0100000000000000000b17222c363e44494a4b4b4b4b4b4b4b4745403a31281d191d2023282b2d2f3234363738393939393837373533312e2d2a26201f1c17110d08020000000000000000000000000000000000000000000000000000000000000000000000000000070c151b20262b2f35393a3f4446484a4d4f5051525253525251504e4c4a4846423d3a38342e29251e19140d050000000000000000000000000000000000030f1a252f3941484d4e535353535353534f4d4942393020170d02000000000000000000000000000000000000000000010b151f2e3840474c4d535353535353534e4d4841392f251a0f0300030f1a252f3941484d4e535353535353534f4d4942393020170d02000000000000000000000000000000000000000000010b151f2e3840474c4d535353535353534e4d4841392f251a0f03000000000000000000000007121d2731394045535353535353535353524e473f352b20150900000000000000000000000000000000000000000000000000000000000000000000030b12181f252a2f35393b4246484b51535557595b5d5d5e5f5f5f5f5f5e5d5c5a59575553504a4a4745413b3a36302c29241d1a140f0a03000000000000000000000000000000000000000000000000000000000000000000000000000004101c27333d474f54566060606060606060605b58534a41362b20140400000000000000000007131f2a35404a52575a606060606060606060575550483e34281d1101000000000000000000000000000000000000000a16212d38434c545a5d606060606060605a58534a4133291f140900000000000000000000000004101c28333e48505557606060606060606060606060606060606060606060606060606060606060606060606060606060606057554f473e33281c10040000000000010d18232d373f464a4c5353535353524846423b33291d140a000000000008111a232c323b41464d5254585c5d5e5f5f5e5c5955534d47423c332d241e272e343e424a5053565a5d5e5f5f5e5d5b5753514b444039302920170f05000000000000000000000000000000000000000a15202a343c4347485353535353534b49453e362c20170d020000000000000000000000071119222b323a41464c5254585c5e5f605f5e5c5955534d47423c332d241b130900000000000000000000000000000000000000030f1b26313c464e53555f606060605f54524c443a3025190c030000000000000000000003030303030303010d1925303a444c525f6060606060585651493f34291e1206000000000000000000000000000000000000030f1b26313c464e53555f606060605f54524c443a3025190c0300000000000000000003030303030303010d1925303a444c525f6060606060585651493f34291e12060000000000000004101c28333e485055575858585858585853514b433a2f2625292d2e34383a3c3e414244454546464545444342403d3b3a36312d2c28231c19130d080200000000000000000000000000000000000000000000000000000000000000000000030b121820262b31373a4145474a50535557595c5d5e5e5f5f5f5e5e5d5b595755534d4946443f3835302a251e170e08020000000000000000000000000000000814202b37414b53595b606060606060605c59544b4232291f140900000000000000000000000000000000000000000007121d2731404a52585a606060606060605b59534b41372b201408000814202b37414b53595b606060606060605c59544b4232291f140900000000000000000000000000000000000000000007121d2731404a52585a606060606060605b59534b41372b20140800000000000000000000000c18232f39434b515f606060606060605f5e5951473d31261a0e010000000000000000000000000000000000000000000000000000000000000000060d151d232930363a4045474d5355545c60626466686a6a6b6b6c6c6c6b6b6a6867666361605b545654514b4846423b39352f2a251f1a150e08020000000000000000000000000000000000000000000000000000000000000000000000000713202c38444f5960636c6c6c6c6c6c6c6c6c67645c53483c3020150a0000000000000000000a17232f3b47525c63666c6c6c6c6c6c6c6c6c64615a5045392d1d1207000000000000000000000000000000000000000d1a26323e49545e66696c6c6c6c6c6c6c67645c53453b30251a0e0200000000000000000000000814202d3944505a61646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6361594f44382c201407000000000006121e29343f4951565860606060605f55534d453b2f261b1106000000050f1a232c353e444c52575e6165686a6b6c6b6a6965625f57534d453f372d27303940444f545c606366696b6c6c6b6a6764605d55514a423b322921170b020000000000000000000000000000000000030f1a26313c464e53555f6060606060575550483e32291e130800000000000000000000050e19232b343d444c52565e6165686a6c6c6c6b6966615f57534d453e362d251b110800000000000000000000000000000000000006121f2b37434e585f626c6c6c6c6c6b615e564c4135291e150b00000000000004080a0a1010101010101010111d2a36414c565e6c6c6c6c6c6c65625b51463a2e22150900000000000000000000000000000000000006121f2b37434e585f626c6c6c6c6c6b615e564c4135291e150b000000000004080a0a1010101010101010111d2a36414c565e6c6c6c6c6c6c65625b51463a2e221509000000000000000814202d3944505a616464646464646464605d554b41382d3035393a3f4446494b4d4f5052525353525251504e4c4a4846423d3a38342e29251e19140d050000000000000000000000000000000000000000000000000000000000000000070c151d232831373c42474b5154545c60626466686a6a6b6c6c6c6b6a6a686664615f575653504a46413a3630292019130d0500000000000000000000000000000c1824303c48535d64686c6c6c6c6c6c6c68655d54443b3025190e0000000000000000000000000000000000000000000c18232f3943525c64676c6c6c6c6c6c6c68645d53483c3024180c000c1824303c48535d64686c6c6c6c6c6c6c68655d54443b3025190e0000000000000000000000000000000000000000000c18232f3943525c64676c6c6c6c6c6c6c68645d53483c3024180c0000000000000000000004101c2934404b555c6c6c6c6c6c6c6c6c6c6a63594e42362a1d1104000000000000000000000000000000000000000000000000000000000000030a11171f272f343b42464b5153575f6165666d6f71737576777878797979787876757472706e6c666663605d5554524d4745403936312b262019140d0500000000000000000000000000000000000000000000000000000000000000000000000916222f3c4854606b70797979797979797979746e64584c3c32261b0f0300000000000000000c1926323f4b57636e73797979797979797979716c615549392f23180c000000000000000000000000000000000000000f1c2935424e5a66707679797979797979746e64574d42362a1f140900000000000000000000000a1623303c4955616c707979797979797979797979797979797979797979797979797979797979797979797979797979797979706b6155483c2f23160900000000000915222e3a46515b62656c6c6c6c6c6c615f574d41382d22170b0300030d17212c353e474f565e61696e7275777879787776726e69625f5751493f373039424a515961666d6f7376777879787774706d67605c544d443b33291d140a000000000000000000000000000000000006121f2b37434e585f626c6c6c6c6c6c64615a50443a3025190e040000000000000000020d17202b353d464f565e61686d7275777879797876726e69625f5750483f372d23190d0400000000000000000000000000000000000815212e3a47535f6a6f7979797979786d685e52463d30271c1207000000050b101416171d1d1d1d1d1d1d1d1d202d3946525e68767979797979726d62564a3e312418080100000000000000000000000000000000000815212e3a47535f6a6f7979797979786d685e52463d30271c12070000050b101416171d1d1d1d1d1d1d1d1d202d3946525e68767979797979726d62564a3e31241808010000000000000a1623303c4955616c70717171717171716d675d53493f383a4146474a505355585a5c5d5e5f5f605f5e5e5d5b595755534d4946443f3835302a251e170e080200000000000000000000000000000000000000000000000000000000000810191e272e343c43474d53555d6064666d6f7173757777787979787877767573706e696763605c54524c46413b322a251e170e06000000000000000000000000000e1a2734404d59646f7479797979797979756f65564d42362a1c11060000000000000000000000000000000000000004101c2934404b55646e7479797979797979746f64594d4034271a0e000e1a2734404d59646f7479797979797979756f65564d42362a1c11060000000000000000000000000000000000000004101c2934404b55646e7479797979797979746f64594d4034271a0e0000000000000000000006131f2c3845515c67767979797979797979756a5e5245382c1f12060000000000000000000000000000000000000000000000000000000000040c151c2328313940454d52555d6065696e7276797b7d80828384848586868585848382817f7d7b797673706d6765615e5753514b46423b37312a251e170e07000000000000000000000000000000000000000000000000000000000000000000030f1b27333f495363707d868686868686868686807467584e43372b1f12060000000000000005111e2a36424d576673808686868686868686867e7164554b4034291c1004000000000000000000000000000000000000101d2a3643505d697682868686868686868074695e52463b30251a0e02000000000000000000000a1724313d4a5764707d86868686868686868686868686868686868686868686868686868686868686868686868686868686867d7063574a3d3024170a00000000000b1824313e4a56626d727979797979796e695f53493f33271f14090009141f29333e474f5961686e747b7e828485868584827f7b756e69625b51493f39424b545c606c70787c80838485868483817d7a726d665e564d453b2f261c1106000000000000000000000000000000000815212e3a47535f6a6f797979797979716c61564c41362a20160c020000000000000009141f29333d474f5960686d747a7f828485868584827f7b756e69625a51493f352b1f160c01000000000000000000000000000000000915222f3c4855626f7c8786868686857a6d61594f42392e23180c03000810171c202324292929292929292929292e3a4754616d7a86868686867f7265584c3f322519130c04000000000000000000000000000000000915222f3c4855626f7c8786868686857a6d61594f42392e23180c030810171c202324292929292929292929292e3a4754616d7a86868686867f7265584c3f322519130c0400000000000a1724313d4a5764707e7e7e7e7e7e7e7e796d655b504443484c5254545c60626567696a6b6c6c6c6c6b6a6a686664615f575653504a46413a3630292019130d0500000000000000000000000000000000000000000000000000000009111a222a303940454e53575f62676d7175797b7d8082838485858685858483817f7d7b7874706d66615e56524c443e36302920180f070000000000000000000000000e1b2835414e5b687481868686868686868175695e5246382d22170b0000000000000000000000000000000000000006131f2c3845515c677480868686868686868174685b4e4135281b0e000e1b2835414e5b687481868686868686868175695e5246382d22170b0000000000000000000000000000000000000006131f2c3845515c677480868686868686868174685b4e4135281b0e000000000000000000000714202d3a4753606d798686868686868687796c5f5346392c20130600000000000000000000000000000000000000000000000000000000060d161e262e343d434b51575e61676d72777b7f8286888a8c8e909091929292929291908f8d8c8a888583807d7a76726e6964605d55534d47433c36302920191007000000000000000000000000000000000000000000000000000000000000000005121f2b3744505b6574818d939393939393939184786a5f53473b2e211508000000000000000714202d3a46525e69778390939393939393938e8275675c5145382c1f13060000000000000000000000000000000000000a1723303d4a5663707d89959393939392867b6e61574d42362a1f1409000000000000000000000a1724313d4a5764707d8a9393939393939393939393939393939393939393939393939393939393939393939393939393938a7d7063574a3d3024170a00000000000c1925323f4c5865727f8686868686867b6e655b50443b31251a0e050e1a25313b454f59616b707a81878b8f90919292918f8c88827b726d625b5147404b545c666d757d84898d9091929291908e8a857f786e695e574d42382d22170b010000000000000000000000000000000915222f3c4855626f7b8786868686867e71685e52463e32281e1308000000000000020e1a25303b454f59606b6f7a81868b8f91929392918f8c87827b716c625b51473d31281d1307000000000000000000000000000000000815212e3a47535f6a73808d9693978e81746b60544a4034281f140908111a21282d303136363636363636363636363a4754616d7a879393938b7f7265584c3f3229241e160d040000000000000000000000000000000815212e3a47535f6a73808d9693978e81746b60544a4034281f1409111a21282d303136363636363636363636363a4754616d7a879393938b7f7265584c3f3229241e160d04000000000a1724303d4a5763707d868b8b8b8b8b8b81776c605a504e54565e6165666d6f7174757778787979787877767573706e696763605c54524c46413b322a251e170e060000000000000000000000000000000000000000000000000009121b232c343c424b51585f62696e747a7d8185888a8c8f9091919292929191908e8c8a8884807d79736d68615e565046413a322a2119100700000000000000000000000916232f3c4956626f7c89959393939392867b6e61544a3f33281c0f030000000000000000000000000000000000000714202d3a4753606d7985929393939395897c6f6356493c30231609000916232f3c4956626f7c89959393939392867b6e61544a3f33281c0f030000000000000000000000000000000000000714202d3a4753606d7985929393939395897c6f6356493c30231609000000000000000000000714202d3a4753606d7a8693939393939286796c5f5346392c201306000000000000000000000000000000000000000000000000000000060f171f2830383f444f555c60696e737a7f84888b8f929897999b9d9d9e9e9f9f9f9e9e9d9b9a99969892908c8986827f7b76716d67615e57534e46413b322b22190f04000000000000000000000000000000000000000000000000000000000000000613202d394653606c7884919e9f9f9f9f9fa196887c6f6255483c3025190d010000000000000814212e3b4754616e7b8795a09f9f9f9f9f9f9285796d6053473a2d22170b0000000000000000000000000000000000000916222f3c4854606b7683909da79fa3998d8074695e52463b3025190e020000000000000000000a1724313d4a5764707d8a979f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f968a7d7063574a3d3024170a00000000000613202d394653606c7782909893988f82776c60574d42362a20170d121e2a36424d57616b707d868e939a9b9d9e9d9d9d9c98948f877f726d62594f45515c666d78818a9196999c9e9d9d9e9d9a98928c837b6e695e544a3f33281d12070000000000000000000000000000000815212e3a47535f6a737f8c95939392857a6d615a50443a3024190d04000000000005111e2a36424d57606b6f7d858d92999b9d9c9b9c9e9c9a938f867e726d62594f433a2f24180d0100000000000000000000000000000006121f2b37434e58606d7984919e9f93887d6f665c51443b31261a0d101a232c33393c3d4343434343434343434343434754616d7a87949f988b7f7265584c3f39352f281f160c01000000000000000000000000000006121f2b37434e58606d7984919e9f93887d6f665c51443b31261a0d1a232c33393c3d4343434343434343434343434754616d7a87949f988b7f7265584c3f39352f281f160c010000000a16232f3c4855616b727f8c93979797938d80736c6158586062686d7175797c7e8082838585868685858483817f7d7b7874706d66615e56524c443e36302920180f07000000000000000000000000000000000000000000000009121b242d353e464e545c606a6f757b81868a8e929797999b9d9d9e9f9f9f9e9d9d9b999796918d8985807a746e68615a524c443c332b22191007000000000000000000000915222e3b4854606a7783909daa9fa3998c7f73665b5044382b1f1409000000000000000000000000000000000006121f2b37434e5864717e8a97a29f9f9d9083776b6054483b2f221509000915222e3b4854606a7783909daa9fa3998c7f73665b5044382b1f1409000000000000000000000000000000000006121f2b37434e5864717e8a97a29f9f9d9083776b6054483b2f221509000000000000000000000714202d3a4753606d7a86939f9f9f9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000000050e172129313a424a505960676d737b80858b9195989c9fa3a39f9d9b9a999898989898999b9c9d9fa3a29f9c9999928f8b87837e79746e69625f58524c443d342b21160a000000000000000000000000000000000000000000000000000000000000000916232f3c4956626f7c8996a1adacacacb2a8998c7f7266564c41362a1d1105000000000004101c2834404b5465717e8b98a7b1acacacaea2988a7d7063544a3f33281c0f0300000000000000000000000000000000000714202c38444f5963707d8a959fabab9f92867b6e61564d42362a1f14080000000000000000000a1724313d4a5764707d8a97a3acacb2acaba6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a3968a7d7063574a3d3024170a000000000005121f2b3744505b656e7b86929f9f948b7e72695e53463f32291f1414212d3a46535e69707d8692989f9d9b9691909192999f9e99928b7f726b60554e58606d78818e939ea09e9892909091979d9f9f9590847b6e665b5044392f23180c00000000000000000000000000000006121f2b37434e58606d78839099a1978e81756c61564c4135291f160c01000000000714202d3a46525e696f7d8691979f9f9892908e8f91979f9f98928b7f726b60554b4035291d1307000000000000000000000000000000030f1b26313c45515d67707d8a939e9a9183786d60574d42362a1f1617212c353e44494a5050505050505050505050505054616d7a8794a0988b7f726558504745413a31281e13080000000000000000000000000000030f1b26313c45515d67707d8a939e9a9183786d60574d42362a1f16212c353e44494a5050505050505050505050505054616d7a8794a0988b7f726558504745413a31281e13080000000714202c38444f59636d74818e959fa59c928a7e716a60626a6f757a7e8285888b8d8f9091929293929191908e8c8a8884807d79736d68615e565046413a322a2119100700000000000000000000000000000000000000000007101b242d363e474f585f666d737c82878e92989b9ea2a9a6a8aaa8a7a6a6a6a7a8a9a8a6a8a19e9a97928c86807a716c615e564d453c342b22190e0500000000000000000007131f2c38434e5865727e8b98a2aeab9e9184786c6053463b30251a0e00000000000000000000000000000000000814212e3a47535f6a7683909ca9aea2988b7f7265594f43382c1f13070007131f2c38434e5865727e8b98a2aeab9e9184786c6053463b30251a0e00000000000000000000000000000000000814212e3a47535f6a7683909ca9aea2988b7f7265594f43382c1f1307000000000000000000000714202d3a4753606d7a8693a0acac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000000030d172029333b434c545c606b707980868d92979da0a29f9b989892908e8d8c8c8b8b8b8c8d8e8f919299979a9d9fa39f9c9a938f8b85807b756e6a615e564e463d32271b0f03000000000000000000000000000000000000000000000000000000000006121e2b37424d576673808d99a8b1acaaacaea99d908376685e5246392d201306000000000006131f2c3845515c6675828f9ba8b0aba9abb0aa9a8e8174665b5044382b1f1206000000000000000000000000000000000004101c27333d4855616b7783909da7aea3988d8074695e52463b3025190e0200000000000000000a1724313d4a5764707d8a97a3b0b2a8a19e9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a968a7d7063574a3d3024170a0000000000030f1b27333f49535f69727f8c959f9f92867b6e615a50443b3025191f2c38434e58616e7b869298a29c938e88848384868c9299a39f93887d6f675c535f6a73808d939ea197928b858483858990959fa0969083786c60554b4034291c10040000000000000000000000000000030f1a26313c44515c666f7c87929f9e938a7d70685d52453d31281d130700000007131f2c38434f59616e7b859298a19a938c86838282858a9297a29f93877d70675d51453a2f24180d010000000000000000000000000000000a15202935404b55616b75818e98a0958c7f72695f53463e31281e1c28333e474f55575c5c5c5c5c5c5c5c5c5c5c5c5c5c616d7a8794a0988b7f72655c5c54524c433a2f24190d0100000000000000000000000000000a15202935404b55616b75818e98a0958c7f72695f53463e31281e28333e474f55575c5c5c5c5c5c5c5c5c5c5c5c5c5c616d7a8794a0988b7f72655c5c54524c433a2f24190d01000004101c28333e47515b606d79839096a1a49f92867c6f6a6f767c81868b8f9298989a9c9d9e9f9f9f9f9e9d9d9b999796918d8985807a746e68615a524c443c332b2219100700000000000000000000000000000000000000050e19222d363e485059616a6f7980878f93999fa3aaabaaaaa29f9d9b9a9a999a9a9b9d9fa2aaa9aba9a19e98928d857e756d685f574e463c342a20170c030000000000000000030f1b27323d4754606d7a85929facaca1968a7d7063574d42362a1c110600000000000000000000000000000004101c2934404b55626e7b88949fabac9f92867a6d6054473d32271b0f0300030f1b27323d4754606d7a85929facaca1968a7d7063574d42362a1c110600000000000000000000000000000004101c2934404b55626e7b88949fabac9f92867a6d6054473d32271b0f03000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000000020b151f29323b454d565d666d747d848c92999fa29f9c98928f8b88858381807f7f7e7e7f7f8081828486888a8d9092999b9ea19f9c98928d86817c746e6860584e43382c1f130700000000000000000000000000000000000000000000000000000000000814212e3a47535f697784919daaa7a09d9fa2aa9f93867a6d6154473a2e23170c00000000000713202d3a4653606d7985929faca69f9c9fa6ab9e9285796c605346392d20130a0000000000000000000000000000000000000b16212c38444f5964707d8a95a0acaa9f92867b6e61564d41362a1e140800000000000000000a1724313d4a5764707d8a97a3b0aca196918d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8a7d7063574a3d3024170a0000000000000b17222d38414d57606d78839099a2988f82766c62564d41362a20222e3b4854606a75828f98a29c918c817b7876777a7f87929aa49a9184796d6056626e7c87929fa19791857e797776787c838f949f9f958b7f72675c5145382c1f13060000000000000000000000000000000a15202834404a54606a73808d96a09e91857a6d60594f433a2f24180d0300000915222f3b4854606b75828f97a19f9388807a767576797e859297a2999184796d60554b4035291d1104000000000000000000000000000000040c18242f39434f59616e7b85929f9f92867b6e615a50433a2f24202d39444f5961646969696969696969696969696969696d7a8794a0988b7f72696969605d564c4135291d11040000000000000000000000000000040c18242f39434f59616e7b85929f9f92867b6e615a50433a2f242d39444f5961646969696969696969696969696969696d7a8794a0988b7f72696969605d564c4135291d11040000000b17212c353f45515c676e7a849198a2a39891857b747c82898e92999c9fa2aaa7a8aaa8a8a7a6a6a7a8a9a8a6a8a19e9a97928c86807a716c615e564d453c342b22190e050000000000000000000000000000000000020d17202b343e48505a616b707c838c92999fa4abaca7a09d999892908f8d8d8d8d8d8f909298989c9fa4abaaa29f97928a827a6e6960584e463c32291e150b0000000000000000000a16202c3945515d6774818e9aa7b1a89b8f8275695e5246382e23170b00000000000000000000000000000006131f2c3845515c6774808d9aa6b0a79b8e8174685d5245392b21160a0000000a16202c3945515d6774818e9aa7b1a89b8f8275695e5246382e23170b00000000000000000000000000000006131f2c3845515c6774808d9aa6b0a79b8e8174685d5245392b21160a00000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000a141d27313a444d575f686d78808991969fa39e9b948f8a85827e7b7977757373727171727273747677797b7e8083868a8e92979b9fa29f99928e87817a6f6a6054483b2e22150900000000000000000000000000000000000000000000000000000000000815222f3b4855626e7b8895a0aca095909298a2a4998a7e7164544a3f34281c1003000000000a1723303d4a5663707d8998a2a99f9490949faba197897c6f6356493c31261b0f03000000000000000000000000000000000005101c28333e4653606c7883909da7aea3988d8074685e52463b3025190e02000000000000000a1724313d4a5764707d8a97a3b0ab9e91848080808080808080808080808080808080808080808080808080808080808080807c6e6255483b2f22150800000000000006111b262f3c44505c666f7c86929f9f948b7e71685e52463e32292834404b54626f7c89939e9f948c7f746e696a686d737e88939fa0968b7f72655e6875828f99a39e91857b716d676a6a6f78828f98a29f9285796d6053473a2e23170b000000000000000000000000000000030c18232e39424e58606d7984919aa1978e81746b60554b4035291f150b0105111e2a36414c56636f7c89939e9e938b7e736d6868666d717c85929fa1968c8073675d5145392c2013070000000000000000000000000000000007121d27313e46525e69727f8b959f988f82756c61554c41352923303c4955616c70767676767676767676767676767676767a8794a0988b7f767676766d685d5245392c20130600000000000000000000000000000007121d27313e46525e69727f8b959f988f82756c61554c413529303c4955616c70767676767676767676767676767676767a8794a0988b7f767676766d685d5245392c20130600000005101a232834404b555e686f7c86929aa4a197908381878f949b9fa3abacaaaba39f9d9c9b9a999a9a9b9d9fa2aaa9aba9a19e98928d857e756d685f574e463c342a20170c030000000000000000000000000000000009141f29323d46505a626c717d8690959fa3ababa49f9b95908c898584828180808081828385888b8f93999fa2aaa9a19e938f847b6f6a60584e443b30271d1207000000000000000004111d2935414b55626f7c88959fabac9f92877b6e61544a3f34281c100300000000000000000000000000000714202d3a4753606d7985929eabaca095897c6f63564c413529190f0400000004111d2935414b55626f7c88959fabac9f92877b6e61544a3f34281c100300000000000000000000000000000714202d3a4753606d7985929eabaca095897c6f63564c413529190f0400000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000006111c262f39434c565f696e7a828d929ea0a09d938e88827d7975716e6c666867666565656565666869666d6e7174767a7d81858a8e92989ea19f99928e867c6f6256493c2f2316090000000000000000000000000000000000000000000000000000000005111e2a36414c5666727f8c99a7aa9d908386929fab9b8e8175665c5044382c1f120600000005121e2a36424d576774808d9aaaa1979083909ca9a99a8d807367584e43372b1f12060000000000000000000000000000000000000b161f2b3744505b65717e8a95a0acaa9f92867b6e61564c41362a1e14080a0a0a0a0a0a0a0a1724313d4a5764707d8a97a3b0a99c8f827673737373737373737373737373737373737373737373737373737373737373736e6a5f53473a2e211408000000000000000a141d28343f4a545f6a737f8c95a09f92857b6e615a50443a302c3845515c6674818e9aa59c9082786c615f575d616c74818d99a49d9083776a616d7a86929fa0958a7d7069605c5860666e7b86929fa2978a7e7164544a3f34281c100300000000000000000000000000000007121c27303c45515c676f7d88939f9d93897d70675d51453d31271d12070714202d3946525e6875828f9ca59b8e81756c615d565c606a717e8b96a09f92857a6d6053473a2f24180c00000000000000000000000000000000010b151f2a36424d56606c788390999e948a7e71675d51453c3026313d4a5764707d8283838383838383838383838383838383909ca99e9184838383827a6d6054473a2d211407000000000000000000000000000000010b151f2a36424d56606c788390999e948a7e71675d51453c30313d4a5764707d8283838383838383838383838383838383909ca99e9184838383827a6d6054473a2d21140700000000081118232e39434c565f6a717e88939fa5a095908d93999fa6acaaa8a09d999992908f8e8d8d8d8d8f909298989c9fa4abaaa29f97928a827a6e6960584e463c32291e150b000000000000000000000000000000030d1925303b444e58626c717e879298a0a7afa79f99938e88837f7c79777574737373747577797c7f83878d92989ea5ada59e9691857c6f6a5f564c42392e23180c0300000000000000010d18242f3a47535f6a7683909da9afa3998c7f73665c5044382b1f14090a0a0a0a0a0a0a0a0a0a0a0a0a0a121f2b37434e5864717e8b97a2adaa9d9083776b6054443a2f24190700000000010d18242f3a47535f6a7683909da9afa3998c7f73665c5044382b1f14090a0a0a0a0a0a0a0a0a0a0a0a0a0a121f2b37434e5864717e8b97a2adaa9d9083776b6054443a2f2419070000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000b17222d38424b555e686e7b838f949da49c969189817c76706d666561605b545a5959585858595a5b545c60626467676d7174797d81868c91969da09e9285796d6053473a2d201407000000000000000000000000000000000000000000000000000000000714202d3946525e687683909da9a79a8d80828f9ca99f9285796d6053463a2d2013090000000714212d3a46535f697784919daa9e91857e8a97a8aa9e9184776a5f53473a2e211509000000000000000000000000000000000000030f1b27333f4953606c7884919da8aea3988d8074685e52463b3025191616161616161616161724313d4a5764707d8a97a3b0a99c8f82766967676767676767676767676767676767676767676767676767676767676767625f584e43372b1f120600000000000000020b17232e38424e58606d78839099a2978f82756c61564c41362d3a4653606d7985929fa2988a7d70655b534d5259616e7b87939f9f95887b6f65727e8b99a39d9184786c6057514e545e6874818d9aa99c8f8276665c5044382b1f1206000000000000000000000000000000000b151e2934404b55606b74808d96a19e9184796d60594f43392f24180c0814212e3b4754616e7a86929f9f94887b6e615a524c5058606c7884919da2978b7e7164554b4035291d100400000000000000000000000000000000030d1925303b44505b666f7c87929f9e91847a6d60584e42382e323f4b5865727e8b8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f90949faba096918f8f8f877a6d6154473a2e21140700000000000000000000000000000000030d1925303b44505b666f7c87929f9e91847a6d60584e42382e3f4b5865727e8b8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f90949faba096918f8f8f877a6d6154473a2e211407000000000007121d27303b444e58616c73808c939ea7a09d9a9fa4abaca59e9b96918c898684828180808081828385888b8f93999fa2aaa9a19e938f847b6f6a60584e443b30271d120700000000000000000000000000010b151f2a36424d56606a717e889299a2aaafa49c959087817c77726f6d6668676766676768666c6f72767b80868e939fa3aaa8a09792867c6f685e544b403428201509000000000000000007131d2b37434e5864717e8b97a2adab9e9184786d6053463b31251a16161616161616161616161616161616212e3a47535f6a7683909ca9aea2988b7f7265594f4332281e1308000000000007131d2b37434e5864717e8b97a2adab9e9184786d6053463b31251a16161616161616161616161616161616212e3a47535f6a7683909ca9aea2988b7f7265594f4332281e13080000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000030f1c28333f4a545d676d7a8491959fa39f928d847d756f6a64605c545553504a4d4c4c4b4b4c4c4d4e4a51535557555d6064666d70757a7f848a9095978c7f72675d5145392c1f1306000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a87939faca7978a7e7f8c99aba297897c6f6356493c31251a0e0200000815222e3b4855616e7b8896a0a89b8e827a8796a0aca096887b6f6255483c31251a0e020000000000000000000000000000000000000b17222d3844505b66717e8a96a0acaa9f92867a6e61564c41362a232323232323232323232324313d4a5764707d8a97a3b0a99c8f8276695c5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a55534e463c31261a0f02000000000000000006111c26303c44515c666f7c87929f9e938a7e71685e52463e323c4956626f7c8997a29f9285796d6053494246535f697683909da7988b7f726875828f9bab998c8073655b5045424d5663707c8998a39f9285796d6053463a2d20130700000000000000000000000000000000030c18232f39434f59606d7984919ea1968d80746b60554b4035291e150b1825323e4b5865717e8b99a39c908376695f53464144505b65727f8c99a99c8f8276675d5145392c1f1306000000000000000000000000000000000009141f28333f4a545f6a74808d96a1978d80746a60544a3f34323f4b5865727e8b989c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9fa6b0a8a09e9c9c94877a6d6154473a2e211407000000000000000000000000000000000009141f28333f4a545f6a74808d96a1978d80746a60544a3f343f4b5865727e8b989c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9fa6b0a8a09e9c9c94877a6d6154473a2e2114070000000000000b151e29323c46505a606c77818e96a0acaaa7acafa7a09d938e89847f7c7a777575747373747577797c7f83878d92989ea5ada59e9691857c6f6a5f564c42392e23180c0300000000000000000000000007121d27313946525e696f7c86929aa3ababa39f928d837c756f6a6662605c545a5a5a5a5a545b606265696e747b818a9298a2a9a9a19891847a6e665c51453c31261a0e0500000000000000010f1b26323c4753606d7985929fabada1968a7d7063574d42362a23232323232323232323232323232323232934404b55626e7b88949fabac9f92867a6d6054473d3221160c010000000000010f1b26323c4753606d7985929fabada1968a7d7063574d42362a23232323232323232323232323232323232934404b55626e7b88949fabac9f92867a6d6054473d3221160c010000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000005101a232b3844505b666d79839096a0a299928b8079706b625f5853514b4846443f40403f3e3e3f3f4041404446484b4c5154545c6063686d72797e838a91857a6d60554b4035291d100400000000000000000000000000000000000000000000000000000004111d2935414c5565727e8b9aa4aca095877a7d8999a3a9998d807366574d42362a1e12050004101d2935404b5565727f8b98a8a9988b7f7784919daaa8998c7f7366574d42362a1e120500000000000000000000000000000000000006111b28333f4a54606d7884919ea8aea2988d8073685e52463a30303030303030303030303030313d4a5764707d8a97a3b0a99c8f8276695c4f4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4847433c332a201509000000000000000000000a141e2834404a545f6a73808d95a09e92857a6d615a50443a3f4b5865727e8b98a99c8f8276665c504138424d576673808d99a69b8e8174677784919eab96897d706353493f3b4653606d7986929fa298887b6e6255483b2f221508000000000000000000000000000000000007121d27313d45515d67707d89939e9f93887d6f675d51453d30271c121d2935414c566875828e9bab998c7f7266574d42353f4953626e7b8897a29f92867a6d6053473a2d2014070000000000000000000000000000000000020b17222d38424e58606d7984919e9f93877c6f665c50443b303f4b5865727e8b98a9a49f969393939393939393939394979ea8a39b98939393877a6d6154473a2e2114070000000000000000000000000000000000020b17222d38424e58606d7984919e9f93877c6f665c50443b3f4b5865727e8b98a9a49f969393939393939393939394979ea8a39b98939393877a6d6154473a2e211407000000000000030c17202a343e44505b656d7a84919daab6b4b3a9a0959189817c7773706d6769686766676768666c6f72767b80868e939fa3aaa8a09792867c6f685e544b4034282015090000000000000000000000000c18232f3943505a616e7b859198a3acaca399928b80786f6a625f585653504a4e4d4d4d4e4a505355575e61696e757e869297a2aaaaa1969082786d60574e42372b21170b00000000000000000a151f2c3845515d6774808d9aa6b0a89c8f8275695e5346382e3030303030303030303030303030303030303845515c6774808d9aa6b0a79b8e8174685d5245392c201304000000000000000a151f2c3845515d6774808d9aa6b0a89c8f8275695e5346382e3030303030303030303030303030303030303845515c6774808d9aa6b0a79b8e8174685d5245392c201304000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000b17212a36424d57606c78818f959fa29892877e736d676059534e46454040434546464544423f3b3a373134383a3b3e4145474a5053565d60666d71787e847f73675d5143392f24180c000000000000000000000000000000000000000000000000000000000613202c3945515d6776828f9cacaa9d9184777a86929faa9d908477695e53463a2d2114070006131f2c3945515d6776828f9ca9a197887c74818d9aa7aa9d908377695e53463a2d211408000000000000000000000000000000000000000b17222d3844505c66717e8b96a1acaa9f92867a6e61564c413d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4a5764707d8a97a3b0a99c8f8276695c4f43404040404040404040404040404040404040404040404040404040403b3a37312a21180e0300000000000000000000020c18232e39424e58606d79839199a1978e81756c61564c41414e5b6774818e9aa79a8d807467544a3f2f3e4b5764717e8a97a49d9083776d7a86939fa399877b6e6154473b3845515c677784909daa978a7e7164574b3e3124180b0000000000000000000000000000000000010b151f2935404b55616b74818e97a19a9184796d60584e42392e2318202d3946525d687884919ea996897c706356493d31394653606c7985929fa398897c6f6356493c3023160900000000000000000000000000000000000006111c262f3c45515d67707d8a949e999083786d60574d42363f4b5865727e8b97a19a938a86868686868686868686878c97a39b918b868686867a6d6154473a2e21140700000000000000000000000000000000000006111c262f3c45515d67707d8a949e999083786d60574d423f4b5865727e8b97a19a938a86868686868686868686878c97a39b918b868686867a6d6154473a2e2114070000000000000008131e28313a46535e696f7d86929facb9b9ada29791837d75706b6663605d555b5a5a5a5a545b606265696e747b818a9298a2a9a9a19891847a6e665c51453c31261a0e050000000000000000000004101c2934404b55616c76828f97a1aaafa49a92877e736d665f58534e4946443f41404040413f4446484d53565e616c717c859298a2aca89f948d80736a5f53473e33281c10040000000000000004101d2935404b55626e7b88949fabac9f93877b6e61544a3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4753606d7985929eabaca095897c6f63564c4135291d11040000000000000004101d2935404b55626e7b88949fabac9f93877b6e61544a3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4753606d7985929eabaca095897c6f63564c4135291d1104000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000004101c28333a46525e69727f8b939ea39992867d716c605c554f47434446494d5051525352514f4c4847433c37332d2f2f35393a3f44464c52545c60656c7179796d60554b4131271f1911060000000000000000000000000000000000000000000000000000000714212d3a4754606d7a86929faca79a8d81747683909da9a095877b6e6154483b2f24180c000714202d3a4753606d7a86929fab9e928579717e8a97a7aca095877b6e6154483b3025190d0100000000000000000000000000000000000006111c28343f4a54606d7984919ea8aea2988d8073685e52494949494949494949494949494949494a5764707d8a97a3b0a99c8f8276695c4f43363434343434343434343434343434343434343434343434343434342f2e2b2620180f0600000000000000000000000007121c27303c45515c676f7c87939f9e938a7e70685d5246434f5c6976828f9ca5988b7f7265584c3f2e3c4956636f7c8996a29f9285786f7b889aa49f9286796c6053463934404b556975828f9ca5998c7f7266594c3f3326190c000000000000000000000000000000000000030d18242f3a434f59606d7a85919ea0968d80736a60544a4034281e212e3a4754616d7a8796a1a297877a6d6054473a2d3744505b6576828f9caa988b7f7265584c3f3225190c000000000000000000000000000000000000000a141d2935414b55616c75828f98a0958b7f72695e52463e3a4754616d7a85919a93867d797979797979797979797a8794a0988b7f7979797976685e5246392d201307000000000000000000000000000000000000000a141d2935414b55616c75828f98a0958b7f72695e52463e4754616d7a85919a93867d797979797979797979797a8794a0988b7f7979797976685e5246392d201307000000000000010d19242f3a43505a616e7b859299a3aebbb8ab9e92857a706b6360595653514b4e4d4d4d4e4a505355575e61696e757e869297a2aaaaa1969082786d60574e42372b21170b0000000000000000000006131f2c3845515c67707d8a949fa9b0a69f93887e716c605c544e47433c3a38342e3433342d3338393c42464d525a616a6f7c86929aa4afa69f92877b6e62594f44392d20150a00000000000000000c18242f3947535f6a7683909ca9afa4998c8073665c504949494949494949494949494949494949494949494e5864717e8b97a2adaa9d9083776b6054443a2f24190d0100000000000000000c18242f3947535f6a7683909ca9afa4998c8073665c504949494949494949494949494949494949494949494e5864717e8b97a2adaa9d9083776b6054443a2f24190d01000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000714202c38444f59616e7b86929fa59f92877d706b615a514b4344495053565a5c5e5f5f5f5e5c5955534e46443f382f27343c424a5053565b5d5f5f5b60666c6d675c51454039312b2317110a0200000000000000000000000000000000000000000000000004101c2834404b5464717e8a99a3aea7978a7e7173808d99aba7988b7f7265554b4035291d10040a1724303d4a5763707d8a98a3a89b8f82756e7a8795a0aca7988b7f7265564c4135291d1105000000000000000000000000000000000000000b17232e3844515c66727e8b96a1adaa9f92867a6d615656565656565656565656565656565656565764707d8a97a3b0a99c8f8276695c4f433629272727272727272727272727272727272727272727272727272722211f1a150e0600000000000000000000000000000b151e2834404b55606a73808d96a09e91857a6d61594f43505d6a7683909da4978a7e7164574b3e313b4855616e7b8894a19f9286796f7c8996ac9e918578655b5044372e414e5b6774818e9aa6998d8073665a4d4033271a0d0000000000000000000000000000000000000007131d28313d45525d68717e8a939e9f92877c6f665c51443c3026232f3c4956626f7c8995a89f928578685d5245392c333f49536774818e9aa79a8d8174675a4e4134271b0e00000000000000000000000000000000000000020b18242f3a43505a616e7b86929f9f92867b6e61594f433946525e68707d88939a92857a6e656c6c6c6c6c6c6d7a8794a0988b7f726c6c6c6c5e564c41362a1d110500000000000000000000000000000000000000020b18242f3a43505a616e7b86929f9f92867b6e61594f4346525e68707d88939a92857a6e656c6c6c6c6c6c6d7a8794a0988b7f726c6c6c6c5e564c41362a1d110500000000000004111d2935414c55626c76828f97a1abb5afacada2978e81776c605a504947454042414040413f4446484d53565e616c717c859298a2aca89f948d80736a5f53473e33281c1004000000000000000003101c28343f4a54606d7984919ea6b0aa9e948c7f736c625a504a423c37322d2c282327272722282b2d31363b42465058606a707e88939fa8aea3998f82766c6155493c31261b0f000000000000000007121d2b37434e5864717e8a97a1adab9e9184796d6056565656565656565656565656565656565656565656565f6a7683909ca9aea2988b7f7265594f4332281e130800000000000000000007121d2b37434e5864717e8a97a1adab9e9184796d6056565656565656565656565656565656565656565656565f6a7683909ca9aea2988b7f7265594f4332281e130800000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000a16232f3c4855616b75828f98a29d938b7e716b60595045414950535b606366696b6c6c6c6b6866625f58535049413d333d464e545b6063676a6b6c6c6b696663605c54514b433d3528221c140b02000000000000000000000000000000000000000000000006131f2c3845515c6675818e9babaca095877a6e707d8999a3a89c8f8275675d5145392c1f1306121f2b37434e586774818d9aaaa8988b7f72687784919daaa99c8f8376685e5246392d2013070000000000000000000000000000000000000006111c2834404a54606d7984919ea9aea2988d8073686363636363636363636363636363636363636364707d8a97a3b0a99c8f8276695c4f4336291c1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1514120f0903000000000000000000000000000000030c18232e39434e58606d7984919aa1978e81746b61564c515e6a7784919da3978a7d7064574a3d313b4754616e7a8794a1a399867a707d8a96a39e9184776b5e493f3334414d5a6774808d9aa79a8d8174675a4e4134271b0e000000000000000000000000000000030608090d0c161f2935414c56616c75818f97a2999083786d60584e42382e23313e4a5764717d8a97a49d9084776a564c4135292d404c5966737f8c99a69c8f8276695c4f4336291c10000000000000000000000006060606060606060007131d28313e46535e69727f8c95a0988e81756b61554b40414c56616b74808d95978f82776c6058606060616d7a8794a0988b7f726560605f524c443a3025190d010000000000000000000000000000020608080c0e07131d28313e46535e69727f8c95a0988e81756b61554b414c56616b74808d95978f82776c6058606060616d7a8794a0988b7f726560605f524c443a3025190d010000000000000613202c3945515d67717e8b949fa9b3aba39fa3a99e938c80736c61584e453b352f3433342d3338393c42464d525a616a6f7c86929aa4afa69f92877b6e62594f44392d20150a000000000000000006121f2b3844505c66727f8c96a0acaea2988f82776c605a50443f38302b26201f1c171a1a1a171c1f20252a30363e464e58616c73808d96a1acab9f948a7d7064584e43372b1d120700000000000000010f1a26313c4653606d7985929eacada1968a7d70646363636363636363636363636363636363636363636363636e7b88949fabac9f92867a6d6054473d3221160c01000000000000000000010f1a26313c4653606d7985929eacada1968a7d70646363636363636363636363636363636363636363636363636e7b88949fabac9f92867a6d6054473d3221160c0100000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000007131f2c38434f5963707d8a949ea1978e81746c62594f47444c535b60656c6f7376787979787775726e6a64605b534e443f464e585f666c707477787979777673706d66605d554f4740332d261d140a00000000000000000000000000000000000000000000000713202d3a4653606d7985929fabaa9d908477686d7a86929fac9f92867a6d6053473a2d20140a15212e3a47535f6a7884919eaba196887b6e6774818d9aabac9f92867a6d6154473a2f24180c00000000000000000000000000000000000000000c18232e3945515c66727f8b97a1adaa9f92867a707070707070707070707070707070707070707070707d8a97a3b0a99c8f8276695c4f4336291c100d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0808060200000000000000000000000000000000000007121d27303d45515d67707d88939f9e938a7d70685d52515e6b7884919ea3968a7d7063574a3d303a4754616d7a8794a0a194877a717d8a97a49d9184776a5e51442d34404d5a6773808d9aa69b8e8175685b4e4235281b0f00000000000000000000000000040a0f1315161a1d1f1924303a44505a616e7a85929ea0958c7f736a5f544a3f3428323f4b5865727e8b98a59c8f8376695c50432f24323e4b5865717e8b98a49d9083776a5d5044372a1d1100000000000002060a0c0d131313131313131313130c161f2a36424d57606d788390999e938a7d70675d51453c444f59606d79839098948c7f726a60554b54616d7a8794a0988b7f726558535346413a32281e13080000000000000000000000000003090e121415191b1d1e161f2a36424d57606d788390999e938a7d70675d5145444f59606d79839098948c7f726a60554b54616d7a8794a0988b7f726558535346413a32281e130800000000000004111d2935414c55606d7a85929ea6b0aaa2999299a1a59c928a7e716a60574d43392f26272722282b2d31363b42465058606a707e88939fa8aea3998f82766c6155493c31261b0f00000000000000000713202d3a4653606d7884919ea8b2a99f92867b6e655b50483e342e261e1b1312100c060d060b0f12131a1f252a343d46505a606d7984919ea8b0a69c8f83766a5f5347392e23180c000000000000000009151f2c3845515c6673808d9aa4afa99c8f82757070707070707070707070707070707070707070707070707074808d9aa6b0a79b8e8174685d5245392c201304000000000000000000000009151f2c3845515c6673808d9aa4afa99c8f82757070707070707070707070707070707070707070707070707074808d9aa6b0a79b8e8174685d5245392c2013040000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000915222f3b4854606b7683909da69e91857a6d605a5047454d565e656c71787c80838485868584827f7b77716c65605850494e58606a6f787d81838586858483807c78726d67605952443f382f261c1106000000000000000000000000000000000000000000030f1b27333f495363707d8a98a2aeaa9a8d807367677683909ca9a3988a7d7063574a3d31261b0f15222f3c4855626f7b8896a1ab9e9184786a64717d8a99a3afa3998b7e7164554b4035291d10040000000000000000000000000000000000000007121c2834404b54606d7985919ea9aea2988e817c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7f8c99a6b2a99c8f8276695c4f4336291c1003010101010101010101010101010101010101010101010100000000000000000000000000000000000000000000000b151e2935404b55606b74818d96a19e91847a6d60594f5e6a7784919da3978a7d7064574a3d313b4754616e7a8794a1aa93877a707d8a96a39e9184776b5e51442f34414d5a6774808d9aa79a8e8174675b4e4134281b0e0000000000000000000000040a0f151b1f212226292b2c2c28323e46525e68717e8b949e9f92877c6f665c50443c2f33404c5966737f8c99a69c8f8275695c4f423629313e4b5764717e8a97a49e9184786b5e5145382b1e120000000000070d121619192020202020202020202020201a25313b44505c666f7c87939f9e9184796d60584e413d45515c676f7c86929f92867c6f675d5154616d7a8794a0988b7f7265584c3f3936302820160c020000000000000000000000060c11151a1e212226282a2b2c2c25313b44505c666f7c87939f9e9184796d60584e4145515c676f7c86929f92867c6f675d5154616d7a8794a0988b7f7265584c3f3936302820160c020000000000000613202c3945515d67737f8c97a2adaea29892869196a1a49f92867c6f695e554b41382d2217171c1f20252a30363e464e58616c73808d96a1acab9f948a7d7064584e43372b1d120700000000000005111e2a36414c5664707d8a96a1adada1978c7f72695e53493f3628231c140c0a060300000000000306090e1419222b343e45515d67717e8a96a0acab9f94887c6f62544b4034281c10040000000000000004101c2834404b54616e7b87939facac9f93877d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d85929fabaca095897c6f63564c4135291d1104000000000000000000000004101c2834404b54616e7b87939facac9f93877d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d85929fabaca095897c6f63564c4135291d11040000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000005111e2a36424d56636f7c89959f9f958a7e71685d5248434d575e686d777e84898d8f91929292918f8c88837e786f6a605b5354606a6f7c83898e9092929291908c89847f796f6b635c504a42382d22171007000000000000000000000000000000000000000005121f2b3744505b6574818e9aaaaea398897d70636673808c99a9aa9a8d817467584e43372b1f121d2935414c5666727f8c99a8ac9b8e817468606d7a86929facab9b8f8275675d5145382c1f130600000000000000000000000000000000000000000c18232e3945515d67727f8c97a1adaa9d938e898989898989898989898989898989898989898989898c919ca8b5a99c8f8276695c4f4336291c100300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c18242f39434f59606d7984919ea1968e81746b60555d6a7783909da4978a7d7164574a3e313b4855616e7b8894a1a2988679707c8996a39e9184786b564c413534414e5b6774818e9aa69a8d8073675a4d4034271a0d00000000000000000000070e151b20262b2e2f3336383939393736414c56626c76828f98a2999083786d60574d41382d404d596673808c99a69b8e8275685b4f423528313d4a5764707d8a97a39e9285786b5f5245382c1f12000000010a12191e2325262d2d2d2d2d2d2d2d2d2d2d2d2d2d28343f4a54606a74808d97a1968d80736a5f53493f404b555f6a727f8b94999184796d605a54616d7a8794a0988b7f7265584c3f322a251e160e050000000000000000000002090e171d1f262b2e2f3235373839393938343f4a54606a74808d97a1968d80736a5f5349404b555f6a727f8b94999184796d605a54616d7a8794a0988b7f7265584c3f322a251e160e05000000000000000714212d3a4754606d7a85929fa9b3a99f92867c849198a2a29891847b6e675d53493f332722190f12131a1f252a343d46505a606d7984919ea8b0a69c8f83766a5f5347392e23180c0000000000000714202d3946525e6876828f9ca8b2ab9e9185796d60574d41382d2417110a02000000000000000000000002091019222935404b55606c7884919dabb0a69a8e8174665c5145382c1f130600000000000000000c18232e3946535f6976828f9ca9afa499938a89898989898989898989898989898989898989898989898989899297a2adaa9d9084776b6054443a2f24190d010000000000000000000000000c18232e3946535f6976828f9ca9afa499938a89898989898989898989898989898989898989898989898989899297a2adaa9d9084776b6054443a2f24190d010000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000714202d3a46525e6975828f9ba79d9083766c61564c414b555e696e7a828b9196999c9e9f9f9f9e9b9995908a837c726c655c5c666f7c8690959a9d9e9f9f9e9c9996918b847d736e605b544a3f332822190c02000000000000000000000000000000000000000613202d394653606c7885919eabac9f9286796d60636f7c8997a2ab9e9184786a5f53473a2e2115202c3945525d687683909ca9a49a8a7e71645d687683909ca9ac9f9285796d6053473a2e23170b000000000000000000000000000000000000000007121d2935404b55606d7985929ea9afa59d9a96969696969696969696969696969696969696969696999ca3adb5a99c8f8276695c4f4336291c100c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0706040000000000000000000000000000000000000000000000000007121d27313d45515d67707d89939d9d93897d70675d5c6976838f9ca4988b7e7165584b3e323c4855626f7b8895a29f9285796f7c8895a99f928578685d52453935424e5b6875818e9ba6998c807366594d4033261a0d00000000000000000109101920272b32373b3c40434546464544423e44505a616e7b86929f9f958c7f72695f53493f33404d5a6673808d99a69b8e8174685b4e413528303d4a5663707d8996a39f9285786c5f5245392c1f120000000a131c232a2f32333939393939393939393939393939392e38424e58606d7a85919e9f92877c6f655b50443a434e58626d75828f97968e81746c6157616d7a8794a0988b7f7265584c3f322519130c0500000000000000000000050d141a22282d31373a3b3f414445454646454441424e58606d7a85919e9f92877c6f655b5044434e58626d75828f97968e81746c6157616d7a8794a0988b7f7265584c3f322519130c050000000000000006121e2b37424d5765727e8b97a2adada1978c7f727c86929aa4a1969083796d655b50443e342b20170d090e1419222b343e45515d67717e8a96a0acab9f94887c6f62544b4034281c100400000000000814212e3b4754616e7a87939facafa3998c7f72675d51453b2f261b1206000000000000000000000000000000071018242f3944505b66727e8b99a3aeac9f9285796d6053463a2d201308000000000000000007121d2a36424d5764707d8a96a1adaba49f9796969696969696969696969696969696969696969696969696969fa2a9aea2988b7f7265594f4332281e13080000000000000000000000000007121d2a36424d5764707d8a96a1adaba49f9796969696969696969696969696969696969696969696969696969fa2a9aea2988b7f7265594f4332281e1308000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000814212e3b4754616e7b87939fa1968a7e71645a504445515d676e7b848f949ea0a8a39f9c9a999a9b9e9f9d9590877f776d66606d79849198a0a79f9d979595989c9f9e96918780746c665b50443f342b1e140a00000000000000000000000000000000000000091623303c4956636f7c8997a1ada99c8f8276675d606d7985929faba196887b6f6255483c302419212d3a4754606d7a86929fac9f93877a6e615666737f8c99a8aea2988a7d7064544a3f34281c100300000000000000000000000000000000000000000c18242f3945515d67727f8c97a2adafa9a7a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a6a8adb5b5a99c8f8276695c4f4336291c1919191919191919191919191919191919191919191313100c070000000000000000000000000000000000000000000000010b151f2935414b55606b74818e97a19e9184796d60596875818e9ba6998c807366594d40313d4a5763707d8a96a39e9184776e7a8797a1a298877a6d6054473a36424d57697683909cac988b7e7265584b3f3225180c00000000000000010a131b222b32373c4347494d5052525352514e4b4746535e69727f8b949f9f92867b6e655b50443b404d5a6673808d99a69b8e8174685b4e413528303d4a5663707d8996a39f9285786c5f5245392c1f12000007121c252e353b3e4046464646464646464646464646464646464645525d68717e8a949f999083776c60564c413c46515b616d7a85919a938a7e71695e616d7a8794a0988b7f7265584c3f322519080200000000000000000000060f171f252a34393c4247484c4e505152535252514e4c48525d68717e8a949f999083776c60564c4146515b616d7a85919a938a7e71695e616d7a8794a0988b7f7265584c3f322519080200000000000000000814212e3a47535f697683909da9b3ab9e9185796d717e88939fa59f958e81776c605a50463c32291f150b02091019222935404b55606c7884919dabb0a69a8e8174665c5145382c1f130600000000030f1b27333f495364717e8b9aa4afac9f92867a6e61554b4033291d140a000000000000000000000000000000000007121d28333f4a54616d7a86929facaea298897d706356493d2f24190d0100000000000000000e1a26313b4653606d7984919eabb5afaca3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3abadb3ac9f92867a6d6054473d3221160c0100000000000000000000000000000e1a26313b4653606d7984919eabb5afaca3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3abadb3ac9f92867a6d6054473d3221160c01000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000004101d2935404b5565727e8b99a49e9184786d605346434e58606d798391969fa6a49f9992908e8d8d8e91969a9f99928c81786d66717e8a96a0a89f95908a88898b8f949da099938c81786c605b51463d30261c1106000000000000000000000000000000000006121f2b37434e586773808d9aa9b2a8988c7f7265555c6675828f9ba8a8998c7f7266564c4135291d27333f495364717d8a99a3aa9d908377685e55626f7c8896a1adaa9b8e8174665c5044382b1f1206000000000000000000000000000000000000000007121d2935404b55606d7a85929faab3b5b4b1acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa3a6abb4b5a99c8f8276695c4f43362926262626262626262626262626262626262626262626201f1c18120b0300000000000000000000000000000000000000000000030d18242f3a434f59606d7a84919ea1968d80746b6066727f8c99ab9b8e817568574d42373f4a5465727f8b98a59b8f8275697885929eaa95887c6f6255493c3a46535e697885919ea49a897c6f6256493c2f231609000000000000000a131c252d343c43474e5355595c5e5f5f5f5d5b5853514d57606c77829098a3989082776c60574d42404d596673808c99a69b8e8175685b4e423528303d4a5763707d8a96a39e9285786b5f5245382c1f1200020d19232e3740464b4c535353535353535353535353535353535353534c56616c76828f989f948b7e71685e52463d3f46525e68707d88939f92857b6e66616d7a8794a0988b7f7265584c3f3225190c00000000000000000000060f18212930363e45494d5355595b5d5e5f5f5f5e5d5b58555356616c76828f989f948b7e71685e52463f46525e68707d88939f92857b6e66616d7a8794a0988b7f7265584c3f3225190c0000000000000000000815222f3b4855626e7b88959fabafa3998c7f73676c73808c939ea79e938c7f736c61584e443b31271d120700071018242f3944505b66727e8b99a3aeac9f9285796d6053463a2d2013080000000005121f2b3744505b6575818e9bacb6a99c8f8276685e5243392f21170b020000000000000000000000000000000000010b17222d3846525d6875828f9ca8b4aa9a8d807367564c4135291d1104000000000000000009141f2c3844505c6673808c99a3afbbb9b1acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa7a9afb8bab1a79b8e8174685d5245392c20130400000000000000000000000000000009141f2c3844505c6673808c99a3afbbb9b1acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa7a9afb8bab1a79b8e8174685d5245392c20130400000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000613202c3945515d6775828f9ca8998c7f72665c50444854606a74808d95a0a8a499938d87838180808184888d92989f938e81786c74818e9ba8a09690837d7b7c7e828991969f9f938e81746d62584e42382e23170b01000000000000000000000000000000000815212e3a47535f6a7784919eaaaca196887c6f62555465717e8b98a7a99c908376685d5246392d202b3744505b6574818e9babaa9a8d80736756535f6a7884919eabab9e9285796d6053463a2d20130a0000000000000000000000000000000000000000010d18242f3945515d6773808c98a2aebab1a7a09d93939393939393939393939393939393939393979aa2abb5a99c8f8276695c4f433633333333333333333333333333333333333333333333332d2c28231d150c030000000000000000000000000000000000000000010407131d28313d45525d68707d8a939e9f93887d6f6763707d8a99a39e918478695f53473f44505c6675818e9ba9998c7f736976838f9ca5988b7f7265574d423f4854616e7b8796a19f93867a6d6053473a2d20140700000000000008121c252e373f464e54585f6266696b6c6c6c6a6864605d55515b656e7b86929f9f948b7f72695e5346404c5966737f8c99a69b8f8275685c4f423529313e4a5764717d8a97a49e9184786b5e5145382b1e120006121e2a3540495157596060606060606060606060606060606060606060605a616e7b86929f9e92857a6d61594f4239414c56616b74808d95979083786d616d7a8794a0988b7f7265584c3f3225190c000000000000000000030d18212a333b42465055575f6265686a6b6c6c6c6b6a6865615f575a616e7b86929f9e92857a6d61594f42414c56616b74808d95979083786d616d7a8794a0988b7f7265584c3f3225190c0000000000000000030f1c28333f4a5465727f8b98a7b1ac9f92867b6e61606c77818e95a0a59f93887e716a60564d43392f231812080007121d28333f4a54616d7a86929facaea298897d706356493d2f24190d010000000613202d394653606c7885929eabb3a9988b7f7265564c4131271d0f050000000000000000000000000000000000000006111c2935414c5665727f8b98aab4aa9d918477685d5245392c201306000000000000000003101c28343f4a54616e7b87929facb9b1a7a0939393939393939393939393939393939393939393939b9ea5afb8aca095897c6f63564c4135291d110400000000000000000000000000000003101c28343f4a54616e7b87929facb9b1a7a0939393939393939393939393939393939393939393939b9ea5afb8aca095897c6f63564c4135291d110400000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000714202d3a4753606d7a86929fa096887b6e62544a414d56626f7c87939fa7a4999387807a7674737375777b80868e939f938c807376838f9ca99e918478706e6f71767d848f949f9d938b7f726a60544a3f34281d1207000000000000000000000000000000000915222f3c4855626f7b8896a0acab9e9184786a5f5354616e7b8795a0ac9f92867a6d6154473a2d222d394653606c7885929eaba298897d7063564e586774818e9aaaada197897c706356493d32261b0f03000000000000000000000000000000000000000007121d2935414c55606d7a85929faab4aca09591868686868686868686868686868686868686868a909aa6b5a99c8f8276695c4f433f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3a38342e271e150b00000000000000000000000000000000000001080d111314161f2935414c56616c75818e97a19a9184796d616d7a86929fa196887b6e6259504a4e56606d7985919ea197897d706673808d99a79c8f8275695f544d4a505b65717e8b98a99d908377675d5145392c2013060000000000040e1a242e374049515860626a6f7376787979787775716d67605c555f69727f8c959f9f92867b6e615a50444b5865727e8b98a59c8f8276695c4f432f24313e4b5864717e8b97a49d9083776a5d5044372a1d11000a16232f3b46515b63666c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b69727f8c95a0978e81746b60544b403a444f59606d79839098958c80736b6d7a8794a0988b7f7265584c3f3225190c0000000000000000010b151f2a333c454d525a6164696e72747778787979787774726e6963605f69727f8c95a0978e81746b60544b40444f59606d79839098958c80736b6d7a8794a0988b7f7265584c3f3225190c000000000000000006121f2b3844505b6676828f9ca9b5a99c8f8276685e5b656d79839097a1a49a92867c6f685e554b403429241a1006010b17222d3846525d6875828f9ca8b4aa9a8d807367564c4135291d11040000000815222e3b4855616e7b8897a1adada197887b6e6255483b3022150b0000000000000000000000000000000000000000000d1924303c4855626f7b8898a2aeaca095877a6d6054473a2d2114070000000000000000000c17232e3846525e6975828f9ca8b2aca095898686868686868686868686868686868686868686868e939ea9b4aa9d9084776b6054443a2f24190d01000000000000000000000000000000000c17232e3846525e6975828f9ca8b2aca095898686868686868686868686868686868686868686868e939ea9b4aa9d9084776b6054443a2f24190d0100000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000a1724303d4a5763707d8a98a39e9184776a5f534246525e6875828f99a4a89f93877e746d6867666768696e737a818b929893887d7783909da5988c7f72666262656b707a828f959f9f92877c6f665c5044392f24180d00000000000000000000000000000005121e2a36424d5766737f8c99a8b2aa9a8d807467584e525e697783909daaa3998a7e7164544a3f33282f3c4956626f7c8997a1ab9f9285796d60534a5764707d8a98a3aea99a8d807467584e43372b1f13060000000000000000000000000000000000000000010d19242f3a45525d6873808d98a2aeaa9d9184777979797979797979797979797979797979797e8a97a3b0a99c8f8276695c4f4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4645403930271d120700000000000000000000000000000001070c13191d20212428242f3a444f59616d7a85929ea0968d80736a6876828f9ca89a8d80746b605b54585f68707d8a97a19e9185796d626f7b8895a09f93877b6e665e57545c606d7683909da4998c7f7266554b4035291d110400000000020c16202c364049525b626a6f767c80838585868584817e7a736d675e57606d78839099a2988f82766c62564d4a5764717d8a97a49d9083776a554b403529323f4c5965727f8c98a59c8f8276695c4f4336291c10000c1925323e4b57636d737979797979797979797979797979797979797979797978736d7883919a9e93897d70665c51453c3d45515c676f7c86929f93877d706d7a8794a0988b7f7265584c3f3225190c000000000000000007121d27313c464e575e616c71777b7f8183848586858584817f7b76706b60606d7883919a9e93897d70665c51453d45515c676f7c86929f93877d706d7a8794a0988b7f7265584c3f3225190c00000000000000000613202d394653606c7985929facb3a9988b7f726556535d676e7b859198a3a29891847a6e675c514540362c22180e0506111c2935414c5665727f8b98aab4aa9d918477685d5245392c2013060000000a1724303d4a5763707d8a96a9b3ab9e928578695f53473a2e2114030000000000000000000000000000000000000000000813202d394653606c7985929facb1a795897c6f6256493c2f23160900000000000000000006111c2a36424d5763707d8a96a1acaa9d9083797979797979797979797979797979797979797979818e9ba7aea2988b7f7265594f4332281e1308000000000000000000000000000000000006111c2a36424d5763707d8a96a1acaa9d9083797979797979797979797979797979797979797979818e9ba7aea2988b7f7265594f4332281e13080000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000c1926333f4c5966727f8c99aa9a8d807467584e434754616e7b86929faba1968c7f736c615e565a5a575f61686d757e86929891857a83909ca3968a7d706354565960686d79839096a1999083786d60554b4035291c110600000000000000000000000000000714202d3a46525e697783909daaaea298897d7063564a4d566673808d99a9ab9b8e8175665b5044382b36414c566673808c99a9ab9b8e8275665c514753606d7a86929facab9e9184786a5f53473b2e21150900000000000000000000000000000000000000000008131e2935414c56616d7a86929faaaca0958a7d706c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c707d8a97a3b0a99c8f8276695c595959595959595959595959595959595959595959595959595953514b43392e23180c0000000000000000000000000000030b12181e24292c2d31353738323e46525e68717e8a939e9f93877c6f67717e8a95a09f92877d716c6667676a6e7a84919ea2988d8073665f6a7783909da4998f82786e696767666d727f8b959f9f93877b6e6154483b2f24180d010000000008131e28323e48525b636d727c82888c8f91929292908e8b857f796e695e5c666f7c87929f9f948b7e71685e524956626f7c8995a99e918578675d5145392c34404d5a6773808d9aa69a8e8174675b4e4134281b0e000d192633404c5966737f868686868686868686868686868686868686868686868578666f7d88939f9d9184796d60574d4237404b555f6a727f8b94999184796d7a8794a0988b7f7265584c3f3225190c00000000000000000c18242f39434e585f696e767e83888c8e909192929291908e8b87827d746d67666f7d88939f9d9184796d60574d42404b555f6a727f8b94999184796d7a8794a0988b7f7265584c3f3225190c00000000000000000815222f3b4855626e7b8898a2aeada197887b6e62554b555e696f7c86929fa4a1969083796d605b51483e342a20170c030d1924303c4855626f7b8898a2aeaca095877a6d6054473a2d2114070000000c1926323f4c5965727f8c98a5b2a99c8f837669574d42372b1e120600000000000000000000000000000000000000000006121f2b3844505b667783909daab1a4978b7e7164584b3e3125180b000000000000000000000e1a25303b4653606c7884919eabaca095897c6f6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7a86929facac9f92867a6d6054473d3221160c010000000000000000000000000000000000000e1a25303b4653606c7884919eabaca095897c6f6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7a86929facac9f92867a6d6054473d3221160c010000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000030f1b27333f49536874818e9bab978a7e7164574b3f4c5965727f8c99a3ab9e9184796d605a524c4d4d4d53565e616c717d8692978d80828f9ca396897c706356494f565d676e7a84919ea0958b7f72675d5145382d22170b00000000000000000000000000000815212e3b4854616e7b87939facab9f9285796d6053464956636f7c8997a1ab9e9285796c605346392d3946525e687783909daaa4998b7e7164544b45515d6776828f9ca9aca196887c6f6255493c31261a0e020000000000000000000000000000000000000000010d1924303a46525e6873808d98a3aea79c9083766b606060606060606060606060606064707d8a97a3b0a99c8f827669666666666666666666666666666666666666666666666666666666605c554b4034281c1004000000000000000000000000060d151d24292f35393a3e4144454645414c56616c75828f97a2999183796d6d7984919da39992857e78757474767b839096a19f92867b6e615864717d8a949e9f948f827b76747475797f87929fa1978e8174695e52463a2d1d130700000000010d1924303a44505a636e737f878f94999c9e9e9d9e9d9b98928c837b6e695e5f6a73808c95a09f92857b6e615a5054616d7a8797a1a197867a6d6053473a2d35414c566875828f9bac998c7f7266594c3f3326190c000d192633404c5966737f8c93939393939393939393939393939393939393939185786b6b74818e97a0968c7f73695f53463e39434e58626d75828f97968d80747a8794a0988b7f7265584c3f3225190c0000000000000004101d2935404b555f6a6e7b838a9095989b9c9a989898999c9b9a938f8981796d676b74818e97a0968c7f73695f53463e434e58626d75828f97968d80747a8794a0988b7f7265584c3f3225190c00000000000000000b1824313e4b5764717e8a97aab4ab9e928578695f53474d57606a717e8a929ca59f958e81756d635a50463c32291e150b0813202d394653606c7985929facb1a795897c6f6256493c2f2316090000000e1b2834414e5b6774818e9aa7b3a79a8d8074675a4d4131261a0e02000000000000000000000000000000000000000000030f1c28333f4a546875818e9ba8b3a6998d8073665a4d4033271a0d0000000000000000000009141f2b3844505b66727f8c99a3aea79a8d8174675c606060606060606060606060605765717e8b98a2aea79b8e8174685d5245392c2013040000000000000000000000000000000000000009141f2b3844505b66727f8c99a3aea79a8d8174675c606060606060606060606060605765717e8b98a2aea79b8e8174685d5245392c201304000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000005121f2b3744505b657783909da499887c6f625549424d566875828f9baba9998c7f73675c514641404042474c525a626b707d8792928785919ea3968a7d7063574a434c555e68707d8a939e9f9285796d60544a3f33281c0f0300000000000000000000000004111d2935414c5665727f8b9aa4afab9b8e8275665c51444653606d7985929eaba197897c6f6356493c303a4754616d7a87939fac9f93867a6d615447404b5565727e8b98a7b1a8998c807366574d42362a1e120500000000000000000000000000000000000000000008131e2a36414c56616e7a86929fabab9f94897c6f63574e535353535353535353535764707d8a97a3b0a99c8f8276727272727272727272727272727272727272727272727272727272726d675c5145382c1f13060000000000000000000000060f181f272f353a4145474a4e505253525150505a616e7a85929fa0958d80736a707d89919fa297928a8482808183879095a09e938c7f72695e55616c75828f95a09f948f8783818082858b9299a29892857a6d61574d42362a1e0c010000000005111d2935414c56616c73808c92999f9f9992919091979c9e9f9590847b6e675c606d79839099a2978f82756c6156525e687885919ea995897c6f6256493c303946525d687784919ea49a897d7063564a3d3023170a000d192633404c5966737f8c999999999999999da0a7a9a29f999999999999999185786b616d7a85929e9f92867b6e615a50443a3c46515b616d7a85919a93887d7a8794a0988b7f7265584c3f3225190c0000000000000006131f2c3945515d676e7c8490959d9d9993908d8b8b8b8d8f92999f9c938e82796d616d7a85929e9f92867b6e615a50443c46515b616d7a85919a93887d7a8794a0988b7f7265584c3f3225190c00000000000000000d1a2633404d596673808c99a6b3a99c8f827669574d42454e58616c73808d939ea79e938c7f736c61584e443b30271d1207121f2b3844505b667783909daab1a4978b7e7164584b3e3125180b000000101c2936434f5c6976828f9ca9b2a5998c7f7266594c3f3326190900000000000000000000000000000000000000000000000b17222d404d5a6773808d9aa6b3a89b8e8175685b4f4235281c0f00000000000000000000030f1c28333f4a54616e7a86929facab9f9285796d60535353535353535353535353535f697683909caaaca095897c6f63564c4135291d110400000000000000000000000000000000000000030f1c28333f4a54616e7a86929facab9f9285796d60535353535353535353535353535f697683909caaaca095897c6f63564c4135291d1104000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000613202d394653606c7985929f9f93867a6d60534746525e697885919eaba297887b6e62554b40363031373a41465059616b727f8b93929197a1a4978b7e7164584b3e434c56616c75828f9ba2978b7f72665b5044382b1f12060000000000000000000000000713202c3945525d6876828f9cacafa3998a7e7164544a4044505c6675818e9baba9998c807366574d42363f4a5464717e8b9aa4a99d908376685e52463b4854616e7b8795a0acaa9d908377695f53463a2d211408000000000000000000000000000000000000000000020d1925303a46525e6874808d99a3aea69b8f82756a5f534746464646464646464a5764707d8a97a3b0aa9d91847f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6053463a2d20130700000000000000000000060f18212a313940454c5254575b5d5e5f5f5e5d59565e68717e8b949e9f92877c6f6b737f8c93999e9f97918e8d8e90939aa09e938e81786d6056505a616e7a8390959e9f9993908e8d8e92979f9f9892867d70685e52453b30251a0e00000000000713202d3946525d68717e8a929fa198928b86848385888f949da0969083796d605c666f7c87939f9e938a7e71685e52566975828f9ca5988b7f7265574d42363b4754616d7a86939f9f93867a6d6154473a2e211407000d192633404c5966737f8c8c8c8c8c8c8c8c9095a0a297928c8c8c8c8c8c8c8c85786b5d68717e8b949f988f82766c61564c41353f46525e68707d88939a91847a8794a0988b7f7265584c3f3225190c00000000000004111d2935414c55606d798391969f9b938e8783807f7e7f8082878f949e9d948e81746a68717e8b949f988f82766c61564c413f46525e68707d88939a91847a8794a0988b7f7265584c3f3225190c00000000000000010e1b2834414e5b6774818e9aa7b4a79a8d8174675a4e413d46505a606c77818f95a0a59f93887e706a5f564c43392e2318110f1c28333f4a546875818e9ba8b3a6998d8073665a4d4033271a0d000000101d2a3643505d697683909ca9b1a4978a7e7164574b3e3124180b0000000000000000000000000000000000000000000000061926323f4c5965727f8c98a5b2a89c8f8275695c4f4236291c0f00000000000000000000000b17222d3846525e6875828e9ba8ada2978a7e7164574d42464646464646463f4a54626e7b88949fabaa9d9084776b6054443a2f24190d0100000000000000000000000000000000000000000b17222d3846525e6875828e9ba8ada2978a7e7164574d42464646464646463f4a54626e7b88949fabaa9d9084776b6054443a2f24190d01000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000714212d3a4754606d7a8798a29e918478675c51454754616e7a8797a1ab9e928578695f5343392f25262b30363e474f59626d74818e979ea1a9a6998c7f7366594c403b444f59626f7c88949e9e9184786c605346392d22170b0000000000000000000000000714212d3a4754606d7a86929facac9f92867a6d6054473a3f4a5464717e8a99a3aa9d908377695e52463a44505c6675828e9baca8998c7f7366564c413a46535e697783909daaaca095887b6e6155483b3025190d0100000000000000000000000000000000000000000008131e2a36414c56616e7b86929fabac9f93877b6e62564d423639393939393d4a5764707d8a97a3b0aca096918c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877a6d6054473a2d211407000000000000000000030c18212a333c434b51565d6064686a6b6c6c6b69666260626c76828f98a2999083786d6d737f878f94989b9d9b9a9a9d9c9996918a81786d665c5046525e686e7a838b92979a9c9c9a9a9b9d9b9a938e867d706b60564c4133291f14090000000004111d2935414c56616d7a85929ea19792867f7a7776787c828d929d9f958c7f73685e606a73808d96a09e92857a6d61595965727f8c98a79c8f8275695e524641444f5964717e8a9aa49d908377685e5246392d20130700091623303c4956636f7d808080808080808083909d9f928580808080808080807f726556626c76828f989f948a7e71685d52453d36414c56616b74808d95958c808c99a5988b7f7265584c3f3225190c0000000000000613202c3945515d6773808d95a09b918c817b767372717273767b828f939e9f93877c6f626c76828f989f948a7e71685d52453d414c56616b74808d95958c808c99a5988b7f7265584c3f3225190c0000000000000003101c2936434f5c6976828f9ca9b2a5988c7f7265594c3f343e44505b656d79839097a1a49a92867c6f685e554b403428231a1017222d404d5a6773808d9aa6b3a89b8e8275685b4f4235281c0f020000111e2a3744515d6a7783909daab0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4b1a99c908376695d5043362a1d10000000000000000000000006111c2a36414c5663707d8996a0aca99c8f8276695e5246382d393939393844505c6673808d99a6aea2988b7f7265594f4332281e130800000000000000000000000000000000000000000006111c2a36414c5663707d8996a0aca99c8f8276695e5246382d393939393844505c6673808d99a6aea2988b7f7265594f4332281e130800000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000815212e3b4854616e7b8794aa9d9083776a554b404955626f7c8895a9a99c8f837669574d4231271d1a1e252a353e47515b616d7a85929ea7b1a79a8e8174675b4e41323e47535f6a75828f9ca096897d7063544a3f33281c0f030000000000000000000004101c2934404b5564717e8b99a3afa99c8f8376685d5245393a4754606d7a86929faca095877b6e6154473b4653606d7985929faba196887c6f6255493c36424d576673808d99a9b1a7988c7f7265564c41362a1d1105000000000000000000000000000000000000000000020e1925303b46525e6974818d99a3afa49a8e8174695e52463a2f242d2d313d4a5764707d8a97a3b0b2a8a09d99999999999999999999999999999999999999999999999999999993877a6d6054473a2d2114070000000000000000000b151e2a333c454d555d60686d7174777879787776736f6c65616e7b86929fa0958c7f736a6d727c82888b8f9091929291908d89847d756d665c544a414c565e686d787e85898d9091929291908f8b87817b706b60594f443a3021170d02000000000713202c3945525d6873808d97a19e92857c726d676a6a6f77808d95a09f92867a6e6158606d7984919aa1978e81756b6155616e7b88959f9f92867b6e615a524d5056606b75828f9ca4998c7f7366564c4135291d1105000915222f3b4854606b6f7373737373737374818e9b9e91847873737373737373726d62575a626e7b86929f9e91857a6d60584e42383a444f59606d798390989285929fa5988b7f7265584c3f3225190c0000000000000714212d3a4754606d7a85929f9e948c7f746e696765656566696e78818f98a39a8e817566626e7b86929f9e91857a6d60584e423a444f59606d798390989285929fa5988b7f7265584c3f3225190c0000000000000004111d2a3744505d6a7783909daab1a4978a7e7164574b3e31333f49535d676e7b859299a3a29891847a6e675c51453f352c22181926323f4c5965727f8c98a5b2a89c8f8275695c4f4236291c0f030000111e2b3844515e6b7784919eaaafa396897c706356493d3023160a00000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1aa9d9083776a5d5044372a1d110000000000000000000000000d1925303b4854606b7784919daaac9f93877b6e6153493f33272d2d2d3a4653606d7984919eabac9f92867a6d6054473d3221160c01000000000000000000000000000000000000000000000d1925303b4854606b7784919daaac9f93877b6e6153493f33272d2d2d3a4653606d7984919eabac9f92867a6d6054473d3221160c0100000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000815222f3b4855626e7b8895a19c8f8376695c5043495663707c8996a3a89b8e8175685b4e423128150e1319232c353f46525d68717e8a95a0aca99c90837669574d423637434e5864707d8a97a29a8e8174665b5044382b1f12060000000000000000000006131f2c3845515c6775828f9babb1a7988b7f7265564c41353945525d687683909ca9a7988b7e7165544b40495663707c8997a2ab9e9184786a5f53473b313c4956636f7c8997a1ada99c908376685e5246392d2013070000000000000000000000000000000000000000000008141e2a36424d57616e7b87929fabac9f92867b6e61564c4135291d24313d4a5764707d8a97a3b0bab2acaaa5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a093877a6d6054473a2d211407000000000000000007121d27303c454e575f676d737a7e81838586858483807c78706b69727e8b949f9f92867c6f666a6f757b7f82848586858483807c79706c605c544a423b444c565e666d72797d80838485868584827e7b746e6860594f473d32281e0f0500000000000714212d3a4754606d7a86929f9f958a7e716a605d585f656d7883919da3988d8073665c5d67707d88939f9e938a7d70675d5f697683909da3998e81756c615e565b60686f7d87939f9f93877b6e6155483b3025190d01000713202c38444f5960636666666666666874818e9b9e9184786b66666666666665625b51535f6973808c96a0978d80746a60544a3f343d45515c676f7c8692989298a2a5988b7f7265584c3f3225190c0000000000000b1825323e4b5865717e8b989e9c8f82756d615e57585858575e666e7b86929f9e9285796d606973808c96a0978d80746a60544a3f3d45515c676f7c8692989298a2a5988b7f7265584c3f3225190c0000000000000004111e2b3744515e6a7784919daab0a3968a7d7063574a3d302d38414b555e696f7d87929fa4a1969083796d605b51473e342a201725323e4b5865717e8b98a4b1a99c908376695d5043362a1d10030000121f2b3845525e6b7885919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0aa9e9184776b5e5144382b1e1100000000000000000000000008141e2c38444f5965727f8c98a3aea4998c7f73655b5044372b1f2a36414c5663707d8a97a1ada79b8e8174685d5245392c201304000000000000000000000000000000000000000000000008141e2c38444f5965727f8c98a3aea4998c7f73655b5044372b1f2a36414c5663707d8a97a1ada79b8e8174685d5245392c2013040000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000916232f3c4956626f7c8995a29c8f8275695c4f424a5764707d8a97a3a79a8e8174675b4e4134281b0e08111a232935414c56616c7783909da8ab9f928578695e52463a323c4653606d7985929e9e9285796c605346392d201306000000000000000000000714202d3a4753606d7985929facaca095887b6e6155483b3035414c5666727f8c99a8a89b8f8275665c51454d576673808d99a9aa9a8d817467584e43372d394653606c7985929eabac9f93867a6d6154473a2f24180d01000000000000000000000000000000000000000000020e1a25303b46535e6974818e99a3aea3998d8073685d5245392e2324313d4a5764707d8a97a3b0b8b0aaa99f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f93877a6d6054473a2d21140700000000000000000c18232e39424e575f696e7980868a8e9091929291908c89837d746c6c77828f98a2999083786d6062696e7275777879787776736f6d66615a504a4238323b444c545c60676d707376777879787775716e69615e564f473d352b20160c000000000004101d2935404b5565727e8b98a29d9083766c6158514e535c66707d8a97a19e9185796d6055606b74818e96a19e91847a6d605964717e8a95a09e938b7e736e6869666c707a84919aa3998f8275695f53463a2d1e13080000030f1b27323d474f545659595959595b6874818e9b9e9184786b5e5959595959595751494d57606d7984919e9f93877c6f665c50443b34404b555f6a727f8b949fa2aaa5988b7f7265584c3f3225190c0000000000000e1b2835414e5b6874818e909192897c6f635b524d4c4b4c4d545e6976828f9ca297887b6e61606d7984919e9f93877c6f665c50443b404b555f6a727f8b949fa2aaa5988b7f7265584c3f3225190c0000000000000005121e2b3845515e6b7884919eabafa396897c706356493d30262f3a434d57606b717e8b929da69f958e81756d635a50463c32291e24313e4b5764717e8a97a4b1aa9d9083776a5d5044372a1d11040000121f2b3845525e6b7884919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0aa9d9184776a5e5144372b1e1100000000000000000000000002101c27333d4754616d7a86929facab9e9184786c6053463a2f242d3946525e6875828f9ba9aca095897c6f63564c4135291d1104000000000000000000000000000000000000000000000002101c27333d4754616d7a86929facab9e9184786c6053463a2f242d3946525e6875828f9ba9aca095897c6f63564c4135291d11040000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000a1623303d495663707c8996a39b8e8275685b4f424b5764717e8a97a4a79a8d8074675a4d4134271a0e0008111924303a44505a64717e8a96a1aca297877b6e6154473b2e3845515c6674818e9ba197897c6f6356493c30231608000000000000000000030f1c28333f4a5463707d8a98a2aeaa9d908477695f53463a2d303c4855626f7b8896a1ac9f9285796d605346535e697784909daaa2988a7d7063574a3d322b3844505b6674818e9babafa4998b7e7165554b4035291d10040000000000000000000000000000000000000000000009141f2a36424d57616e7b87929fabab9f92857a6d60554b40342824313d4a5764707d8a97a3b0b0a69f9c93939393939393939393939393939393939393939393939393939393877a6d6054473a2d2114070000000000000004101c2834404b545f6a6e7b848c92989b9d9e9d9d9e9c9995908980776c6e7b86929f9f958c7f72695f5f6165686a6b6c6c6b696663605c5450443f383029323a424a50555c606367696b6c6c6b6a6865615e57524d443d352b23190e04000000000006131f2c3945515d6776828f9ca8988b7f72655a5045414a54606d7985919ea197897c70635659606d7a84919ea1968e81746b60606c78839098a39b908b807b777576797d849196a09f92877c6e62574d42362a1e0c020000000b16212b353d4448494d4d4d4d4e5b6874818e9b9e9184786b5e514d4d4d4d4c4a463f45515c67707d89939e999083786d60574d423639434e58626d75828f97a19f9f988b7f7265584c3f3225190c0000000000000c1926323f4c5965727f8283848586786d605346423f3e3f424d576773808d9aa995897c6f625c67707d89939e999083786d60574d4239434e58626d75828f97a19f9f988b7f7265584c3f3225190c0000000000000005121f2c3845525f6b7885929eabafa296897c6f6356493c302328313b454f59626c73808d949ea79e938c7f726c61584e443a302724313d4a5764707d8a97a3b0aa9e9184776b5e5144382b1e11050000111e2b3844515e6b7784919eaab0a396897d7063564a3d3023170a00000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a99d9083766a5d5043372a1d10000000000000000000000000000b16202d3946525d6875818e9ba7aca096897c7063554b4135292e3a4754616d7a86929facaa9d9084776b6054443a2f24190d010000000000000000000000000000000000000000000000000b16202d3946525d6875818e9ba7aca096897c7063554b4135292e3a4754616d7a86929facaa9d9084776b6054443a2f24190d010000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000091623303c4956636f7c8996a29b8f8275685c4f424a5763707d8a96a3a79a8e8174675b4e4134281b07000008131e28323e4653606d7984919eaba9978a7d7064574a3d2d34404b5464717e8a97a8998c7f7266594c3f2f24190d01000000000000000006121f2b3844505b6674818e9baab3a9998d807366574d42362a2e3a47535f6a7884919eaba298897d7063564954616e7b8795a0ac9f9286796d6053473a2d28333f4a5464717d8a99a3aeab9c8f8275675d5145392c20130600000000000000000000000000000000000000000000020e1a25313b46535f6975818e99a4aea2988c7f72675c5145382d22313d4a5764707d8a97a3b0aa9f948f86868686868686868686868686868686868686868686868686868686867a6d6054473a2d2114070000000000000006131f2c3845515c666e7c8591969f9f9c9791909092989fa09d928d81786c727f8c959f9f92867b6e665b55585c5d5e5f5f5e5d5a5653504a423e342e26202930383f444b5153565a5d5e5f5f5e5d5c5854524d46413b322b231911080000000000000714202d3a4753606d7a86929fa196877a6e6154473e3944505c6674818d9aa9998d80736654515d67707d8a939e9f93887d70675d666f7c869299a29b928d86838283858a9196a09d938c80736a5f53453b31261a0e00000000040f19232b32383b3c404040414e5b6874818e9b9e9184786b5e51454040403f3e3a34404b55606b75818e97a0958c7f72695e52463e313c46515b616d7a85919a9393938b7f7265584c3f3225190c0000000000000c1825313e4a57636d7275767778796d665c5044383030363f4c5966727f8c99ab96897d706355606b75818e97a0958c7f72695e52463e3c46515b616d7a85919a9393938b7f7265584c3f3225190c0000000000000005121f2b3845525e6b7885919eabafa296897c6f6356493c30231f29333d47505a606c78828f95a0a59f93887e706a5f564c42392e23313e4a5764717d8a97a4b0aa9d9184776a5e5144372b1e11040000111e2a3744515d6a7784909daab0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000c1825323f4b5865727e8b98a5b1a99c8f8276695c504336291d100000000000000000000000000005111d2935414c56636f7c8995a0aca89b8e8174675d5145392c37434e5865727f8b99a3aea2988b7f7265594f4332281e13080000000000000000000000000000000000000000000000000005111d2935414c56636f7c8995a0aca89b8e8174675d5145392c37434e5865727f8b99a3aea2988b7f7265594f4332281e1308000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000916232f3c4956626f7c8995a29c8f8275695c4f42495663707c8996a3a89b8e8175685b4e422e23180c0000020c16202c3844505c6673808d99a9a6998c807366544a3f332e3a4754616d7a8796a19b8f827568564c4135291d110400000000000000000613202d394653606c7985929eabada197897c6f6256493c31262b37434e586774808d9aaaaa9a8d807367574d5565727e8b98a7a89c8f8275675d5145382c222d3a4754606d7a86929facac9f92867a6d6053473a2e23170c000000000000000000000000000000000000000000000009141f2b37424d57626e7b87939facaa9e9184796d6053493f3327313d4a5764707d8a97a3b0a99c8f82797979797979797979797979797979797979797979797979797979797976685d5245392c20130700000000000004111d2935414c56606d79849197a19e949089858384858b9297a29d938c7f726c78839098a3989083786c60574d4f5152535251504d4946443f383028231c171e262e34394045474a4d5051525352514f4b4846423b3630292019110800000000000000091623303c4956636f7c8998a39e918478685e524639343f4a5464717e8b97ac9c908376665b5055616b75818e97a19a9184796d60606a717e8792989f9d9992908f8f91979ea09d938e81786d60584e4333291f1409000000000007111921272c2f30333335414e5b6874818e9b9e9184786b5e514538333332312e2e39434f59616d7a85929f9f92867b6e61594f4339343f46525e68707d8786868686867f7265584c3f3225190c0000000000000916222e3a46515b636568696b676d675c544a3f41414142464e586673808d99a399887c6f625559616d7a85929f9f92867b6e61594f43393f46525e68707d8786868686867f7265584c3f3225190c0000000000000005111e2b3844515e6b7784919eaab0a396897d7063564a3d302317212b353f44505b666d79839197a2a49a92867c6f685e544b403428313e4b5864717e8b97a4b1aa9d9084776a5d5144372a1e11040000101d2a3643505d697683909ca9b1a5988b7e7265584b3f3225180700000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685c4f4235291c0f00000000000000000000000000010d1924303a4854606b7783909daaac9f92857a6d6054473c313b4754606a7783909dabac9f92867a6d6054473d3221160c0100000000000000000000000000000000000000000000000000010d1924303a4854606b7783909daaac9f92857a6d6054473c313b4754606a7783909dabac9f92867a6d6054473d3221160c01000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000915222f3c4855626f7b8895ab9c908376695d50434955626f7c8895a9a99c8f837669554b4034281c1004000004101c28343f4a54626f7c8996a1a99c8f8276665b5044382d3946525e687884919e9e918578685d5245392c2013070000000000000000091623303c4956636f7c8997a1adab9e9185786c605346392d2026313d4a5663707d8998a2aa9d918477695e535c6775828f9ca8a7988b7e7265554b403529202c3945515d6776828f9ca9aea3988a7d7164544a3f34281c100300000000000000000000000000000000000000000000030e1a26313c47535f6a75818e9aa4ada1978b7e71655b5044372b313d4a5764707d8a97a3b0a99c8f82766c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5d564c4135291d11040000000000000613202c3945525d68737f8c96a09e938e827c787677797e859298a29f92867b6e6e7b86929f9f948b7f72695f53493f4546454443403c3a38342e261e17110c151c23282f34383a3d40434445464544423e3b3a36302a251f170e0800000000000000000c1925323f4c5865727f8b98aa9b8f827568564d41362e3b4855626e7b889aa49f9285796c60534f59616d7a85929ea0968d80746a60616c717e868e92999b9d9d9c9c9e9c9a96918a81786d665c50463c3121180d03000000000000070f161b202223262835414e5b6874818e9b9e9184786b5e5145382b2626251d27303d46525e68717e8b949f988f82756c61554b403536414c56616b70797979797979726d62564a3e3124180b00000000000006121e2a353f495157595b5d555c605c554b474e4e4e4e4d52575f6a76838f9c9f92867a6d6054525e68717e8b949f988f82756c61554b4036414c56616b70797979797979726d62564a3e3124180b0000000000000004111e2a3744515d6a7784909daab0a3978a7d7064574a3d312417192328333f4a545d676e7b859299a3a29891847a6d665c51453f35323f4b5865727e8b98a5b1a99d9083766a5d5043372a1d100400000f1c2835424f5b6875818e9ba8b3a6998c807366594d402f23180c00000000000000000000000000000000000000000000010e1b2834414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e000000000000000000000000000008131e2c38434f5965727f8b98a2aea2988b7e7165574d4237404b55626f7c8895a0aca79b8e8174685d5245392c20130400000000000000000000000000000000000000000000000000000008131e2c38434f5965727f8b98a2aea2988b7e7165574d4237404b55626f7c8895a0aca79b8e8174685d5245392c20130400000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000714212e3a4754616d7a8799a49d9184776a564c414754606d7a8797a1ab9e918478675c5145382c1f13060000000c17232e394653606c7884919eab9f9285796c605346392d36414c566975828f9ca197877a6d6054473a2d2114070000000000000006121f2b37434e586773808d9aa9b3aa9a8e8174655b5044372b1f202d3a4653606d7985929faca095877b6e6154606d7985929faca095877b6e6154483b2f241d2935414c5565727f8b98a7b1aa9b8e8175665c5044382c1f1206000000000000000000000000000000000000000000000009141f2b37434e58626f7c87939faca99d9184786c6053463d32313d4a5764707d8a97a3b0a99c8f8276696060606060606060606060606060606060606060606060606060605f524c443a2f24190d010000000000000714212d3a4754606d7a86929fa1978e81786f6a6a676d717c86929fa2988e81746a727f8c95a09f92867b6e655b50443b3039383633302d2c28231c150c06030a11171d23292c2d303436383939383735322e2d2a251f19140d050000000000000000000e1b2734414e5a6774818d9aa69a8d8073675a4d40302d3a4653606d7986939fa298877b6e615448525e68717e8a939e9f93877c6f675c616c717b81868b8f9192929291908d89847d746d665c544a3f342a200f060000000000000000040b0f1315161b2835414e5b6874818e9b9e9184786b5e5145382b1e1918151e2a36414c56606c778390999e938a7d70675d51453c2f3a444f5961636c6c6c6c6c6c65625b51463a2e221509000000000000010d18232d373f464a4c4f504b5153514c52545a5a5a5b575e61696f7c87929f9c8f8376675d514c56606c778390999e938a7d70675d51453c3a444f5961636c6c6c6c6c6c65625b51463a2e2215090000000000000003101d2a3643505d697683909ca9b1a5988b7e7265584b3f3225181017222d38424c555f69707d87929fa4a1969082786d605b51473e34404d596673808c99a6b3a89c8f8275695c4f4236291c0f0300000d1a2734404d5a6773808d9aa6b3a89b8e817568554b4034291c100400000000000000000000000000000000000000000005121e2a36424d576976838f9ca9b2a5988c7f7265594c3f3226190c0000000000000000000000000000020f1b27323d4754606d7a86929facaa9c908376695f53473845515c6774808d9aa7aca095897c6f63564c4135291d1104000000000000000000000000000000000000000000000000000000020f1b27323d4754606d7a86929facaa9c908376695f53473845515c6774808d9aa7aca095897c6f63564c4135291d110400000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000613202d394653606c7986939f9f928578685d524545515d677885919eab9f9386796d6053463a2d20130800000006121f2b3744505b6575818e9ba8a298887b6f6255483c2f30404d5a6673808d99a995887c6f6255493c2f221609000000000000000815212e3b47535f6a7784919eaaaea2988a7d706453493f33271b1f2c3845515c6775828f9baca7988b7e72655463707d8998a2aa9d908377695e52463a2d1d19242f3b4855616e7b8895a0acab9f9285796d6053463a2d20130a0000000000000000000000000000000000000000000000030f1a26313c47535f6a75828f9ba6aca0968a7d7064594f4438313d4a5764707d8a97a3b0a99c8f8276695c53535353535353535353535353535353535353535353535353535345413a32281e130800000000000004101c2934404b5565717e8b98a29e92857a6d6660585c606a717e8b96a19f92857a6d6d78839099a2988f82776c60574d42362a2b2a2723201f1c17110a03000000060c12181c1f2023272a2b2c2c2b2a292521201e1a140e0802000000000000000000000f1c2936424f5c6975828f9ca5988c7f7265594c3f322c3845515c667885929eaa96897c706356494c56616c75828f97a2999183796d605a61696e757b7f82848586858583807c78706c605c544b42382e22180e00000000000000000000000307090e1b2835414e5b6874818e9b9e9184786b5e5145382b1e120b0c1925303a44505b656f7c87929f9e9184796d60584e4138323d474f5556606060606060585651493f34291e12060000000000000007111c252d353a3e3f42434045474c565d616767676869696e727b8491999e938a7d7063554b44505b656f7c87929f9e9184796d60584e41383d474f5556606060606060585651493f34291e120600000000000000020f1c2835424f5b6875828e9ba8b3a6998c807366594d402f23180c111c262f3a434d57606b727f8b929da69f948e81746d63594f463c414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e0100000c1925323f4c5865727f8b98abb5aa9d908477675c5145382c1f13060000000000000000000000000000000000000000000714212d3a46535f697885929fabb4aa968a7d7063574a3d3024170a0000000000000000000000000000000a16202c3945515d6774818e9aa7ab9f94887b6e62544a3f4653606d7985929fabaa9d9084776b6054443a3024190d01000000000000000000000000000000000000000000000000000000000a16202c3945515d6774818e9aa7ab9f94887b6e62544a3f4653606d7985929fabaa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000006121f2b3844505b667884919ea297877a6d605447414c556976838f9ca9a499897c6f6356493c3025190d000000030f1b27333f495365727e8b98acaa988b7e7265584b3f30323f4b5865727e8b98a3978a7d7064574a3d3124170a000000000000000915222f3c4855626f7c8896a0acac9f9286796d6053473a2d22171c2834404b5565717e8b9aa4a89c8f8275665c6774808d9aaaa9998d807366574d42362a1e14212d3a46535f697784919daaada297897d706356493d32271b0f0300000000000000000000000000000000000000000000000915202b37434e58626f7c88949eaaa89d9083766b6054483c313d4a5764707d8a97a3b0a99c8f8276695c4f464646464646464646464646464646464646464646464646464639352f2820160c0100000000000006131f2c3845515c677683909ca9998c7f73675d544e5157606d7984919ea2988b7e71666f7c87929f9f948b7e72695e52463e32291f1a161312100c0600000000000001070c101314171a1d1e1f201f1e1c181514120e0902000000000000000000000000111d2a3744505d6a7783909da4978a7d7164574a3e312834404b546a7783909da4978a7d7164574a44505a616e7b85929fa0958c80736a5f575f61696e727577787979787673706c65615a514b423930261c0f0600000000000000000000000000020e1b2835414e5b6874818e9b9e9184786b5e5145382b1e120008131e27333f49535f6a73808d96a0968d80736a5f53493f33353d44484a5353535353534c4a463f372d23180d0100000000000000000a131c232a2e3132352f343946525d686d7474747475777b7f8591969e938e81746b6155433f49535f6a73808d96a0968d80736a5f53493f333d44484a5353535353534c4a463f372d23180d0100000000000000010d1a2734404d5a6773808d9aa6b3a89b8e817568554b4034291c100a141d28313b454f59626d74808d949fa69d938c7f726b61584e44424d57697683909ca9b2a6998c7f7366594c403326190d000000091623303c4956636f7c8999a4afac9f9286796d6053473a2d22170b0000000000000000000000000000000000000000000815222e3b4855616e7b8897a2adaea298887b6e6155483b2e22150800000000000000000000000000000004111d2935414c55626f7c88959faba6998d8073665c50444d5764717e8a97a2ada2988b7f7265594f4332281e1308000000000000000000000000000000000000000000000000000000000004111d2935414c55626f7c88959faba6998d8073665c50444d5764717e8a97a2ada2988b7f7265594f4332281e13080000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000030f1c28333f4a546976838f9ca995897c6f625649404d5a6673808d99aaab998c7f7266564c41362a1c11060000000b17222d3c4956626f7c899aa4a89b8e817568564c4136313d4a5764707d8a97a3988b7f7265584c3f3225190c00000000000005121e2a36424d5766737f8c99a8b2ac9c8f8275675d5145382c1b1118232e3b4754616e7a87939fac9f9285796d60697784919daaa197897c6f6256493c30251a121e2a36424d576673808d99a9b3a99a8d807467584e43372b1f13060000000000000000000000000000000000000000000000030f1b26313c4754606a75828f9ca6ab9f95897c6f63584e43373d4a5764707d8a97a3b0a99c8f8276695c4f43393939393939393939393939393939393939393939393939392c29241e160d04000000000000000714202d3a4753606d7986929fa197887b6f62554b4245515c6674818d9aaa9b8e8174686a73808c95a09f92867b6e615a50443b3025190e07060300000000000000000000000406070a0d1011121312110f0b080705020000000000000000000000000000121e2b3845515e6b7884919ea3968a7d7063574a3d30232e43505d697683909ca5988b7e7265584b3f46525e69717e8b949f9f92877c6f665c53575e6165686a6c6c6c6b696763605b535045403930271e140a0000000000000000000000000205070e1b2835414e5b6874818e9b9e9184786b5e5145382b1e1205020b17222d38414e58606d7984919e9f92877c6f655b50443b3033383c3d4646464646463f3e3a342d251b1106000000000000000000010a11181e22252628232e3a4754616d7a808181818284878c929796918b81796d60594f4438414e58606d7984919e9f92877c6f655b50443b33383c3d4646464646463f3e3a342d251b11060000000000000000000c1925323f4c5865727f8b98abb5aa9d908477675c5145382c1f13060b161f2a333d47515b606d78828f96a0a59f93877d706a5f564c47535f697885929eabb4aa978a7e7164574b3e3124180b0000000714202d3a4753606d7a86939facaea399897d706353493f33271b0f030000000000000000000000000000000000000004111d2935414c5565717e8b98a9b3ac9f9285786d6053463a2d201307000000000000000000000000000000010d19242f3a47545f6a7783909da9ab9e9184796d605346525e6976828f9ca9ac9f92867a6d6054473d3221160c020000000000000000000000000000000000000000000000000000000000010d19242f3a47545f6a7783909da9ab9e9184796d605346525e6976828f9ca9ac9f92867a6d6054473d3221160c020000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000b17222d414e5b6774818e9aa4978b7e7164584b3e495663707c8998a2a99c8f8276685e5246382d22170b0000000614202d3a4753606d7a86939faa9e918477685e5246392f3c4956626f7c8995a2998c7f7266594c3f3326190c0000000000000714212d3a46535e697783909daaafa49a8b7e7165554b4035291d0a14202d3946525e687783909daaa298897c70636e7b8796a0ab9e9285796c605346392d20130e1a26313c4956636f7c8997a1adab9e9184786a6054473b2e2215090000000000000000000000000000000000000000000000000a15202b37434e58626f7c89949faba79c8f82756a5f53473b3d4a5764707d8a97a3b0a99c8f8276695c4f43362d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d201d19130c0400000000000000000916232f3c4956626f7c8999a39e9285796c6053463a404a5464717d8a97ac9d90847767606d79839099a2988f82766c62564d41362a20170c0200000000000000000000000000000000010305060605040200000000000000000000000000000000000000121f2c3845525f6b7885929ea396897c706356493d302936434f5c6976828f9ca5988c7f7265594c3f424d56626c76828f98a2999083786d60584e5254585c5e5f5f5f5e5d5a56535049413e342e271e150c020000000000000000000002090e1114141b2835414e5b6874818e9b9e9184786b5e5145382b1e12050006111b262f3c45515d67707d8a939e999083776c60564c41362a2c2f3039393939393932312e29231b1309000000000000000000000000070d121618191c212e3b4854616e7b878d8d8e8f9193938f8d89847e756d675c51473e2f3c45515d67707d8a939e999083776c60564c41362c2f3039393939393932312e29231b130900000000000000000000091623303c4956636f7c8999a4afac9f9286796d6053473a2d22170b040d18212b353f44505c666d7a849197a2a49992867c6f685e544b55626e7b8897a2adaea298887b6f6255483c2f2215090000000613202c3945515d677784909daab4ab9a8d8073655b5044372b1f140a000000000000000000000000000000000000010c13202c3945515d6775828e9ba8b5a89c8f8275665c5044382b1f12060000000000000000000000000000000008131e2b37434e5865717e8b97a2ada1968a7d7063564c54616e7b87939faca79b8e8174685d5245392c2013040000000000000000000000000000000000000000000000000000000000000008131e2b37434e5865717e8b97a2ada1968a7d7063564c54616e7b87939faca79b8e8174685d5245392c201304000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000061825323f4b5865727e8b98aa9a8d817467564c414653606d7986929fac9f92867a6e61544a3f33281d1207000006131f2c3945515d677885919eaba096877a6e6154473b2f3c4955626f7c8895a2998c807366594d4033261a0d0000000000000815212e3b4854616e7b8795a0acac9f93877a6e6154473b2f24180c111e2a36414c5666737f8c99a9aa998d807366717e8b97a8ab9b8e8174665b5044382b1f120913202d3a4653606d7985929eabada196887c6f6255493c31261a0e020000000000000000000000000000000000000000000000040f1b27323c4854606a76828f9ca6ac9f93877c6f62574d423d4a5764707d8a97a3b0a99c8f8276695c4f433629202020202020202020202020202020202020202020201413110d08010000000000000000000b1825323e4b5865717e8b98ab9c908376655b5044373b4855626e7b889aa49f9286796d60666f7c87929f9e948b7e71685e52463e32291e130800000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3945525f6c7885929fa296897c6f6356493c302935424f5c6875828f9ba6998c7f7366594c403b44505a616e7b86929fa0958c7f726a5f544a484c4f5152535252504d4946443f382f28231d150c0300000000000000000000050d14191e2021272835414e5b6874818e9b9e9184786b5e5145382b1e120500000a141d2935404b55616b75818e989f958b7e72685e52463d302723232d2d2d2d2d2d2524221e18110901000000000000000000000000000106090c0c15212e3b4854616e7b87949a9b9c9e938682807d78716c605c554b40352935404b55616b75818e989f958b7e72685e52463d3027232d2d2d2d2d2d2524221e18110901000000000000000000000714202d3a4753606d7a86939facaea399897d706353493f33271b0f03060f192328343f4a545d686e7b859299a3a29891847a6d665c515665717e8b98a9b3ac9f9285796d6053463a2d20130700000004101d2935404b556773808d9aa9b3ab9e9184786c6053463c2f261b1106000000000000000000000000000000000007131d28333f4a54606d7a86929facb1a7988b7f7265544a3f34281c100300000000000000000000000000000000010f1b26323c4753606d7985929faba99b8e8275685d525966737f8c99a4aca095897c6f63564c4135291d110400000000000000000000000000000000000000000000000000000000000000010f1b26323c4753606d7985929faba99b8e8275685d525966737f8c99a4aca095897c6f63564c4135291d1104000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000916222f3c4955626f7c8898a29d908377685d524545515c6775828e9ba8a3998b7f72665b5044392e23180f060004101d2935404b556a7784909daaa8978a7d7064574a3d2f3b4855626e7b8895a19a8d8074675a4d4134271a0e000000000005111d2a36414c5665727f8b98a7b1a99d908376685e5246392d1d12070e1925303c4955626f7c8896a1a99d9083766774818e9ba7a3998a7d7164544a3f33281c0f06121f2b3844505c6674818e9babb2a8998c807366574d42372b1e12060000000000000000000000000000000000000000000000000a15202c38434e5863707d89949faba49a8e8174695e52463d4a5764707d8a97a3b0a99c8f8276695c4f4336291c1313131313131313131313131313131313131313130707040100000000000000000000000d1a2633404d596673808c99a69b8e81746853493f333a4653606d7986939fa399887b6e61606a73808d96a09f92857b6e615a50443a3025190e04000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3945525f6c7885929fa295897c6f6256493c2f2935424f5c6875828f9ba6998c7f7366594c40323f46535e69727f8b949f9f92867c6e665b50443f42444546464543403d3937332d261d18120b0300000000000000000000050e171f252a2d2e342d35414e5b6874818e9b9e9184786b5e5145382b1e12050000020b18242f39434f59616e7b85929f9f92857a6e61594f43392e2318202020202020191815120d06000000000000000000000000000000060b0f12131c212e3b4854616e7b8793939495989a9285817d756e685e574d43392e242f39434f59616e7b85929f9f92857a6e61594f43392e23182020202020191815120d060000000000000000000000000613202c3945515d677784909daab5ab9a8d8073655b5044372b1f140a00071117232e38424c565f69707d87929fa5a0969082786d605b5d6875828f9ca8b5a99c908376665c5044382b1f1206000000010d18242f3d495663707c8997a1adaca196897d7063584e41382d22170f06000000000000000000000000000000071118242f3844505b66717e8b98a2aeaca095887b6e6155483b2e23170b0000000000000000000000000000000000000a151f2c3945515d6774808d9aa6ac9f92867a6d6154606b7784919eabaa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000000000000000000000000000a151f2c3945515d6774808d9aa6ac9f92867a6d6154606b7784919eabaa9d9084776b6054443a3024190d01000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000713202d3a4653606d7985929f9f93867a6d605447404b5563707d8996a1ab9e9184786c60554b4034282118100b09111d2a36414c566a7784919daaa69a8d807367554b40343b4855616e7b8894a19a8d8174675a4e4134271b0e00000000000713202d3946525e6876838f9ca9b2a8998c7f7266564c41362a1e0b010815222e3b47545f6a7884919eab9f92867a6d7784919eaa9f92867a6d6054473a2d22170b03101c28343f4a5464717d8a99a3aeaa9d908477695f53473a2d211408000000000000000000000000000000000000000000000000040f1b27323d4854606b7683909ca7ac9f92867b6e61564c414a5764707d8a97a3b0a99c8f8276695c4f4336291c100d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a0a08040000000000000000000e1a2734414d5a6774808d9aa69a8d8073675a4d402d3845515c677885929fab95887c6f6258606d79849199a2978f82756c61564c41362a20160c020000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929ea296897c6f6356493c302936434f5c6976828f9ca5998c7f7266594c3f3336424d57606c78839098a3989083786c60574d41382d393939383634302d2b27221b140b070000000000000000000000020d17202930363a3b413a38414e5b6874818e9b9e9184786b5e5145382b1e120500000007121d27313e46525e68727f8b959f978e81756b60554b4034281f1509131313130c0b0906010000000000000000000000000000020a11171c1f2028232e3b4854616e7b86868687898c9195928e89827a6e695e544a40342827313e46525e68727f8b959f978e81756b60554b4034281f15091313130c0b0906010000000000000000000000000004111d2935404b556773808d9aa9b3ab9e9184786c6053463c2f261b11060006111c26303a444d57606b727f8b939da69f948e81746d62606d7a86929facb2a8998c7f7266544a3f34281c1003000000000713202d3a4653606d7985929eacb2a89c8f82756a5f53493f332721180f0802000000000000000000000003091119232935404b55606c7884919daab3a99d908477695f53463a2d1c110600000000000000000000000000000000000004101d2935404b55626f7b88949faba3998b7e726557636f7c8996a0aca2988b7f7265594f4332281e130800000000000000000000000000000000000000000000000000000000000000000004101d2935404b55626f7b88949faba3998b7e726557636f7c8996a0aca2988b7f7265594f4332281e130800000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000006121f2c3844515c6676828f9ca4998a7d7164554b404653606c7884919ea8a0968a7d71675c51453d332a221c18181a222d3946525e687885929eaba99d908376675c5145383c4955626f7c8895a2998d8073665a4d4033271a0d00000000000714212e3a4754616d7a86929facaca096887b6f6255483c3025190d0006131f2b37434e586774818e9aaaa399897d707b8796a0a99c8f8276675d5145392c1c1106000b17232e3a4754606d7a86929facaca095887b6e6155483b3025190d010000000000000000000000000000000000000000000000000a16212c38444f5963707d89959faba3998d8073685d52454a5764707d8a97a3b0a99c8f8276695c4f4336291c1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a171614100b05000000000000000e1b2835414e5b6874818e9ba6998d8073665a4d403334404b556b7885919ea396897c7063565c676f7c87939f9e938a7e71685e52463e32281e13080000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2b3845525e6b7885919ea396897d7063564a3d30293643505c6976838f9ca5988b7f7265584c3f32313b44505b666e7b86929f9f958b7f72695f53493f33272c2c2b2a2723201f1b17110a0200000000000000000000000009141f29323b4246474d4745404e5b6874818e9b9e9184786b5e5145382b1e1205000000010b151f2a36414d56606c788390999e93897d70675c51453c31261a0e04060606000000000000000000000000000000000000020b141c22282b2d352e343a46535e69767979797a7c7f848c9399948f847b6e665c5144382c1f2a36414d56606c788390999e93897d70675c51453c31261a0e040606000000000000000000000000000000000000010d18242f3d495663707c8997a1adaca196897d7063584e41382d22170f06000a151e28323c454f59626d74818e949fa69d938c7f726b66727f8b98a3aeaca096887c6f6255493c2e23170b000000000006121f2c3844505c6673808d9aa4afaa9e94887c6f655b50443d332a2219140e09060400000100000406090e141a232b353d45515d67717e8a95a0acada2978b7e7265574d42362a1e0a00000000000000000000000000000000000000000c18242f3947535f6a7683909ca9ab9d908376695f6774818e9aa8ac9f92867a6d6054473d3221160c02000000000000000000000000000000000000000000000000000000000000000000000c18242f3947535f6a7683909ca9ab9d908376695f6774818e9aa8ac9f92867a6d6054473d3221160c0200000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000004101c2834404a5465727f8c98a79b8e8175675c514544505b66727f8c96a1a89e9184796d60594f453c342c272524262a343c4754616d7a86939facac9f9286796d6053473a3d495663707c8996a3998c7f7266594c3f3326190c0000000004101d2935404b5564717e8b99a3afaa9e9184776a5f53473a2e1e140800030f1b26323d4a5763707d8a98a2ab998c80737e8a97a8a8988c7f7265554c4135291d0a00000613202c3945515d6776828f9ca9b1a7988c7f7265564c41362a1e110500000000000000000000000000000000000000000000000004101b27323d4854606b7683909da7ab9f92857a6d60554b4a5764707d8a97a3b0a99c8f8276695c4f4336292727272727272727272727272727272727272727272727272423201c1710080000000000000f1c2835424f5b6875828e9ba6998c7f7366594c40332e44515e6b7784919ea3968a7d70635755606b74808d96a09e92857a6d615a50443a3024190d0400000000000000000000000000000000000000000000000000000000000000000000000000000000111e2a3744515d6a7784909da3978a7d7064574a3d312a3743505d6a7683909da4978b7e7164584b3e3128333f4a545f6a737f8c95a09f92867b6e655b50443b30251a1f1d1a1613120f0b0600000000000000000000000000020e1925303b444d52545a53514b4e5b6874818e9b9e9184786b5e5145382b1e120500000000030d1925303b44505b666f7c87929f9e9184796d60574d42372b20160c0200000000000000000000000000000000000000000a141d262d33383942434045464d575e6c6c666d6d6f72787f87939f969083786d6053463c312625303b44505b666f7c87929f9e9184796d60574d42372b20160c0200000000000000000000000000000000000000000713202d3a4653606d7985929eacb2a89c8f82756a5f53493f332721180f08030c16202a333d47515b606d78828f96a0a59f93877d706d7984919eaab4aa9d9184776a5f53473b2e1c1106000000000003101c28343f4a54616e7b87939fabb0a69c9083776c60584e453c342a251e1a1312100c070e070c1013131a1f262a353d47505a606d7984919ea7b1a99f9285796d6053473b31261a0e000000000000000000000000000000000000000007121d2b37434e5864717e8a97a1ab9f95887b6e616d7985929faba79b8e8174685d5245392c201304000000000000000000000000000000000000000000000000000000000000000000000007121d2b37434e5864717e8a97a1ab9f95887b6e616d7985929faba79b8e8174685d5245392c2013040000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000c18232e3b4855616e7b88959f9f9285796d6053473f4a54606d7984919ea6a0968c7f736b60574e463f3833313131363d46505a64717e8a9aa4afaea399897c6f6356493c3d4a5764707d8a97a3988b7f7265584c3f3225190c0000000006131f2c3945515d6775828f9babb3a99a8d807467584e43372b1f0d0200000a14202d3a4753606d7986929fa99c908376818d9aa7a096887b6e6155483b2f24190d000004111d2935414c5565727f8b98a7b1a99c908376685e5246392d201407000000000000000000000000000000000000000000000000000b16212c38444f5963707d8a95a0aba2988c7f72675c514a5764707d8a97a3b0a99c8f8276695c4f43363434343434343434343434343434343434343434343434343431302d28221a110800000000000f1b2835424e5b6875818e9ba6998c807366594d40333845525e6b7885919ea396897c7063564f59606d7984919ea1978e81756c61564c4135291f160c01000000000000000000000000000000000000000000000000000000000000000000000000000000101d293643505c6976838f9ca4988b7e7165584b3e322935414c566b7784919eac968a7d7063574a3d30222d38424e57606d78839099a2988f82776c60574d42362a20170d0d0a06050300000000000000000000000000000005111e2a36424d565e6167605c554e5b6874818e9b9e9184786b5e5145382b1e1205000000000008141f28333f4a545f6a73808d96a0968c8073695f53473e32281e13080000000000000000000000000000000000000006111c262f383f44464f504b51535452535f605c606162666c727f8b95a0958c7f7265574e42372b1f28333f4a545f6a73808d96a0968c8073695f53473e32281e1308000000000000000000000000000000000000000006121f2c3844505c6673808d9aa4afaa9e94887c6f655b50443d332a2219140e090e18212c353f44515c666d7a849198a2a49992867c717e8b96a0acaea3988c7f7265584e43372b1f0a000000000000000c17232e3846535f6975828e99a3afab9f948b7f726a60574e463e36302a25201f1c181b1a1b181c1f20262b31363f474f59616c74808d96a1adada2978d8073675d5145392a1f14090000000000000000000000000000000000000000010f1a26313c4653606d7985929eaca7998c7f7366717d8a98a2aca095897c6f63564c4135291d11040000000000000000000000000000000000000000000000000000000000000000000000010f1a26313c4653606d7985929eaca7998c7f7366717d8a98a2aca095897c6f63564c4135291d11040000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000714212d3a46535f697783909da2988a7e7164584e4345515c67717e8b949fa89f92877d70695f585048443f3e3e3f42464f58616c7683909cacaab0ab998c7f7266594c3f3f4c5865727f8b98a4978b7e7164584b3e3125180b000000000714202d3a4753606d7a86929facada297897c706356493d31261a0f00000006131f2c3845515d6775828f9ca89f92867983909daa9d918477695f53473a2d1e13080000010d19242f3b4855616e7b8895a0acac9f93867a6e6154473b2f24180d0100000000000000000000000000000000000000000000000004101c27333d4855616b7783909da7aa9e9285796d60544a5764707d8a97a3b0a99c8f8276695c4f4340404040404040404040404040404040404040404040404040403d3c39332c231a1005000000000e1b2734414e5a6774818d9aa69a8d8073675a4d40343744505b657885929ea295897c6f625649515d67707d89939d9e938a7d70685d52453e31281e13080000000000000000000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875818e9ba6998c7f7366594c402e2c3945525d687985929fa49a887b6f6255483c2f22262f3c44505c666f7c87929f9f948b7e71695e52463e32291e1308000000000000000000000000000000000000000714202d3a46525e696e746d675f585b6874818e9b9e9184786b5e5145382b1e12050000000000020b17222d38424e58606d7984919e9f92867b6e625a50443a3024190c030000000000000000000000000000000000000b17222d38424a50535b5d555c60605d564c4a505354545b606c7883909d9e9184786a5f53473a2e21222d38424e58606d7984919e9f92867b6e625a50443a3024190c030000000000000000000000000000000000000003101c28343f4a54616e7b87939fabb0a69c9083776c60584e453c342a251e1a1312101a232834404a545e686f7c869299a4a29891847b85929ea8b2aa9f92867a6d6154473c32261b0f0000000000000006111c2a36424d57626e7b87929fa8b0a69f92877c6f695f585046413b36312d2c282327272723282c2d31373b42465159606b717e8a929da8b1a79f92857a6d61554b4035291d10040000000000000000000000000000000000000000000a151f2c3845515c6773808d9aa4aa9d9184776a75828e9baaaa9d9084776b6054443a3024190d010000000000000000000000000000000000000000000000000000000000000000000000000a151f2c3845515c6773808d9aa4aa9d9184776a75828e9baaaa9d9084776b6054443a3024190d010000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000005121e2b37424d5765727f8c98a39c9083766a605447404b55606c77828f97a2a39992857b6f6a625a554f4c4b4b4c4d5359606a707d8a949f9b9ea6a89b8f827568574d42404b546774818e9aa896897c6f6356493c3023160900000003101c28343f4a5464707d8a98a2aeab9f9285796d6053463a2d20130a00000004101d2935404b5565727e8b98a7a3988a7d87939fa99a8d807367574d42372b1e0c010000000814212d3a46535f697784919daaafa4998b7e7165554b4135291d1104000000000000000000000000000000000000000000000000000b16212c38444f5964707d8a95a0aca1978b7e72665b505764707d8a97a3b0a99c8f8276695c4f4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4a49443e362c22170b000000000d1a2734404d5a6773808d9aa69a8e8174675b4e4130394653606c7986929fa895887b6e6255484b55606b74818e96a19e91857a6d60594f433a2f24190d0400000000000000000000000000000000000000000000000000000000000000000000000000000d1a2633404d596673808c99a69a8e817467544b40342d3a4754606d7a8798a29f93867a6d6053473a2d201d28343f4a545f6a73808d95a09f92857b6e615a50443a3025190e040000000000000000000000000000000000000814212e3b4754616e7b80796f6a605b6874818e9b9e9184786b5e5145382b1e120500000000000006111c262f3c45515d67707d8a939e988f82766c61564c4135291e150a0000000000000000000000000000000000030f1c28333f4a545b6068696b676d6d685d52454446474a505b6573808c99a196887b6e6255483b2f221c262f3c45515d67707d8a939e988f82766c61564c4135291e150a00000000000000000000000000000000000000000c17232e3846535f6975828e99a3afab9f948b7f726a60574e463e36302a25201f1c1818232e39424c565f6a707d87939fa5a09691859297a1adaea2988d8074685e5246392a20150a00000000000000000e1a26313b47535f6974808d96a0abaea39991857b6e6a615a524c46423c3a38342e3434342e34383a3c42474d535b626b707d86929fa4aeaaa0958b7f72685e5243392f24180d0100000000000000000000000000000000000000000004101c2834404b55616e7b87939faca095887b6f7985929faca3988b7f7265594f4332281e13080000000000000000000000000000000000000000000000000000000000000000000000000004101c2834404b55616e7b87939faca095887b6f7985929faca3988b7f7265594f4332281e1308000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000020e1a26313c4754616d7a86929f9f94887c6f62584e4244505b656e7b859299a4a19791857c716c63615959585758575f616b707c869299938f939eab9e928578695f534745515c667683909da196877a6d6054473a2d21140700000006121f2c3844505c6674818e9baab4ab9b8e8175665c5044382c1f1206000000000c18242f3b4754616e7b8795a0aa9c8f838f99a4a297897c706356493d31261a0e0000000005121e2a36424d576673808d99a9b3ab9c8f8275675d5145392c2013070000000000000000000000000000000000000000000000000005101c28333e4653606c7883909da8a99e9184786c60555764707d8a97a3b0a99c8f8276695c5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a575550483e33281c10040000000c1926323f4c5965727f8c98a59c8f827669564c41363b4754616e7a8799a3a196877a6d605447434f59606d7a84919ea1978e81746b61554c4135291f160c01000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a89d908376665c514538303d495663707c8996aa9e918477675d5145392c1f17232e38424e58606d79849199a2988f82756c61564c41362a20160c0200000000000000000000000000000000000815212e3b4854616e7b87837c726c656874818e9b9e9184786b5e5145382b1e1205000000000000000a141d2935404b55616c75828f989f948a7e71685d52453d30261c11060000000000000000000000000000000006121f2b3844505b666c75767778797a6d60544b403a3a3f495364717e8b97a8978a7d7164574a3e3124141d2935404b55616c75828f989f948a7e71685d52453d30261c11060000000000000000000000000000000000000006111c2a36424d57626e7b87929fa8b0a69f92877c6f695f585046413b36312d2c2823272727303a444e58616b727f8c939ea7a0989298a1a9b1a79f92867a6e61564c41362a1e1105000000000000000009141f2b37424d57606d79849199a4afaba19791847c706c615e56534d494644404141414141404546494d53575f616d727d869298a2aeaca2989083786c60564c4131281d120700000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9a7998c7f737d8a98a2ac9f92867a6d6054473d3221160c0200000000000000000000000000000000000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9a7998c7f737d8a98a2ac9f92867a6d6054473d3221160c02000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000914202d3946525e6874818e9aa49b8f82756a60544a3f49535e69717e87939fa3a19791867e76706b686564646567696e747d8592989387828f9baaa197887b6e6255484653606d7985929f9e918478675d5145392c2013060000000713202d3a4653606d7985929eabaea3998a7e7164544a3f34281c1003000000000714202d3a46525e697783909daa9f948f949fab9f9285796d6053463a2d20130900000000020e1a26313c4956636f7c8997a1adac9f92867a6d6054473a2e23180c00000000000000000000000000000000000000000000000000000b161f2b3744505b65717e8a95a0aca0968a7d7064626264707d8a97a3b0a99c8f827669676767676767676767676767676767676767676767676767676767676764615a5044392d2014080000000a1723303d4a5663707d8996a89e918477685e5246393c4956626f7c8995ab9e918478685d52453d45515d67707d8a939e9e938a7d70675d51453d31281d1207000000000000000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8796a09f9286796d6053463c36414c5665727f8c98ab9b8e817568554b4035291d111c26303c45515c676f7c87939f9e948a7e71685e52463e32281e130800000000000000000000000000000000000815212e3b4854616e7b8790867f776e6974818e9b9e9184786b5e5145382b1e120500000000000000020b18242f3a43505a616e7b86929f9e92857a6d60594f42382e23170c030000000000000000000000000000000613202d394653606c7881838485868275665c5145403f414a5464717e8b97a4988b7e7165584b3e32251818242f3a43505a616e7b86929f9e92857a6d60594f42382e23170c03000000000000000000000000000000000000000e1a26313b47535f6974808d96a0abaea39991857b6e6a615a524c46423c3a38342e34343430353c464f59636d74818e959faaa29fa2aab3aaa0958c7f72685e52443a3025190d010000000000000000030e1a26313c45515d676f7d87939fa4aea9a19691867e756e68615e575653514a4e4e4d4e4e4b515356575f62696e767f879298a2aaafa49a92867c6f665b50443a301f160c01000000000000000000000000000000000000000000000007121d2b37424d5764717d8a97a1aa9d908377818e9baaa79b8e8174685d5245392c20130400000000000000000000000000000000000000000000000000000000000000000000000000000007121d2b37424d5764717d8a97a1aa9d908377818e9baaa79b8e8174685d5245392c20130400000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000005111d2935414c56626f7c87939f9f93877c6f665b5044414d57616c727f8b919fa3a198928b827d78757271717274777b81879297978e817d8998a3a9978b7e7164584b4a5463707d8a98a29c8f827569554c4135291d11040000000a1623303d495663707d8997a2adac9f92867a6d6054473a2e23170c000000000005111e2a36424d576673808c99a9a69f9c9fa6ab9b8e8275665c5044382c1f120600000000000913202d394653606c7985929eabaea3988a7d7164544a4034281c100400000000000000000000000000000000000000000000000000030f1b27333f4953606c7884919da8a89c9083766e6e6e6e707d8a97a3b0a99c8f8276737373737373737373737373737373737373737373737373737373737373706c6155493c3023160a0000000714212e3a4754616d7a8796a0a096877a6d61544740414d5765727f8c98ac9c8f827569564c4135414c55616b75818e97a19e91847a6d60594f43392f24180d030000000000000000000000000000000000000000000000000000000000000000000000000714202d3a46525e697784919ea398897d7063584e433f46525e6876828f9ca3998b7e7164584b3e2f24180c151e2834404b55606b74808d96a19e92857a6d615a50443a3024190d04000000000000000000000000000000000815212e3b4854616e7b8798928c827b7174818e9b9e9184786b5e5145382b1e1205000000000000000007131d28313e46525e69727f8c95a0978e81746b60544a3f34281f140900000000000000000000000000000006121f2b3844505b6677849091929285796d6058514a4c4b515b6673808d99a9978a7d7164574a3e312417131d28313e46525e69727f8c95a0978e81746b60544a3f34281f14090000000000000000000000000000000000000009141f2b37424d57606d79849199a4afaba19791847c706c615e56534d49464440414141414241464749505b606d79839098a2aeacaeb4aea2989083786d60564c4132291e13080000000000000000000009151f2935404b55606b727f8b929da4ada9a198928a817a746e696562605c545b5a5a5a5b545c606266696e747b828b9299a2aaaea39f93887e706a5f544a3f32291e0d04000000000000000000000000000000000000000000000000000e1a26313c4653606d7984919eaba095887b85929faba095897c6f63564c4135291d1104000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26313c4653606d7984919eaba095887b85929faba095897c6f63564c4135291d110400000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000010d1925303a47535f6a75828f9aa49a9083786c60564c4145505a626d737f8a9298a0a29f948f8984817f7e7e7f8083878e92999992857b7986929fa79a8e817467564c505c6674818e9aa7988c7f7265594c3f2f24190d01000006131f2b37434e586774808d9aa9b3a99c8f8276675d5145392c1c11060000000000020e1a25303c4955626f7c8897a1adaba9abafa4998b7e7164544a3f34281c1003000000000006121f2b3844505b6674818e9babb4aa9b8e8175665c5144382c1f120600000000000000000000000000000000000000000000000000000b17222d3844505b66717e8b96a0ab9f948a7d7b7b7b7b7b7f8b98a5b1ab9e9184808080808080808080808080808080808080808080808080808080808080807e7064574a3d3124170a0000000713202d3946525e687784919ea8978a7e71645b514b4c535f6976828f9ca49a8c7f7266594c3f2f3a434f59616d7a85919ea1968e81746b60554b4035291f150b01000000000000000000000000000000000000000000000000000000000000000000000005121e2a36424d576773808d9aa69b8e81746a5f554e4a5059616d7a86929f9f92867a6d6154473a2e2114070c18232e39434f59606d7984919ea1978e81756c61564c4135291f160c010000000000000000000000000000000815212e3b4854616e7b879298948f857e74818e9b9e9184786b5e5145382b1e12050000000000000000010c161f2a36424d57606d788390999f93887c6f665c50443b31251a0d040000000000000000000000000000030f1c28333f4a546774818e9a9f978b7e716a605c5459555d606c7884919da297897c6f6356493c3023160c161f2a36424d57606d788390999f93887c6f665c50443b31251a0d04000000000000000000000000000000000000030e1a26313c45515d676f7d87939fa4aea9a19691867e756e68615e575653514a4e4e4d4e4f4c5254535b60636b6f7a85929facb8bab2a89f92867c6f665c50443b3020170d0200000000000000000000030d18242f3a434f59626d74808d929ca3adaaa29f938e86807b76726f6d6669686767676869666d6f72777b81868f949fa3ababa39f918c7f726c61584e42382d20170d000000000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a4a79c8f828f97a2aa9d9084776b6054443a3024190d010000000000000000000000000000000000000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a4a79c8f828f97a2aa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000008131e2b37434e58626f7c87939f9f958b7f72685e53493f48515b636d737e8691969fa39f9c96918e8c8b8a8b8d9093999f9993877d707683909ca99d918477685d5253606d7985919ea095887b6e6155483b2e2215080000000815222e3b4754606a7884919eabb1a7988b7f7265554c4135291d0a000000000000000913202d394653606c7884919eabb8b6b9ac9f93867a6d6154473a2e23170c000000000000030f1c28333f4a5464717d8a99a3aeab9f9285796d6053463a2d22170b000000000000000000000000000000000000000000000000000006111b28333f4a54606d7884919ea8a69a8f8a88888888888b919ba7b3aca196918d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8074675a4e4134271b0e01000005111d2a36414c566673808c99a59d9083766d605c55565e656e7b87939f9f93877b6e6154483b2e313e46525d68717e8a939e9d93897d70675d51453d31271d12070000000000000000000000000000000000000000000000000000000000000000000000020e1a25303c4855626f7c88949f9f92867c6f676058545c606b73808d99a39c8f8275685e5246392d20130707121d27303d45515d67707d89939d9e938a7d70685d52453d31281d13070000000000000000000000000000000613202d394653606c787f86909597928a81818e9b9e9184786b5e5145382b1e1205000000000000000000040d1a25303b44505c666f7c87939f9a9083786d60574d42362a1f160c0100000000000000000000000000000b17222d3c4956626f7c89949f9f92857c716d66666666676d737f8c96a09f9285796d6053463a2d2013070d1a25303b44505c666f7c87939f9a9083786d60574d42362a1f160c0100000000000000000000000000000000000009151f2935404b55606b727f8b929da4ada9a198928a817a746e696562605c545b5a5a5b5c565d6163656c70757d839098a2aebab9aca0968a7e716a5f544a3f32291e0e0500000000000000000000000007131d28313d47515b606c77808c919ea1a9aea59e98928d87837f7c79777674747474747677797c7f83888e92999fa6aea8a199928b7f736d635a50463c2f261c0e05000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87939fac9e948f949ea9a3988b7f7265594f4332281e1308000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87939fac9e948f949ea9a3988b7f7265594f4332281e13080000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000020f1b26323c47535f6a74818e97a29f92857a6d655b50443f49515b636c717c848c92989ea1a19e9b989797989a9d9f9f9791877e716b73808c99a09f93867a6d61545b65717e8a97a19d918477695f53473a2d2114080000000916222f3c4955626f7c8896a1adaca095877b6e6154483b2f24190d0000000000000005121f2b3744505b6574818e9aaab4bfb6a99c908376685e5246392d1c1106000000000000000b17222d3a4754606d7a86929facada297897d706353493f33271b0f0300000000000000000000000000000000000000000000000000000b17222d3844505c66717e8b96a1aca19a969595959595989ba3adb8b2a8a19e9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8d8174675a4e4134271b0e010000010d1925303b4855626e7b88939e9f958b7f736d676767686d77828f99a49c908376695e53463a2d2935414c56616c75818e97a19e9184796d60594f43392f24180c0400000000000000000000000000000000000000000000000000000000000000000000000915212e3b47535f6a76828f9aa3999083796f6a6867666d717d87929f9f94897d7063564c41362a1e1105000b151e2935404b55606b74818e97a19e91857a6d60594f433a2f24180d04000000000000000000000000000006121f2b3844505b666c727c838c9299938e8e939e9e9184786b5e5145382b1e12050000000000000000000009141f28343f4a54606a74808d97a0958c7f72695e53463e31281d130700000000000000000000000000000615222e3b4754606a76828f98a29792857e7975737273757a8088939fa1978d8074665c5144382c1f120609141f28343f4a54606a74808d97a0958c7f72695e53463e31281d1307000000000000000000000000000000000000030d18242f3a434f59626d74808d929ca3adaaa29f938e86807b76726f6d6669686767676869686d7073787d82899095a0aab4b4b7aa9e9184796d605b51473e342a20160c030000000000000000000000010c161f2b353f44505b656c747f8a92979ea6acaaa29f9a93908c898684828181808181828486898c90959a9fa3ababa49f9691877e736d635b51473e342a1d140a000000000000000000000000000000000000000000000000000000000c17232e3846535e6975828f9ca8a69e9c9ea6ac9f92867a6d6054473d3221160c020000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17232e3846535e6975828f9ca8a69e9c9ea6ac9f92867a6d6054473d3221160c020000000000000000000000000000000000000000000000000000000104000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060503000000000000000000000000000000000000000a15202b37434e58616d7a85929fa2978f81776c605a50464049515a616a6f797f868c9196999c9d9e9f9f9e9c9a98928d857d716c63707d899994949a8a7d706355606c7883909da3998c807366574d42372b1e1206000005121e2a36424d576673808c99a8b2aa9d908377695e53463a2d1e130800000000000000030f1b27333f495364707d8a98a2aeacb2a8998c7f7266564c41362a1d0a00000000000000000613202c3945515d6776828f9ca9b3a99a8d8174655b5044372b1f1205000000000000000000000000000000000000000000000000000006111c28343f4a54606d7984919ea8aba5a3a1a1a1a1a1a5a7adacacacb2acaba6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69a8d8174675a4e4134271b0e010000000814212e3a47535f6975818e98a29f92877f79757474767a818f949f9e93897d7063574d42362a24303a44505a616d7a85929ea0968d80746b60554b40352920150a000000000000000000000000000000000000000000000000000000000000000000000006121f2b37434e58626f7c87939f9f9590837c77757475797e869299a2988f82766b6054443a3025190d0100030c18242f39434f59606d7a84919ea1978e81746b60554b40352921160a0000000000000000000000000000030f1c28333f4a545b606a6e787f8690959b9b9ea59e9184786b5e5145382b1e120500000000000000000000030b17232e38424e58606d7a84919e9f92867b6e615a50433a2f24180d010000000000000000000000000006131f2b37434e58616e7b869298a097928b8582807f8082858d939aa19892857a6d61544a4034281c1004030b17232e38424e58606d7a84919e9f92867b6e615a50433a2f24180d0100000000000000000000000000000000000007131d28313d47515b606c77808c919ea1a9aea59e98928d87837f7c797776747474747576777a7d8084898e939da0a7afaaa8abaca0968e81746d62594f463c32281e150b000000000000000000000000040d192327333f49535b606d737d858f949da0a7acaca49f9c989892918f8e8d8d8d8e8f919298999d9fa7acaca69f99938d847d716c635b51493f352c22180b020000000000000000000000000000000000000000000000000000000006111c2a36424d5763707d8a96a1acaaa8aab0a79b8e8174685d5245392c2013040000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c2a36424d5763707d8a96a1acaaa8aab0a79b8e8174685d5245392c201304000000000000000000000000000000000000000000000000000004090e11131314202d3a4753606d7a8693a0acac9f9286796c5f5346392c201312110f0c070100000000000000000000000000000000040f1b26323c46525e68717e8b949e9e938c80736c61584f474048505860676d737b8084898c8f9192929291908d8a85807a706b61606d798787878787878073665d67707d8a95a09f92867b6e6154483c31261a0e0200000714212d3a46535f697784909d9f9fa9998c807366574d42362a1e120500000000000000000b17222d3a4753606d7a86929f9f9f9fa196887b6f6255483c3025190d000000000000000004111d2935414b5565727f8b98a79f9f9e9184786c605346392d2013060000000000000000000000000000000000000000000000000000000b17232e3844515c66727e8b96a19f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8d8174675a4e4134271b0e0100000006121e2b37424d57616e7b859298a299928c8582818182868f939e9f958e81756b6054453b31251e28323e46525e68717e8a949e9f93887d6f675d51453d32271b0f0300000000000000000000000000000000000000000000000000000000000000000000030f1b26323c4754606a74808d949e9f95908983818082848b9298a29992857b6e61594f4432291e130800000007121d28313d45525d68707d8a939e9d93897d70675d51453d32271b0f0300000000000000000000000000000b17222d38424a50585f666d727c838c9299a0a79e9184786b5e5145382b1e1205000000000000000000000006111c26303d45515d67717e8a949e988f82756c61554b4035291d110400000000000000000000000000030f1b27323d46535f69707d8691969e9f97928e8c8c8d8f92989f9f9691867d6f685e5242392e23180c000006111c26303d45515d67717e8a949e988f82756c61554b4035291d1104000000000000000000000000000000000000010c161f2b353f44505b656c747f8a92979ea6acaaa29f9a93908c898684828181808182838487898c91969b9ea5acaba59e9b9ea1a89d938c7f726b61584e443a30271c1207000000000000000000000000071017222d384149505b636b707b828990959c9fa4acaca9aaa39f9d9c9b9a9a9a9b9c9d9fa3aaaaababa39f9b948f878079706b625a514940372e231a10060000000000000000000000000000000000000000000000000000000000000e1a25313b4653606c7884919e9f9f9f9f9fa095897c6f63564c4135291d110400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a25313b4653606c7884919e9f9f9f9f9fa095897c6f63564c4135291d110400000000000000000000000000000000000000000000000000080f151a1d1f2020202d3a4753606d7a86939f9f9f9f9286796c5f5346392c20201f1e1c18130c05000000000000000000000000000000000a15202a36414c56626d76828f97a19f93887e716a60594f473f464e555c60696e73797c7f82848586858583817d79736d6860595d67757a7a7a7a7a7a796d60606d7984919ea49a8e8174695e53463a2a1f15090000000815222e3b4855616e7b88959393939396897c6f6256493c31251a0e02000000000000000006131f2c3945515d6775828f93939393939184786a5f53473a2e1e13080000000000000000010d18242f3b4854616e7b87959393939396897c6f6256493c2f23160900000000000000000000000000000000000000000000000000000006111c2834404a54606d7984919393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393938d8174675a4e4134271b0e01000000020e1a26313c46525e69707d8692989f9f98928f8d8d8f92999e9f9590837a6d61594f4433291f16202a36414c56616c75828f97a29a9184796d60584e43372b1f130600000000000000000000000000000000000000000000000000000000000000000000000a15202b37434e58606d78828e939da09d95908e8d8e91969f9f9792877d70695f53473d3320170d02000000010c161f2935414c56616c75818e97a19e9184796d60594f44382c1f1307000000000000000000000000000006111c262f383f444e545c606a6f788087909593939184786b5e5145382b1e12050000000000000000000000000a141e2935414c55616c75828f9893948a7d70675d5145392c20130600000000000000000000000000000a15202a36424d57606b707c848c9196999c9b9999999b9d9a97928d847d6f6b60564c4130271c12070000000a141e2935414c55616c75828f9893948a7d70675d5145392c20130600000000000000000000000000000000000000040d192327333f49535b606d737d858f949da0a7acaca49f9c989892918f8e8d8d8e8f8f919696999ea1a8aaaca69f9c938e9196a1a59f93877d706a5f564c42392e2318110800000000000000000000000006111b262f383f44515961696e757d83898f939a9c9fa2aaa7a8aaa9a7a7a7a7a7a9a9a8a6a9a29e9b99928e88827c746d676059504840372e251c11080000000000000000000000000000000000000000000000000000000000000009141f2b3844505b66737f8c999393939393939084776b6054443a3024190d01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f2b3844505b66737f8c999393939393939084776b6054443a3024190d0100000000000000000000000000000000000000000000000009121a20262a2c2d2d2d2d3a4753606d7a8693939393939286796c5f5346392d2d2d2c2b28241e170f07000000000000000000000000000000040d1925303a44505a616e7b859299a39a92867c6f6b6159504641434b51565e61666d6f737677787979787674706d67615d564f555d686d6d6d6d6d6d6d67616b74808d96a19f93877c6f62574d42362a180e030000000c1926323f4c5965727f8686868686868684786c605346392d20130900000000000000000004101d2935404b5565727f86868686868686807467584e43372b1f12060000000000000000000714212d3a46535e697783868686868686868073665a4d4033271a0d000000000000000000000000000000000000000000000000000000000c18232e3945515c67727f86868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868074675a4e4134271b0e01000000000915202a36424d56616b707d868e92999b9d9b9a9a9c9d9a97928b837a6d685d52473d3321170e1925303a44505a616e7b85929393968d80736a6054473b2e2215080000000000000000000000000000000000000000000000000000000000000000000000040f1b27323d44515c666d79818a9195999c9d9b9a9b9e9c99928e857d706b61574d42352b210e050000000000040d19242f3a44505a616d7a85929393968d80746b6054483b2f2215090000000000000000000000000000000a141d262d333c424a50585f666d737c838686868684786b5e5145382b1e1205000000000000000000000000020c19242f3a43505a616e7b8686868686847a6d6053473a2d2014070000000000000000000000000000040e1a26313b454f59606a6f797f848a8d8f9192929291908d8a8580796f6b60594f443a301e150b00000000020c19242f3a43505a616e7b8686868686847a6d6053473a2d2014070000000000000000000000000000000000000000071017222d384149505b636b707b828990959c9fa4acaca9aaa39f9d9c9b9a9a9a9b9c9ea0a8a6abacaba39f9b94908981849198a2a49992867c6e685e544a40342823190b020000000000000000000000000a141d262d3340474f575e616b70777d82878b8f9298989a9b9d9e9e9f9f9f9e9d9d9b999797928e8a86817c766f6a605d554f473e362e251c130a0000000000000000000000000000000000000000000000000000000000000000030f1c28333f4a54616e7a8786868686868686867f7265594f4332281e1308000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1c28333f4a54616e7a8786868686868686867f7265594f4332281e130800000000000000000000000000000000000000000000000008121b242b323639393939393a4753606d798686868686868687796c5f5346393939393837342f2921190f0500000000000000000000000000000008131e29323f46525e69707d87929fa29892857d706b625a524c4440454d52545c606366696a6b6c6c6b696764605c55524c444c565d61616161616160606a707d88939fa2978e81756a5f53453b31251a06000000000b1825313e4a57626d7279797979797979786c655b5044372b1f1205000000000000000000000c18242f394a56626d7279797979797979746e6458463c31261b0f0300000000000000000005121e2a36424d5767717779797979797979736e63584b3f3226190c0000000000000000000000000000000000000000000000000000000007121c2834404b55626d727979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746e64584c3f33261a0d0000000000030e1925303b444f59616b707a81868b8e9091929291908d8a857f786d685e564c41352b210f08131e29323e46525e69717e8686868686877c6f6256493c2f2316090000000000000000000000000000000000000000000000000000000000000000000000000a16202834404a545c676d747d84898d8f91929292918f8c87817b706b61594f453b3123190f0000000000000008131e28323e46525e68717e8686868686887c6f6356493c30231609000000000000000000000000000000020b141c222830383f444e545c606a6f77797979797872685c5043372a1d11040000000000000000000000000008131e28313e46535f696e7979797979786d675d5145392c20130600000000000000000000000000000009141f29333d474f5860676d72787d8082848586858483807e79736d6760594f473d32281e0c03000000000008131e28313e46535f696e7979797979786d675d5145392c20130600000000000000000000000000000000000000000006111b262f383f44515961696e757d83898f939a9c9fa2aaa7a8aaa9a7a7a7a7a8a9aaa8a6aaa29f9c99928f89837d757c86929aa4a29891847a6d665c51443f352b1d140a000000000000000000000000020b141b2227353e454d525960636b70757b7e8285888b8d8f9091929292929191908e8c8a8885817e7a746f6a626058514b433d352d241c130a010000000000000000000000000000000000000000000000000000000000000000000b17222d3846525e686e797979797979797979726d6256473d32261e140a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222d3846525e686e797979797979797979726d6256473d3220160c020000000000000000000000000000000000000000000000040f1a242d363d4245464646464545515c67767979797979797979756a5e523e454646464544403a332b21170c010000000000000000000000000000020d17202a36424d56606b727f8b929ca29792867d716c615e5650474242464a505356595c5e5f5f5f5e5d5a5753514b46413a444c5254545454545960696f7c86929aa49f92857b6e61584e4333291f1409000000000916222e3a46515b62656c6c6c6c6c6c6c6b605b53493f33271b0f030000000000000000000007121d2e3a45515b62656c6c6c6c6c6c6c67645c5247342a20150a00000000000000000000020e1a25313b45555f676a6c6c6c6c6c6c6c66635c52473b2f23170a00000000000000000000000000000000000000000000000000000000000c18232e3943515b62656c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c67645c52473c3024170b00000000000009141f29323e474f5960686e747a7e81838485858483817d79726d665e564c443a3023190f020d17202a36424d57626c717979797979796f6a6054473b2e221508000000000000000000000000000000000000000000000000000000000000000000000000040c18232e39424b555c606c70777c80838485868584827f7b756e6961594f473e332a1f110700000000000000010c16202a36414c56616c717979797979796f6b6054483b2f22150900000000000000000000000000000000020a11171e262e343c424a51585f626a6c6c6c6c6b6860564b3f33271b0f0200000000000000000000000000010c161f2a36424d575f616c6c6c6c6c6b605d554b4035291d1104000000000000000000000000000000030d17212b353d464e555c60666d70737677787978787674716d67605d554f473d352b20160c000000000000010c161f2a36424d575f616c6c6c6c6c6b605d554b4035291d1104000000000000000000000000000000000000000000000a141d262d3340474f575e616b70777d82878b8f9298989a9b9d9e9e9f9f9f9f9e9d9c9a9898928f8b86827d76706b707e88939fa5a0968f82786d605b51473d2f261b1106000000000000000000000000020a1117232c333b42464f54596063696e7276797c7e808283848585868585848382807d7b7975716d68625f58544e45403a312b231b120a010000000000000000000000000000000000000000000000000000000000000000000006111c2a36414d565e616c6c6c6c6c6c6c6c6c65625b51443f3830261c110600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c2a36414d565e616c6c6c6c6c6c6c6c6c65625b5146342b210e040000000000000000000000000000000000000000000000000915202b363f484e5253535353514a4b555c6c6c6c6c6c6c6c6c6c6a6359464b5253535352504c453d33291e1307000000000000000000000000000000050e1925303b444f59626d73808d929da29892877e756d68615a534e47433f4446494c4f5152535252504e4a4745403935323a414647474d535b626b707b859198a29e948b7e71685e52463c3121170d030000000006121e29353f49515759606060606060605e53504941382d22170b000000000000000000000001111d29343f48515658606060606060605a58524a413622180e04000000000000000000000009141f2933434d555b5d606060606060605a58524a40352a1f1307000000000000000000000000000000000000000000000000000000000007121d27303f4951565860606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605a58524a41362b1f1408000000000000020d17202c353e474f565e61686e717577787979787674706d67605c544c443a32281e110700050e1a25303b45505a62656c6c6c6c6c6c6260584e43372b1f13060000000000000000000000000000000000000000000000000000000000000000000000000007121c273039434b515a61646b6f7376787979797775726e69615e574f473e352c21180e000000000000000000040d1925303a44505a61646c6c6c6c6c6c6360594f44382c1f1307000000000000000000000000000000000000060c141c2328303940444e54555d606060605e5c564e443a2f23170b000000000000000000000000000000040d1a26313b454d53555f606060605e53514b433a2f24180d0100000000000000000000000000000000060f19232b343d434b51545c606366696b6c6c6c6b6a6764605d55514b433d342b23190e0400000000000000040d1a26313b454d53555f606060605e53514b433a2f24180d0100000000000000000000000000000000000000000000020b141b2227353e454d525960636b70757b7e8285888b8d8f9091929293929291908f8d8b8885827e7a75706b63616c737f8c939ea79f948d80746d62594f41382d22170b000000000000000000000000000006111a202930363d44484f54565e6165666d6f7174757778787979787877767573716f6d6664605d56534e47433d352f281f191109000000000000000000000000000000000000000000000000000000000000000000000000000e1925303b444d52545f606060606060606060605f5e504a42382e23170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e38424a505e5f606060606060606060585651493f3422190f000000000000000000000000000000000000000000000000000e1a26323d4851595e606060605e575550515f606060606060605f5e595053585f6060605f5c574f453a2f24180c0000000000000000000000000000000009141f29323d47515b636e74808d929fa299928b817a706c625f57534e4745413c4043444546464543413d3a383435393a3d43474c52575f626d727d859197a1a0958f82756c62564d41342a200f050000000000010d18232d373f464a4c535353535353535246443f382f261b11060000000000000000000000010c18232d363f454a4b535353535353534e4c4741382f241006000000000000000000000000030d1721323b434a4f51535353535353534d4b4740382e24190e020000000000000000000000000000000000000000000000000000000000000b151e2d373f464a4c53535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534e4c4741382f241a0e0300000000000000050e1a232c353d444c52565e6164686a6b6c6c6b6a6763605d55504a423a322820160c00000009141f29333f4850565860606060605f56544e463d32271b0f0300000000000000000000000000000000000000000000000000000000000000000000000000000b151e2730394045505559606366696b6c6c6c6b6965615e57524d453e352c231a0f060000000000000000000008131e29323e4850555760606060606056544f473d32271b0f0300000000000000000000000000000000000000020a11171e272e343c434749515353535351504b443c32281d12070000000000000000000000000000000009141f29333b4246485253535353514745403a31281d1307000000000000000000000000000000000000081119222b303940454a5053575a5c5e5f5f5f5e5d5a5753514b45413a312b2219110700000000000000000009141f29333b4246485253535353514745403a31281d1307000000000000000000000000000000000000000000000000020a1117232c333b42464f54596063696e7276797c7e808283848585868685848382807e7c7975726e686360595a636d75818e95999999928b7f726b6053493f33271b0f030000000000000000000000000000080e171f252a33383d44484d535f605c60626567686a6b6b6c6c6c6b6a6a68666462605c605f534d47433c383229241d160d07000000000000000000000000000000000000000000000000000000000000000000000000000008141f29323b41464753534d545b60666c6c6c6c6c6a5c544a3f34281c10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a545c6a6c6c6c6c6c66605b544d4c4a463f372d23130c04000000000000000000000000000000000000000000000000111d2a36424e59636b6c6c6c6c6b64615a534d53535353535353534d535b60656c6c6c6c6b6861574c4034281c0f00000000000000000000000000000000020d17202b353f49525c646e74808c9399a29f938e857d756e6a625f5854524c49474540413f3e3e3d3d3e3f3f404045474a4e53565e61696e767e879297a1a1969083796d605a50443b3022180e0000000000000007111b252d353a3e3f46464646464646453937332d261d140a0000000000000000000000000006111b242d343a3d3f4646464646464641403c362f261d130000000000000000000000000000050f202932393f434446464646464646403f3b352e261c120800000000000000000000000000000000000000000000000000000000000000030c1b252d343a3e3f4646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646413f3c362f261d130800000000000000000008111a232c323b41464c5254585b5d5e5f5f5e5d5a5753514b443f38302820160e04000000020d17202d363f454a4b5353535353534947433d342b20150a000000000000000000000000000000000000000000000000000000000000000000000000000000030c151e272e343e44494f54565a5c5e5f5f5f5e5c5954524d46423b332c231a11080000000000000000000000020d17202c363e45494b5353535353534948443d352b21160a00000000000000000000000000000000000000000000060c151c232832373b3c444646464645433f3a322a20160c0100000000000000000000000000000000030d17212931363a3b4646464646453a39352f281f160c01000000000000000000000000000000000000000810191e272e34383f44464a4d505152535251504d4a47454039352f281f19100700000000000000000000030d17212931363a3b4646464646453a39352f281f160c01000000000000000000000000000000000000000000000000000006111a202930363d44484f54565e6165666d6f7174757778787979797878777573716f6d6665615e56544f515b606d79838c8c8c8c8c8c867d70655b5044372b1f1205000000000000000000000000000000050d141a21272c36424d575e6c6c6c6c6c6c6c6a665f5f5f5f5f5e5e66696c6c6c6c6c6c6c5e574d42362b272018130c04000000000000000000000000000000000000000000000000000000000000000000000000000001070e17202930363b424651575f666c72797979797975665c5044382b1f12060000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2b3844505c66757979797979726c665f575146423b3229251e160e070100000000000000000000000000000000000000000000131f2c3945525e6b757979797978706c615f57514b434646424b51575f656c71787979797873685c5044372b1e110000000000000000000000000000000000050e19232d37404a525c646e737f8792979f9e97928a827b756f6a65605d565653514b4d4c4b4b4a4a4b4b4c4d4b515357585f62686d737b828b9299a19f9791847a6e675d51483e32291f100600000000000000000a131b23292e313239393939393939382d2b27221b140b02000000000000000000000000000009121b23292e3132393939393939393433302b241d140b0100000000000000000000000000000e1720272e3336373939393939393933322f2a241c140a00000000000000000000000000000000000000000000000000000000000000000009131b23292e313239393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393433302b241d140b010000000000000000000008111a202930363b4146474b4e5051525251504e4a47454039342e261e160e040000000000050e1b242d343a3d3e4646464646463c3b37322b22190f0400000000000000000000000000000000000000000000000000000000000000000000000000000000030c151d232833393d4348494d5051525352514f4c4846423b363029211a110800000000000000000000000000050e1b242c34393d3e4646464646463c3b38322b23190f040000000000000000000000000000000000000000000000030b121820262b2e2f37393939393837332f2820180f05000000000000000000000000000000000000060f171f262a2d2e3939393939382d2c29241d160d04000000000000000000000000000000000000000000070c151d23282e34383a3d4043444546454543413e3a38352f29241d160d07000000000000000000000000060f171f262a2d2e3939393939382d2c29241d160d0400000000000000000000000000000000000000000000000000000000080e171f252a33383d44484d5254545c60626567686a6b6b6c6c6c6c6b6a69676562605c5454524c484445515c676e7b808080808080807f786c605346392d2013060000000000000000000000000000000002090e16212d3a46535e69767979797979797771665b5253525a66707679797979797976695e53463a2d21160d07010000000000000000000000000000000000000000000000000000000000000000000000000000040c1318202830353e444d525b62696e787f8686868687796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7987868686867f786e69625b524d443e3530282018130c0400000000000000000000000000000000000000000013202d394653606c7987868686847d756e69605c554f46454f545c60696e777e8586868685786b5f5245382c1f1200000000000000000000000000000000000007111b252e38414a525c646d727d8590949fa19e938f87817c76716d686663605d555a59585757575858595a555d6063676a6f747a80868f949fa39e9590857c6e685e554c41362d20170d000000000000000000010a11181e2225262d2d2d2d2d2d2d2b201f1b17110a02000000000000000000000000000000000911181d2224252d2d2d2d2d2d2d2726241f1a130b02000000000000000000000000000000050e161c2227292a2d2d2d2d2d2d2d2726231f19120a02000000000000000000000000000000000000000000000000000000000000000000010911181e2225252d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2726241f1a130b02000000000000000000000000080e171e252a3036393b3e42444546464543413d3a39352f28231c150c040000000000000009121b22292e31323939393939392f2e2b2720191007000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b121822282d32383b3c40434546464644423f3b3a36302a251f170f0800000000000000000000000000000009121b22282d3031393939393939302f2c27211911070000000000000000000000000000000000000000000000000000070c151b1f22222a2d2d2d2d2b2a27231d160f060000000000000000000000000000000000000000060d141a1e21222c2d2d2d2d2b20201d18130c040000000000000000000000000000000000000000000000030b12181c23282b2d30333638393939383734312d2c29241d18130c040000000000000000000000000000060d141a1e21222c2d2d2d2d2b20201d18130c04000000000000000000000000000000000000000000000000000000000000050d141a21272c33383b4246474a505355585a5c5d5e5f5f605f5f5e5d5c5a585553504a4746413b38404b555e696e73737373737373726c655b5044372b1f12050000000000000000000000000000000000000815212e3b4854616e7b86868686868683776a5d50464f5c6976828686868686867b6e6154483b2e211508000000000000000000000000000000000000000000000000000000000000000000000000000000070d161d2429323a414650565e616d727b828c929992877e71665c5044382b1f12060000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2b3844505c66717e879399928c827b726d615e565046413a3229241d160d0700000000000000000000000000000000000000000b1825313e4b5864717e889396918a827b736d67615953525960666d737b828b929792877e7064574a3d3124170a0000000000000000000000000000000000000009131c262f38414a525b626b707b828c92989e9e99928e88837e7a76726f6d67696766656464646465666769676d7074777c81868d92999fa19e938e837b6e6a5f564d433a2f241b0e050000000000000000000000070d12161819202020202020201f13120f0b0600000000000000000000000000000000000000060c11151718202020202020201b1a17140e08010000000000000000000000000000000000040b11161a1d1e202020202020201a1917130e0800000000000000000000000000000000000000000000000000000000000000000000000000070d1216181920202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b1a17140e08010000000000000000000000000000050d14191e252a2d2e313537383939383734302d2c29241d17110a030000000000000000000911181d2124252d2d2d2d2d2c23221f1b150f07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c171c21272c2f303336383939393836322e2d2a251f1a140d0500000000000000000000000000000000000910171d2124242d2d2d2d2d2d23221f1b160f0700000000000000000000000000000000000000000000000000000000040a0f1315161e202020201e1d1b17120c050000000000000000000000000000000000000000000003090e1214151f202020201e1413110d07010000000000000000000000000000000000000000000000000000070c11171c1f202427292b2c2c2c2b2a2724201f1d18120d07010000000000000000000000000000000003090e1214151f202020201e1413110d0701000000000000000000000000000000000000000000000000000000000000000002090e161c21272c30363a3b3f4446494b4d4f5051525253535251504f4d4b4946443f3b3936302f39434d565e616666666666666665605b53493f33271b0f030000000000000000000000000000000000000815212e3b4854616e7b87939393939083776a5d50444f5c6976828f93939393877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000000000000000000000000000710191f282f353e444c525a61696e767f8690949a93877e716c61544a3f34281c10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54616c717e87939a9490867f766e69615a524c443e352f281f191007000000000000000000000000000000000000000a1724303d4956626c717f8b919e948f868079706b615f5d606b6f797f868f949f93887e716c6155493c3023160a00000000000000000000000000000000000000010a141d262f384049515961696e787f868f949c9f9f9b94908b86837f7c7a77757472717170707172727376787a7d8084888e92989fa39f97928b81796e695f574e443b31281e1209000000000000000000000000000106090b0c1313131313131312060503000000000000000000000000000000000000000000000105090b0c131313131313130e0d0b0803000000000000000000000000000000000000000000060b0e1011131313131313130d0c0a07020000000000000000000000000000000000000000000000000000000000000000000000000000000106090b0c13131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130e0d0b0803000000000000000000000000000000000002080e14191e202125282a2b2c2c2b2a2724201f1d18120c06000000000000000000000000060c111517182020202020201615130f0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b10161b1f222327292b2c2c2c2b292621201e1a140e090300000000000000000000000000000000000000060c111517182020202020201615130f0a040000000000000000000000000000000000000000000000000000000000000003060809111313131312110f0b0701000000000000000000000000000000000000000000000000000205070813131313131207060401000000000000000000000000000000000000000000000000000000000000060b101213171a1d1e1f201f1e1d1a171413100c070100000000000000000000000000000000000000000205070813131313131207060401000000000000000000000000000000000000000000000000000000000000000000000000050b10161c1f252a2d2e34383a3c3e414244454546464645454442403e3c3a38342e2d2a2527313b444d5254595959595959595953504941382d22170b000000000000000000000000000000000000000815212e3b4854616e7b87949f9f9d9083776a5d50444f5c6976828f9c9f9f94877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000000000000000000000000040f19222b313a41454f565e616c717b828b92989a93887e716c615a5042382e23170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e3842505a616c717e88939a98928b827b716c615e564f45413a312b22190f040000000000000000000000000000000000000815212d3945505a626d727f8b919c98928c847d756e69686d747c838c92989c918b7f726c625a5044392d2014080000000000000000000000000000000000000000020b141d262e373f474f575e666d727b828990949b9f9f9c9992908c89868482807f7e7e7d7d7e7e7f808284868a8d91969b9fa39f99938d857e756d675e574e453c32291f160c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e111414181b1d1e1f1f1e1d1b171413100c070100000000000000000000000000000105090b0b13131313131309080603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f1315161a1d1e1f201f1e1c191514120e0903000000000000000000000000000000000000000000000005080a0b1313131313130909070300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306070a0d101112131212100e0b070604000000000000000000000000000000000000000000000000000000060606060605000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b1014191e2023282c2d2f3234353738383939393938373634322f2d2c2823201e191f29323b4246474d4d4d4d4d4d4d4c46443f382f261b1106000000000000000000000000000000000000000815212e3b4854616e7b8794a1aa9d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e211508000000000000000000000000000000000000000000000000000000000000000000000000000a16212b343d434b515961686d757e858f949f9f93887f716c625a50483e30261c110600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c26303e48505a626c717f88939f9f948f857e756d686159514b433d342b21160a00000000000000000000000000000000000005111d29343e48505a626d727f8c929c9f96918a827b73717a818891959f9d928c7f736d625a50483e33281c1004000000000000000000000000000000000000000000020b141c252d353e454d545c60696e757c83898f93999da09f9c999992918f8d8c8b8a8a8a8b8b8c8d8f91939a9a9ea0a19e99928e87817a716c605d554d453c332a20170d040000000000000000000000000000050a0d0f10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100f0d0a0500000000000000000000000002080d101213131313131313090806030000000000000000000000000000000000000000000000010407071213131313131313131313120f0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507080b0f1112131312100e0a07060400000000000000000000000000000000000000000000060606060606000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030709090d1012131313110f0c08070502000000000000000000000000000000000000000000000000000000000006060606060600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040607090b0d0f1111121313121111100d0b08060603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090e1114171c1f20222527292a2b2c2c2d2c2c2b2a29272522201f1c1714110d17202930363a3b404040404040403f3937332d261d140a00000000000000000000000000000000000000000815212e3b4854616e7b8794a1a99d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e211508000000000000000000000000000000000000000000000000000000000000000000000000030f1b27323d464e555d606b707a818a92979f9b918b7f726d625a50483e362c1e140a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141e2c363e48505a626d727f8b919b9e97928a817a706b605d554e463d32271b0f030000000000000000000000000000000000000c17222d363f48515b636d737f8c929ca09e948f867f7d848d939aa09d938d80736d635b51483e362c22170b0000000000000000000000000000000000000000000000020a131b232c333b424a50575f616b6f767c82878c9196989c9fa29f9d9c9a99989797979798999a9c9e9fa39f9c9997918c86817c746d68625a514b433b332a21180e0500000000000000000000000000030a1016191c1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1c1916100a03000000000000000000060d14191c1f1f2020202020201515120f0a030000000000000000000000000000000000000001080d1113141f202020202020202020201e1b161009010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104070c10121316181a1c1d1e1f1f201f1e1d1c1a181513120f0b060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030607090b0d0f1111121313121211100f0d0a08070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205060c10121316181a1c1d1e1f1f20201f1e1d1c1a18161312100c0605050e171f252a2d2e33333333333333322d2b27221b140b0200000000000000000000000000000000000000000815212e3b4854616e7b87949c9c9c9083776a5d50444f5c6976828f9c9c9c94877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000000000000000000000007131f2c38434e5860676d747d858e939fa29b918b7f726d625a50483f362d241a0c020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c1a242d363f48505a626d727f8b919ba29f938e857d746d6760584e43382c1f130700000000000000000000000000000000000006101b242d363f49515b636d73808d929da49e98928c8a91969fa49e938e81746e645b51493f362d241a10050000000000000000000000000000000000000000000000000109111a212930383f444d535960636b6f757b7f84888c8f929797999b9c9d9e9f9f9f9f9e9d9d9b99979992908c8884807a746f6a615d5650454039312920180f0600000000000000000000000000040d151c21262929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292926211c150d04000000000000000810181f25292b2c2d2d2d2d2d2d22211f1b150e060000000000000000000000000000000000040c13191d20212b2d2d2d2d2d2d2d2d2d2d2b27211b130a0100000000000000000000000000000000000000000000000000000000000000030506090c0e1011121313131211100e0b090605030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030506090c0e1011121313131211100e0b090605030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010507070b0d0f111213131312110f0d0b07070501000000000000000000020608080c0f1112131312110f0c080705020000000000000000000000000000000000000000000000000000000001080d1113181c1f20222527292a2b2c2c2c2c2b2a29272422201f1c1712100c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104060b10121315171a1c1d1e1f1f201f1f1e1d1b19171514120e0906030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030607090b0e0f1112121313131212110f0d0b0907060300000000050d14191e20212626262626262626201f1b17110a020000000000000000000000000000000000000000000815212e3b4854616e7b878f8f8f8f8f83776a5d50444f5c6976828f8f8f8f8f877b6e6154483b2e2115080000000000000000000000000000000000000000000000000000000000000000000000000915222e3b4854606a6f79818a91979ea39c918c7f726d625b51483f362d241b12080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242d363f48515b626d727f8c919ca39e97918a81796f6a6054483b2e2215090000000000000000000000000000000000000009121b242d373f49525b636e74808d929da5a39f99979ea1a69e948e81786c605c524940372d241b1108000000000000000000000000000000000000000000000000000000080f171e262e343b42464f54596063696e73777b7f8285888a8c8e8f9192929292929191908f8d8b8886837f7c78736e68625f58524c443f352f271f170e0600000000000000000000000000030d161f262d3235363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363635322d261f160d03000000000006101a222a303538393939393939392f2e2b2620181006000000000000000000000000000000040d161e24292c2d383939393939393939393937332c251c13090000000000000000000000000000000000000000000000000000000003060b0f121315181b1d1e1f2020201f1e1c1a181513120f0b0603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060b0f121315181b1d1e1f2020201f1e1c1a181513120f0b060300000000000000000000000000000000000000000000000000000000000000000000000000000000000004080d111314171a1c1e1f1f20201f1e1c1a171413110d08040100000000030a0f121415191c1e1f20201f1e1c191514120e090300000000000000000000000000000000000000000000000003090e13191d2023282c2d2f31333637383839393838373634312f2d2b28221f1c17110d0802000000000000000000000000000000000000000000000000000000000000000000000000000001070d1113171c1f20222426292a2b2b2c2c2c2b2b2a28262422211e1a1312100c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010204050506060606050403010000000000000000000002090e1114141a1a1a1a1a1a1a1913120f0b0600000000000000000000000000000000000000000000000814212e3b4754616e7a8283838383828074675a4e414d5a6673808283838383827a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000000000000000916232f3c4956626f7c848e9393939393918c7f726d625b51493f362d241b120900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d363f49515b626d727f8c9193939393938e847c6f6256493c2f231609000000000000000000000000000000000000000009121b252d374049525c646e74808d939da59f9f9f9fa79f948f82786d665b504a40372e251b12090000000000000000000000000000000000000000000000000000000000050c141c232831363d44484f54575e61666a6e7276797b7e80818384858586868584848382807e7c7a76726f6c65615e56534e46413a3229241d150d0500000000000000000000000000000a151f2831383e424343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343423e3831281f150a00000000020d18222c343b4144464646464646463c3a37312a22180e0300000000000000000000000000010c1620282f35393a4546464646464646464646433e372e251b100500000000000000000000000000000000000000000000000000060b1012171b1f20222527292b2c2c2d2c2c2b29272522201f1b17120f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b1012171b1f20222527292b2c2c2d2c2c2b29272522201f1b17120f0b060000000000000000000000000000000000000000000000000000000000000000000000000001070c1013191d20212427292a2c2c2d2c2c2b29272421201d1913100d0701060b0f151a1f212226292b2c2c2c2c2a282621211e1a140d05000000000000000000000000000000000000000000030a0f151a1e24292c2e34383a3c3e4042444445464645444443403e3b3938332d2c28231c19130d08010000000000000000000000000000000000000000000000000000000000000000000003090e13181d2023282b2d2f3133353737383939393837373533312e2d2a26201f1c17110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507080d0d0d0d0d0d0d0c060503000000000000000000000000000000000000000000000000000714202d3946525e686e767676767676746e64584c404b58636e737676767676766e685e5246392d2014070000000000000000000000000000000000000000000000000000000000000000000000010e1b2734414e5a67748186868686868686867f736d635b51493f372d241b1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d373f49515b636d737f86868686868686868174675a4e4134271b0e01000000000000000000000000000000000000000009131c252e37404a525c606c77818e93939393939393959082796d665c544a3f382e251c130900000000000000000000000000000000000000000000000000000000000000020a11171f262a32383d44484d5354575f6265666c6f717375767778797979787877767573716f6d676662605b53524c47433c3530282018120b03000000000000000000000000000005101c26313a42494e50505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050504e49423a31261c100500000008141f2a343e464d51525353535353534847433c342a20150a0000000000000000000000000008131e28323a41454752535353535353535353534f4940372c21160a0000000000000000000000000000000000000000000002080d11171c1f22272b2d2f323436373939393938373634322f2d2b27221f1c17110d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d11171c1f22272b2d2f323436373939393938373634322f2d2b27221f1c17110d0802000000000000000000000000000000000000000000000000000000000000000000060b12181d1f252a2d2e313336373839393939373634312e2d2a25201d18120d11171b1f262b2e2f323537393939393735322e2d2a251f170f0500000000000000000000000000000000000000060b151a1f262b2f35393a404446494b4d4f50515252535251504f4d4b4846443f3a38342e29241e19130c0400000000000000000000000000000000000000000000000000000000000000040a0f151a1d24292c2e34383a3c3e404244444546464545444342403d3b3a36312d2c28231c19130d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111e2a36414c565e6169696969696967645c52473c47525c6366696969696969615e564c41362a1e11050000000000000000000000000000000000000000000000000000000000000000000000010d1a2733404c58646e747979797979797979736d635b51493f372d251b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b252d373f49515b636d737979797979797979746e64584c4033271a0d010000000000000000000000000000000000000000010a131c252e384044505b656c7881868686868686868683796d675d544a42382d261c130a01000000000000000000000000000000000000000000000000000000000000000000060b141a21272c32383b4246484e5355545b6062646668696a6b6c6c6c6c6b6a6a68666462605d555553504946413b373229241e160e07010000000000000000000000000000000a16212d38424c545a5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5a544c42382d21160a0000000d1925303b4650585d5f60606060606055534e463c31261b0f030000000000000000000000030c19242f3a444c52545e6060606060606060605f5a52493e33271b0f000000000000000000000000000000000000000001070d13191c23282b2d3337393c3f41434445464646454443413e3c3937332d2b28221c19130d070100000000000000000000000000000000000000000000000000000000000000000000000000000001070d13191c23282b2d3337393c3f41434445464646454443413e3c3937332d2b28221c19130d07010000000000000000000000000000000000000000000000000000000000020a11171d24292c3036393a3e40424445464646454442403e3a3936302c29241d191b22272b31373a3b3f42444546464544423f3b3a36312921170d0300000000000000000000000000000000020a111720262b31373a4145474a515355585a5c5d5e5f5f5f5f5e5d5c5a575553504a46443f38353029241e160d070000000000000000000000000000000000000000000000000000000000070c151b20262b2f35393a3f4446484a4d4f5051525253525251504e4c4a4846423d3a38342e29251e19140d0500000000000000000000000000000000000000000000000000000000000000010407070a0d10111213131211100d0b07070501000000000000000000000000000000010406070a0d0f11121213131211100e0c0908060300000000000000000000000000000000000000000000000000000000000000000000000000010d1925303b444c52545c5c5c5c5c5c5a58524a4136404a52585a5c5c5c5c5c5c54524c443b3025190d010000000000000000000000000000000000000000000000000000000000000000000000000b1824303c48535c64676c6c6c6c6c6c6c6c66635b51493f372d251b130900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131b252d373f49515b63666c6c6c6c6c6c6c6c67645c53483c3024180b00000000000000000000000000000000000000000000010a131c2627333f49535b666c757979797979797979776d675d554b42392f261c140a01000000000000000000000000000000000000000000000000000000000000000000000003090e161b21272c31363a3c4247484a50535557595b5c5e5f5f5f5f5f5e5e5d5c5a585553514b4946443f3836302b262019130c0400000000000000000000000000000000000d1926323e49545e666969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969665e54493e3226190d000000101c2935414d5862696c6c6c6c6c6c6c625f584e43372b1f120600000000000000000000000b151e2935414c565d606b6c6c6c6c6c6c6c6c6c6c645a4f43372b1e1200000000000000000000000000000000000000040c13181e24292e34383a3f4446484b4e50515253535352514f4d4b4846443f3938332d29241e18130c0400000000000000000000000000000000000000000000000000000000000000000000000000040c13181e24292e34383a3f4446484b4e50515253535352514f4d4b4846443f3938332d29241e18130c04000000000000000000000000000000000000000000000000000000060c141c23282f35393a4146474a4d4f515252535352514f4d4a4746413a39352f2924262d33373c4347484c4f5152535352514f4c4846423b33291f1409000000000000000000000000000000060c141c232831373c42474c5154545c60626466696a6b6b6c6c6b6b6a69676462605b5453504a45413a352f281f18120b0300000000000000000000000000000000000000000000000000030b121820262b31373a4145474a50535557595c5d5e5e5f5f5f5e5e5d5b595755534d4946443f3835302a251e170e080200000000000000000000000000000000000000000000000000000002080d111314171a1d1e1f201f1f1e1c1a181413110d0803000000000000000000000003080d111314171a1c1e1f1f201f1f1e1d1b181615130f0a0602000000000000000000000000000000000000000000000000000000000000000000000008141e29323b4146475050505050504e4c4741382f3840474b4d5050505050504746413b32291e1408000000000000000000000000000000000000000000000000000000000000000000000000000814202b36414a53585a60606060606060605957514940372e251b1309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000109131b252e37404951575960606060606060605a58534a41362b2014080000000000000000000000000000000000000000000000010a1417222d38414a545b60686c6c6c6c6c6c6c6c6a605d554c433930271d140a020000000000000000000000000000000000000000000000000000000000000000000000000000040a0f161b1f252a2d31373a3b3f4446484b4d4e505152525353525151504f4d4b494745403c3937332d2a251e1b150d08020000000000000000000000000000000000000f1c2935424e5a6670767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767670665a4e4235291c0f000000121f2b3844515d697479797979797979766a5f53473a2e2115080000000000000000000007121d27303945525d686d78797979797979797979766c5f5346392d2013000000000000000000000000000000000001070d161d24293035383f444649505355585a5c5e5f5f605f5f5e5c5a585553504946443f38353029241d160d080200000000000000000000000000000000000000000000000000000000000000000001070d161d24293035383f444649505355585a5c5e5f5f605f5f5e5c5a585553504946443f38353029241d160d0802000000000000000000000000000000000000000000000000070f181e262e34394045474c5254575a5c5d5f5f605f5f5e5c5a5754524c47454039352f2f383f44464e5355595c5e5f5f5f5f5d5b5954534d453b31251a0e0200000000000000000000000000070f181e262e343c43474d53555d6064666d6f71737577777879797877777673716e6c6663605c54524c45413a3128231d150c040000000000000000000000000000000000000000000000070c151d232831373c42474b5154545c60626466686a6a6b6c6c6c6b6a6a686664615f575653504a46413a3630292019130d0500000000000000000000000000000000000000000000000003090e13191d202124272a2b2c2c2c2c2b29272421201d1913100c0600000000000000060b0f13191d20212426292a2b2c2c2c2b2b29272522211f1b15120e0903000000000000000000000000000000000000000000000000000000000000000000020d1720293036393b43434343434341403c362f262e353b3f404343434343433b3936302920170d0200000000000000000000000000000000000000000000000000000000000000000000000000030f1a252f3841484c4e53535353535353534c4b4640372e251c1309010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e3740464b4c53535353535353534e4c4841382f251a0f030000000000000000000000000000000000000000000000000006111b262f38424a50535b60606060606060605d54514c433a31271e150b020000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f141a1e21262b2e2d3338393c3e40424344454646464545444342403e3c3a39352f2d2b27221b19140f0a040000000000000000000000000000000000000000101d293643505c6976828383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838276695c504336291d10000000131f2c3946525f6c79868686868686867c6f6255483c2f221509000000000000000000000c18232e39424f59606d7a85868686868686868686796c605346392d201300000000000000000000000000000000040c13181f282f353a41454a5053535b60626567696a6c6c6c6c6b6a69676562605b5353504a45413a352f281f19130c0400000000000000000000000000000000000000000000000000000000000000040c13181f282f353a41454a5053535b60626567696a6c6c6c6c6b6a69676562605b5353504a45413a352f281f19130c0400000000000000000000000000000000000000000000071019212a30383f444b5153565e616466696a6b6c6c6c6c6a696764615e5653514b45413a3c41495053585f6265686a6c6c6c6c6a6865615e574d42362a1e1205000000000000000000000000081019212a30383f444e53575f62676d7175797c7e8082838485858685848382807e7b7974706d66605d56524c433d342e271e160e050000000000000000000000000000000000000000000810191e272e343c43474d53555d6064666d6f7173757777787979787877767573706e696763605c54524c46413b322a251e170e0600000000000000000000000000000000000000000000060e141a1e24292c2d3134363738393938383634312e2d29251f1c17110a03000000020a11171b1f24292c2d313335373839393938383634322f2e2b26211e1a150e09030000000000000000000000000000000000000000000000000000000000000000050e171e252a2d2e3636363636363433302b241d242a2f32333636363636362e2d2a251e170e0500000000000000000000000000000000000000000000000000000000000000000000000000000008131d262f363c40414646464646464646403e3b352e251c130a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e353b3e40464646464646464641403c362f261d13080000000000000000000000000000000000000000000000000000000a141d262f383f44464e5353535353535353504745413a31281f150c03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e12151a1e2122282b2d2f313335363738393939393837373533312f2d2c2924201f1b17110e08020000000000000000000000000000000000000000000013202d394653606c79868f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f86796c605346392d2013000000131f2c3946525f6c79859293939393887b6f6255483c2f22150900000000000000000005101c2834404b54606b74818e979393939393939386796c605346392d2013000000000000000000000000000000070d161d2429313a40454c52545c6063656c6f727476777879797978777674716f6c6563605b54524c45413a3129241e160e070000000000000000000000000000000000000000000000000000000000070d161d2429313a40454c52545c6063656c6f727476777879797978777674716f6c6563605b54524c45413a3129241e160e070000000000000000000000000000000000000000071019232b333b424a50555d6065686d717375777879797978777573716d6865605d55524c44464e535b60646a6e727577787979787775726e695e53463a2d211407000000000000000000000008111a222b333c424a50585f62696e747a7e8185888b8d8f90919292929291908f8d8a8885817d79736d68605d564f454039302820160e050000000000000000000000000000000000000009111a222a303940454e53575f62676d7175797b7d8082838485858685858483817f7d7b7874706d66615e56524c443e36302920180f070000000000000000000000000000000000000000060f181f262b3035393a3d404344454646454443403e3a3935302c28231c150c0802070b141b22272b2f35393a3d40424445454646454443413f3c3b37322e2b26201a150e060000000000000000000000000000000000000000000000000000000000000000050d14191e20212929292929292726241f1a13191f23262729292929292921201e19140d0500000000000000000000000000000000000000000000000000000000000000000000000000000000010b141d252b303334393939393939393933322f2a231c130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c232a2f323339393939393939393433302b251d140b01000000000000000000000000000000000000000000000000000000020b141d262d333839424646464646464646443a39352f281f160d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205090e1214171c1f2022242628292b2c2c2c2c2c2b2b2a2927252220201d1813120f0b060000000000000000000000000000000000000000000000000013202d394653606c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9386796c605346392d2013000000131f2c3946525f6c7985929f9f9f95887b6f6255483c2f2215090000000000000000050e1b242c3845515c666f7c88939fa99f9f9f9f9f9386796c605346392d201300000000000000000000000000000810191f282f353e434b51565d60666d7074787b7e81838485868686858482807e7b7874706c66605d56514b433e353028201910080000000000000000000000000000000000000000000000000000000810191f282f353e434b51565d60666d7074787b7e81838485868686858482807e7b7874706c66605d56514b433e35302820191008000000000000000000000000000000000000050e19222b353d454d545c60676d72767a7e80828485858686858482807d7a76726d67605d565050585f656c71767b7f82848586868584827f7b6e6154483b2e2115080000000000000000000007111a232b343d454d545c606a6e757b81868a8e929897999c9d9e9e9f9f9e9e9d9c9a9797928e8985807a736d686059514b423a322820170e05000000000000000000000000000000000009121b232c343c424b51585f62696e747a7d8185888a8c8f9091919292929191908e8c8a8884807d79736d68615e565046413a322a211910070000000000000000000000000000000000020a1117212a31373a4145474a4d505152535252514f4d4b4746413a38342e261e19130d12181d262d33373a4145474a4d4f51525253525251504e4b4947433c3a37312b2620180f06000000000000000000000000000000000000000000000000000000000000000002080d1114141d1d1d1d1d1d1b1a17140e080e1317191a1d1d1d1d1d1d1414110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b131a202427272d2d2d2d2d2d2d2d2625231e19120a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d272724201a130b020000000000000000000000000000000000000000000000000000000000020b141c22282b2d353939393939393939372d2c29241e160d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206060b0f121315181a1b1d1e1f1f20201f1e1e1d1c1a18161413110d07050300000000000000000000000000000000000000000000000000000013202d394653606c7986939f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9386796c605346392d2013000000131f2c3946525f6c7985929faca295887b6f6255483c2f22150900000000000000020c16202b37424d57606d7983919aa4afacacacac9f9386796c605346392d20130000000000000000000000000009111a222b313a41454f555d60686d73797d8185888b8d8f919292939292918f8d8b8885817d78726d68605d555046413a322b221a11090000000000000000000000000000000000000000000000000009111a222b313a41454f555d60686d73797d8185888b8d8f919292939292918f8d8b8885817d78726d68605d555046413a322b221a110900000000000000000000000000000000020d17202b343d474f575f666d72797e83878a8d8f909292939292918f8d8a86837e79736d68605b5a626a6e787d83888c8f9192929292908e8c8275685b4f4235281c0f000000000000000000050f19232b353d464e575f666d727c81878e92999b9fa2aaa6a8aaa9a8a7a7a8a9aaa9a6a9a29e9a97928d85807a706b605c544c443a322920170c0300000000000000000000000000000009121b242d353e464e545c606a6f757b81868a8e929797999b9d9d9e9f9f9f9e9d9d9b999796918d8985807a746e68615a524c443c332b22191007000000000000000000000000000000020b141b2227333c42464c5254575a5d5e5f5f5f5f5e5c5a5754524c46443f38302a251e171d24292f383f44464c515457595c5d5e5f5f5f5e5e5c5a5855534e4847423c37312a2117110a020000000000000000000000000000000000000000000000000000000000000000010507081010101010100e0d0b08030002070a0c0d1010101010100807050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080f14181a1b2020202020202020191916120d07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d1216191920202020202020201b1a18140f080100000000000000000000000000000000000000000000000000000000000000020a11171c1f20282d2d2d2d2d2d2d2d2a21201d19130c040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030606090b0d0f101112131313121211100f0d0b090706040100000000000000000000000000000000000000000000000000000000000013202d394653606c798693939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939386796c605346392d2013000000131f2c3946525f6c7985929faca295887b6f6255483c2f2215090000000000000008131e28323a47535f69737f8c95a0acb6b8b9beac9f9386796c605346392d201300000000000000000000000009121b232c343d434b515961676d737a7f848a8e92979899969494989298949496999897918e89847f7a736d67615a524c443d342c231b1209000000000000000000000000000000000000000000000009121b232c343d434b515961676d737a7f848a8e92979899969494989298949496999897918e89847f7a736d67615a524c443d342c231b120900000000000000000000000000000008141e29323d464f5960696e787f858b90939a999c9d9e9f9f9f9f9d9c9a9992908b85807a726c65636c717c838a9095989b9d9f9f9f9f9d9b8e8275685b4f4235281c0f0000000000000000030d17212b353d474f5860696e787f868e93999fa3ababaca8a9a29e9d9b9b9a9b9c9d9fa3aaa9aba9a19e98928c857d736d665d564c443a32291e150a000000000000000000000000000007101b242d363e474f585f666d737c82878e92989b9ea2a9a6a8aaa8a7a6a6a6a7a8a9a8a6a8a19e9a97928c86807a716c615e564d453c342b22190e0500000000000000000000000000000a141d262d333f454d53565d606467696a6b6c6c6b6b696764615e5653504a423e36302920272f353e41495053555d606466686a6b6c6c6c6b6b696765625f5855534e47423c3328221c140b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080b0d0e13131313131313130d0c0a0602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002060a0c0d13131313131313130e0d0b08030000000000000000000000000000000000000000000000000000000000000000000000060b0f12131b20202020202020201d1413110d08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202d394653606c798686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c605346392d2013000000131f2c3946525f6c7985929faca295887b6f6255483c2f221509000000000000030d1925303a44505a616e7b86929fa7afacabadb3ac9f9386796c605346392d2013000000000000000000000009121b242d353e464e555d606c707980868c91969a97918e8c8988878685868788898c8f91979a96918c868079706c615d564e463e352d241b120900000000000000000000000000000000000000000009121b242d353e464e555d606c707980868c91969a97918e8c8988878685868788898c8f91979a96918c868079706c615d564e463e352d241b120900000000000000000000000000020e1925303b444e58606b6f7b838b92979c9fa4a9a19e9c9a9a999a9c9ea1a39f9c97928d857e776e6d737e8690959d9fa7a8aba49f9f9f9f9b8e8275685b4f4235281c0f00000000000000010b151f29333d474f59606a6f7b838c92999fa4abadaaa29f9b979792908f8e8e8e8f909298989d9fa7acaaa29f97918880786d685e564c443a30261c1106000000000000000000000000050e19222d363e485059616a6f7980878f93999fa3aaabaaaaa29f9d9b9a9a999a9a9b9d9fa2aaa9aba9a19e98928d857e756d685f574e463c342a20170c0300000000000000000000000006111b262f383f4451575f61686d7073767778797978777673716d6864605c545046413a322a313940454f535b6064676d707375777878797978777674726f6a67625f57534d453f332d261d140b0200000000000000000000000000000000000002080d10121313131313131313131313131313131313131313131313121211100e0b09070604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306060f131313131313131311070604010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030608090c0f111213131211100e0c0a07060401000000000000000000000000000000000000000000000000000000000013202d3946535f6c767979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979766c5f5346392d2013000000131f2c3946525f6c7985929faca295887b6f6255483c2f2215090000000000010b151f2a36414c56626c76828f98a3aca49f9ea1a9b39f9386796c605346392d20130000000000000000000007111b242d363e474f5860676d747d848c929897928d8985827f7d7b7a7979797a7b7d7f8285898d929798928c857d756d6860584f473f362d241b11070000000000000000000000000000000000000007111b242d363e474f5860676d747d848c929897928d8985827f7d7b7a7979797a7b7d7f8285898d929798928c857d756d6860584f473f362d241b110700000000000000000000000005111e2a36414c56606a6f7d8590959ea1a9a29e9997928f8e8d8d8d8f9197999ea1a29f97928b827a747f8b92989fa7a9a19e999993929292998e8275685b4f4235281c0f0000000000000007121d27313b454f59606b707c8590959fa3abaea9a19e98928e8a87858382818181828386888b90959b9fa4aca9a19a938d837a6d685e564c42382e23170d0400000000000000000000020d17202b343e48505a616b707c838c92999fa4abaca7a09d999892908f8d8d8d8d8d8f909298989c9fa4abaaa29f97928a827a6e6960584e463c32291e150b0000000000000000000000000b17222d384149505b62696e747a7d808384858685858482807e7a76716d66615a524c443b333a434b515961656c71757a7d80828485858685858483817e7c78746e6a625f5751443f382f261d140a0000000000000000000000000000000000060d14191c1f1f202020202020202020202020202020202020202020201f1e1e1c1a18161413100c070501000000000000000000000000000000000000000000000000000000000003080c0e0e131313131313130f0e0c09040000000000000000000000000000000000000000000000000000000000000003070b0d0e131313131313130e0e0c080300000000000000000000000000000000000000000000000000000000000000000001040707090c0e101111121313121211100f0d0b0907060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f131516191c1e1f1f201f1e1d1b19161413110d0801000000000000000000000000000000000000000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e12000000131f2c3946525f6c7985929faca295887b6f6255483c2f221509000000000007121d27313946525e68717e8b949faaa49a939297a1ad9f9386796c605346392d2013000000000000000000060f19232d363e485059616a6f79818a919797918b85817c797572706e6d6d666d6d6e707275797c81858b919697918a817a6f6a615951483f362d23190f060000000000000000000000000000000000060f19232d363e485059616a6f79818a919797918b85817c797572706e6d6d666d6d6e707275797c81858b919697918a817a6f6a615951483f362d23190f0600000000000000000000000714202d3946525e686f7c869297a0a7a49d97928c888582818080808285888c91969ea1a29f948f84818c919fa3aaa39f97928d898685858687898275685b4f4235281c0f000000000000000c18242f39434d57606b707d8692979fa7aeaba39f96918b86817e7b7876757474757677797c7f83888e939a9fa7aca49f9590837a6d685e544a3f34281f160c0100000000000000000009141f29323d46505a626c717d8690959fa3ababa49f9b95908c898584828180808081828385888b8f93999fa2aaa9a19e938f847b6f6a60584e443b30271d120700000000000000000000030f1b27333f49535b606d727b81868a8d909192929292918f8d8a86837e78716c615e564d453c444c555d606c70787d82868a8c8f909192929291918f8d8b8884807b756e69625b504a42382f261b11060000000000000000000000000000000810181f25292b2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2b2a29272523201f1c1813110d08020000000000000000000000000000000000000000000000000001090f14181a1b202020202020201c1b191510090200000000000000000000000000000000000000000000000000000001080e1317191a202020202020201b1a18140f0901000000000000000000000000000000000000000000000000000000000206080d11131416181a1c1e1e1f1f201f1f1e1d1b1a18161312100b060603000000000000000000000000000000000000000000000000000000000000000000000000060a0e1011131313131313100f0d0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c10151b1f222226292a2b2c2c2b2b2a28252321201d19130c0400000000000000000000000000000000000000000000000000000f1b27333e49525a5f60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605f5a52493e33271b0f000000131f2c3946525f6c7985929faca295887b6f6255483c2f22150900000000020b18232f39434f59616d7a85929ea6a99f938785929eab9f9386796c605346392d20130000000000000000030c18212b353e48505a626b707c848e9398928c857f7974706c6666636161605c6061616366666c7074797f848b9298938e857c706b625b51483e352b21180c03000000000000000000000000000000030c18212b353e48505a626b707c848e9398928c857f7974706c6666636161605c6061616366666c7074797f848b9298938e857c706b625b51483e352b21180c0300000000000000000007131f2c38444f59616e7a859198a2a9a39f928d85807b78757473737475787b7f848b91969ea59f96918d929ca4a9a199928c85807c797878797a7d7e7164574a3e3124170b00000000000004101d2935404b555e69707d879298a2a9b1a8a099928c847f7a75716e696a6868676869666d6f72767b818790959da4afa79f9590837a6d665c50443e31281d13070000000000000000030d1925303b444e58626c717e879298a0a7afa79f99938e88837f7c79777574737373747577797c7f83878d92989ea5ada59e9691857c6f6a5f564c42392e23180c030000000000000000040f19232b3744505b656c747f868d92989a9c9d9e9f9f9e9e9c9a9992908a847e756d685f574e464c565d676d747d838a8f9299999b9d9e9f9f9f9e9e9c9a9896918d87817b726d605b544a41382d22170b040000000000000000000000000006101a222a30353839393939393939393939393939393939393939393939393838373634322f2d2c2923201d19130f0a0300000000000000000000000000000000000000000000030b131a202427282d2d2d2d2d2d2d292825211b140c0300000000000000000000000000000000000000000000000000020b12191f2326272d2d2d2d2d2d2d282724201a130b0300000000000000000000000000000000000000000000000000040a0f1214191d2021232527292a2b2c2c2c2c2b2b2a28272522201f1c1715120f0a050200000000000000000000000000000000000000000000000000000000000000040b11161a1d1e2020202020201d1c1916100a030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b12181d1f272b2e2f3235373839393837363532302d2c29241e160d04000000000000000000000000000000000000000000000000000a16212c3740494f535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534f4940372c21160a000000131f2c3946525f6c7985929faca295887b6f6255483c2f221509000000000a141d2934404b55606b74818e97a1ada1978e8183909da99f9386796c605346392d201300000000000000000b151e2a333d47505a626c717d8691969490867f79726d6763605b54565554535053545556545b6063676d72797f858f949791867d726d625a50473d332a1e150a0000000000000000000000000000000b151e2a333d47505a626c717d8691969490867f79726d6763605b54565554535053545556545b6063676d72797f858f949791867d726d625a50473d332a1e150a0000000000000000000915222f3b4854606b75818e97a1aaa399928a8079736e69696767666769696e73797f848e939fa3a19e9a9da4a8a09691877f79736f6d67666c6e70716c6155493c3023170a000000000005101a232c3945515d676e7b859299a2aab1a79f9691878079726d6764615e575c5b5b5b545c6062656a6e747c838d929fa3aba7a0959082786d60594f433a2f24180d02000000000000010b151f2a36424d56606a717e889299a2aaafa49c959087817c77726f6d6668676766676768666c6f72767b80868e939fa3aaa8a09792867c6f685e544b40342820150900000000000000000b16212c38444f59606c77818b92999fa2aaa9a8a09e9c9b9c9d9fa29f9c96918a827a6e695f584e555d686d79818a90959c9fa3aba39f9e9c9b9c9d9ea1a9a8a19e99938e867f746c665b53493f332720150a000000000000000000000000020d18222c343b4144464646464646464646464646464646464646464646464645454443413e3c3a38342f2d29241e1a150f0a0400000000000000000000000000000000000000010b151d252b303435393939393939393534312c261e150c000000000000000000000000000000000000000000000000000b141d242b303334393939393939393534302b251d150b0100000000000000000000000000000000000000000000070c10151a1f2124292c2d303234363738383939393838373533322f2d2b2823211f1b15120e090300000000000000000000000000000000000000000000000000000000050d151c2227292a2d2d2d2d2d2d292926211c150d04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d151d24292c32373b3c3f4244454646454443413f3d3a39352f281f160c0100000000000000000000000000000000000000000000000005101b252e373e4346464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646433e372e251b1005000000131f2c3946525f6c7985929faca295887b6f6255483c2f22150900000006111b262f3845515c67707d89939ea9a69e91857a84919daa9f9386796c605346392d20130000000000000007121d27303c454f59626c717e879298938c827b726d67605c5553504a4d505152535352514e4a5053555c60676d727b828b929892877f726c61594f453c30261c11060000000000000000000000000007121d27303c454f59626c717e879298938c827b726d67605c5553504a4a484746444647484a4a5053555c60676d727b828b929892877f726c61594f453c30261c11060000000000000005111d2a36414c56636f7c89939ea9a59f92877e746d67625f575b5a5a5a575f62666d7279818c9299a3aba7a9aca09691847c736d6762605c5b60616364615a5045392d21140800000000000b16212b37434e58606d79839097a1abb1a79f9590847c736d67605d5554524d4f4e4e4e4a505355585f626a6f78808a9299a3aba79f948d80736b61554b4035291f140900000000000007121d27313946525e696f7c86929aa3ababa39f928d837c756f6a6662605c545a5a5a5a5a545b606265696e747b818a9298a2a9a9a19891847a6e665c51453c31261a0e0500000000000003101b27323b4854606b73808c939fa3aba9a19e9896918f8f8f909297989d9f9e938f847b6e6a5f565d676d7a838e939da0a7a59e9b999291908f8f909297979c9fa6a49f98928b81786c655b50443c32261b0f05000000000000000000000008141f2a343e464d5152535353535353535353535353535353535353535353535251514f4d4b494745403a3935302b26201b150c0700000000000000000000000000000000000009131d272f373c40414646464646464642413d3730271e0e050000000000000000000000000000000000000000000000030d1d262e363c3f414646464646464641403c372f271d13090000000000000000000000000000000000000000070c12181c1f262b2e2f35393a3c3f414344444546464545444342403e3c3a38342e2e2b26211e1a140f0a0400000000000000000000000000000000000000000000000000040d171f272e3336373939393939393635322d261f160d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a10191f272f35383c4347494c4f515252535251504e4c494745413a31281e13080000000000000000000000000000000000000000000000000009131c252c33373939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393937332c251c130900000000131f2c3946525f6c7985929faca295887b6f6255483c2f2215090000000b17222d38414e58606d7984919ea5aa9e948a7e7885919eab9f9386796c605346392d2013000000000000000c18232e39434d57606b717e8b929992887f786e69605d55514b5153575a5c5e5f5f5f5f5d5b5854524d51555c60696e767f879298928b7e716b60574e42382e23170c030000000000000000000000000c18232e39434d57606b717e8b929992887f786e69605d55514b514f4b443b3a3a383a3a3b3d3f44464b51555c60696e767f879298928b7e716b60574e42382e23170c030000000000000713202d3946525e6875828f9ca5ab9e938b7e716c605d55534d4e4d4d4d4d53545c60676d757f87929facb4b7aa9e91847b6f6a605d55535150535456575550483e33281c11050000000004101c27333a47535f6a74808d95a0a9b2a89f9590837a6f6a605c55514b484642424141423f4446494e53585f666d737e879299a4afa69f93887d70675d51453b30251a0e0200000000000c18232f3943505a616e7b859198a3acaca399928b80786f6a625f585653504a4e4d4d4d4e4a505355575e61696e757e869297a2aaaaa1969082786d60574e42372b21170b0000000000000713202c38444f5963707d88939fa5aea69f97918c87848382828385888b90959d9e9691857c6e685e606d798390959da5a8a09d938f8a86848382828385878b8f949da0a7a29f938e81776c60584e43372b21160b00000000000000000000000d1925303b4650585d5f6060606060606060606060606060606060606060605f5f5e5d5c5a585653514b4746413a37312b262018120b03000000000000000000000000000000030f1a252f3941484d4e535353535353534f4d4942393020170d02000000000000000000000000000000000000000000010b151f2e3840474c4d535353535353534e4d4841392f251a0f030000000000000000000000000000000000030b12181c23282c31373a3b414547494b4d4f5151525253525251504e4d4b4946443f3c3a37312d2a251f1b160f0a0400000000000000000000000000000000000000000000000b151f2931393f424446464646464643423e3831281f150a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b131c222b31394045474e5455595c5d5e5f5f5e5e5d5b585654514c433a2f24190d01000000000000000000000000000000000000000000000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b27211b130a0100000000131f2c3946525f6c7985929faca295887b6f6255483c2f2215090000040f1b27333f49535f6a73808c96a0aca2988f82757985929fac9f9386796c605346392d201300000000000004101c2834404b555f69707d87929892877e726c665f57514d53555c606467696b6c6c6c6b6a6865615e57544f51575e616d727d86929792877d706a5f544a3f3428201509000000000000000000000004101c2834404b555f69707d87929892877e726c665f57606060605e5c564e44392d2c2d2e323f49515759606060575e616d727d86929792877d706a5f544a3f34282015090000000000000714212e3a4754616d7a86929faca3998e81756d625a514b47424140404142474b51555e69707c86929facb8b0a3968a7d70696058514b46454446474a4a49453e362c22170c00000000000714202c38444f59626e7c87929fa7b1aaa1969083796d685f58514b45413b3a363035342e34383a3c43474e545c606c717e87939fa5afa49a9185796d60574d42362a1e11050000000004101c2934404b55616c76828f97a1aaafa49a92877e736d665f58534e4946443f41404040413f4446484d53565e616c717c859298a2aca89f948d80736a5f53473e33281c100400000000000916222f3b4854606b7683909aa4afa89f948f847f7a7776757676787b7f838990959c9791847a6d666c75818f959fa7a79f959189827e7a7776757676787b7e828990959ea5a59d938c7f736a5f53473d33271c100400000000000000000003101c2935414d5862696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6b6a69676562605c5554524c47433c373228231d150c0700000000000000000000000000000814202b37414b53595b606060606060605c59544b4232291f140900000000000000000000000000000000000000000007121d2731404a52585a606060606060605b59534b41372b20140800000000000000000000000000000001070c151d23282e34383c4347484c525456585a5c5d5e5f5f5f5f5e5e5d5b5a585553504a4847433c3a36312b27201b150d0802000000000000000000000000000000000000000006111c27313b434a4f51535353535353504e49423a31261c1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b141c252e343d434b515358606265686a6b6c6c6b6a69686563605d554c4135291d110400000000000000000000000000000000000000000000000000010910161b1e202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201e1b161009010000000000131f2c3946525f6c7985929faca295887b6f6255483c2f22150900040d1a232b3744505b656f7c87929fa8a79f92867b6e7986939fac9f9386796c605346392d20130000000000050f1a232c3845515c676e7b85929992867d716c605b544d51575f61676d70737677787979787775726e69636059524d525b626b707c85929892857c6e665c50443c31261a0f04000000000000000000050f1a232c3845515c676e7b85929992867d716c605b63666c6c6c6c6b6760564b3f331f25303b44515b62656c6c6c6c6c67646b707c85929892857c6e665c50443c31261a0f0400000000000b1825313e4b5864717e8b99a3ac9f92867b6e625a504540393731343331373c45515c676e7b859299a3aeabaea99c9083786c60564c413a3838393b3d3e3c39332c241a100500000000000916232f3c4855616b76828f99a3afaea39891847a6d675e564e454039352f2d2a25282823282c2d31373c424a505a616c727f8b939ea8aca1978c8073695e52463a2d2014070000000006131f2c3845515c67707d8a949fa9b0a69f93887e716c605c544e47433c3a38342e3433342d3338393c42464d525a616a6f7c86929aa4afa69f92877b6e62594f44392d20150a00000000000a1623303d495663707c89949facaca0958f827a726d686968696a696e72767d838c929f968f82786d717e8b939ea7a79f9590837d75716d676968696a696e71767d838e939ea5a59f92877c6f62594f44382c20140700000000000000000005121f2b3844515d697479797979797979797979797979797979797979797979797878777674716f6d6764615d56534e47433c342e271e191008000000000000000000000000000c1824303c48535d64686c6c6c6c6c6c6c68655d54443b3025190e0000000000000000000000000000000000000000000c18232f3943525c64676c6c6c6c6c6c6c68645d53483c3024180c0000000000000000000000000000030b12181e272e34394044464e5355565d60636567696a6b6b6c6c6c6b6b6a68666562605c5455534e4846423b37322b262019130c04000000000000000000000000000000000000000a16222e39434d555b5d6060606060605c5a544c42382d21160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c262e3740464f555d60656a6f7275777879797877767472706d675d5145392c201306000000000000000000000000000000000000000000000000000000050a0f1213131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313120f0a0500000000000000131f2c3946525f6c7985929faca295887b6f6255483c2f221509010c161f2a36414c56606c77839099a3aba0958c7f726d7a879aa4af9f9386796c605346392d201300000000000b16212b37434e58606d7983919792877d706b615a504d555c60696e74797d8082848586868584817f7b76706b605d564e5159606a6f7c8692979083786d60584e43372b21160a0000000000000000000b16212b37434e58606d7983919792877d706b615a636d72797979797772675c4f43372a2a36414d56626d727979797979746e646a6f7c8692979083786d60584e43372b21160a00000000000e1b2834414e5b6774818e9aaba99c8f8276695f53483f352f2b262727313c46515b606d79839097a1aaa29fa2aa9f948b7e71685e52463c322b2d2e3031302d28221a1208000000000005121e2a36424d5763707d89949fabb2a89f92867c6f685e554c443c342e2924201e1a1b1b171c1f20262b30383f44505a626d75818e96a0aca79f92867b6e6154473b2e21140800000003101c28343f4a54606d7984919ea6b0aa9e948c7f736c625a504a423c37322d2c282327272722282b2d31363b42465058606a707e88939fa8aea3998f82766c6155493c31261b0f0000000004101d2935404b556774808d9aa6b0a99d91837a6d68615e565c5c575f61656b7078808b9399948c7f737a85929fa5aba095908279706b64605d555c5c565e61646b7079818e939ea8a3999083776b6054483c2f22160900000000000000000006131f2c3946525f6c79868686868686868686868686868686868686868686868685848482807e7c7975716d68625f58534e454039302a221a11090000000000000000000000000e1a2734404d59646f7479797979797979756f65564d42362a1c11060000000000000000000000000000000000000004101c2934404b55646e7479797979797979746f64594d4034271a0e00000000000000000000000000040d151d2329303940454a5153585f6266686d6f7274767777787979787877767573716f6d6666625f5854534d47433d373129241e160e060000000000000000000000000000000000010e1a27333f4a555f676a6c6c6c6c6c6c69665e54493e3226190d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101b252e384049515960676d71777c7f8284858586858483817f7d796d6054473a2d21140700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7985929faca295887b6f6255483c2f22150907121d28313946525e68727e8b949faba3999083786d6e7a8794a1b69f9386796c605346392d20130000000004101c27333a47535f6a73808c95928b7f726b6159504d575e676d737b81858a8d8f9192929292908e8b87827d756d685f584e4f58606a707e8793958c7f726a5f53473d32271b0f040000000000000004101c27333a47535f6a73808c95928b7f726b61595966727f8686868684776b5e51443826303846525e68727f8686868686817467606a707e8793958c7f726a5f53473d32271b0f0400000000101d2a3743505d6a7683909da9a5988c7f7265574d423629241d1a242f39434e58626d74818e959fa9a29892989fa69e92857a6d61584e43372b2021232423211c1710080000000000000714212d3a46535e6975828f9ca6b0aca0968c7f736a60564c433a3228231d1814120e09060c1012131a1e262e343e48515b606d7984919ea09d95908a807366594d4033261a0d00000006121f2b3844505c66727f8c96a0acaea2988f82776c605a50443f38302b26201f1c171a1a1a171c1f20252a30363e464e58616c73808d96a1acab9f948a7d7064584e43372b1d120700000006131f2c3945515d677784909daaada1978a7d70675e56524c4f4f4d53555960666d737e87939f92867b7f8c97a2ada39990837a6d67605954514c4f4f4d52545960676d78818f96a0a49f95897d7063564a3d3023170a00000000000000000006131f2c3946525f6c7985929393939393939393939393939393939393939399929291908f8d8b8985827e7a756f6a625f58514b433c342c231b120900000000000000000000000e1b2835414e5b687481868686868686868175695e5246382d22170b0000000000000000000000000000000000000006131f2c3845515c677480868686868686868174685b4e4135281b0e000000000000000000000000050e161f272f343d434b51545c60646a6e72767a7c7e808284848585868585848381807e7c7976736f6a66615e57544e47433c3530282017110a0200000000000000000000000000000003101d2936424f5b6771777979797979797670665a4e4235291c0f03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c19222d37404a525b636b6f797e84888c8f909192929191908e8b897f7266594c3f3326190c0000000000000000000000000003080c0e0e131313131313130f0e0c09040000000000000000000000000000000000000000000000000000000000000003070b0d0e131313131313130e0e0c0803000000000000000000000000000000000000000000000000000000000406070b0e11121313131313130c0c0a0602000000000000131f2c3946525f6c7985929faca295887b6f6255483c2f2215090b18242f39434f59616e7a85929fa6a89f92877c6f666e7b8894a1ac9f9386796c605346392d2013000000000714202c38444f59626f7c8792968e81746d62594f4d575e696e7980868d92989a9c9b999898999b9b9a938f89827a6f6a5f574d4e58616c737f8c9592867c6e62594f43382c20150a000000000000000714202c38444f59626f7c8792968e81746d62594f5966727f8c93939184776b5e5144382e38424f59616e7b8692939391857a6d6058616c737f8c9592867c6e62594f43382c20150a00000000121f2b3845525e6b7885919eaba295897c6f6256493c31231817202935404b555f6a727f8b939da7a298928590949fa1978e81746a5f53473c32261b17171714110c05000000000000000815212e3b4854616e7b87939facb2a89d9184796d60584e443a31292018120d0705020000000306090c151c2328363f45515d676f7d899395908a837e776c605346392d2013060000000713202d3a4653606d7884919ea8b2a99f92867b6e655b50483e342e261e1b1312100c060d060b0f12131a1f252a343d46505a606d7984919ea8b0a69c8f83766a5f5347392e23180c0000000714202d3a4753606d7a86939facab9e9285786c60554c464142434246484f545c606c727f8b9398908385929ea9ab9f92877c6f685d554f47454142434246474f555d666d7984919b9a93908c8276695c4f4336291c1003000000000000000006131f2c3946525f6c7985929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9e9e9d9c9a9898928f8b86817c756f6a605c554e463e352d241b1209000000000000000000000916232f3c4956626f7c89959393939392867b6e61544a3f33281c0f030000000000000000000000000000000000000714202d3a4753606d7985929393939395897c6f6356493c302316090000000000000000000000050f172028313940454f555c60666d71777b7f8386898b8d8f9091929292929191908e8d8b8885827f7c77736e69626058534e46413a3228221c140b03000000000000000000000000000004111e2a3744515d6a77838686868686868276695c504336291d10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151e2b343f49525c646d737c848b9095989b9d9e9f9f9e9d9c9b988c7f7266594c3f3326190c000000000000000000000001090f14181a1b202020202020201c1b191510090200000000000000000000000000000000000000000000000000000001080e1317191a202020202020201b1a18140f0901000000000000000000000000000000000000000000000001070c101314171b1e1f202020202020191816120d070000000000131f2c3946525f6c7985929faca295887b6f6255483c2f22150a141d2935404b55616b75818e97a2aca1968d80746a626f7b8895a2ac9f9386796c605346392d2013000000000916232f3c4855606b768390999184796d605b514b555e696e7b838d92999f9c96918e8c8b8b8c8e92979e9c938f847c6f695f564c505a606d788390988f82766b6054483d32271b0f000000000000000916232f3c4855606b768390999184796d605b514c5966727f8c999e9184776b5e514438343f4a54606b75818e989e948a7e71685d525a606d788390988f82766b6054483d32271b0f00000000131f2c3946525f6c7985929faca194887b6e6155483b2e22151f29333b45515d676f7c86929fa5a49a92867b829099a39f93877c6f62584e43372b20150a0a0805000000000000000005121e2a36424d576673808d99a4afaca0968a7e71665c51463c32281f170e0700000000000000000000030a1117242935414b55606b75818e8a837d78706c655b5044372b1f1205000005111e2a36414c5664707d8a96a1adada1978c7f72695e53493f3628231c140c0a060300000000000306090e1419222b343e45515d67717e8a96a0acab9f94887c6f62544b4034281c100400000815212e3b4854616e7b879aa4afa89b8f8275655b50433a363031363a3d424a515a626d75818e9794909297a1ada3998d80736a5f564c433d39352f30363a3d434b545d67707d8a8e8b87837f7c6f6255493c2f22160900000000000000000006131f2c3946525f6c7985929facacacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a6a7aaa9a7aaa29f9b99928e87827c736d675f584f473f362d241b10070000000000000000000915222e3b4854606a7783909daa9fa3998c7f73665b5044382b1f1409000000000000000000000000000000000006121f2b37434e5864717e8a97a29f9f9d9083776b6054483b2f22150900000000000000000000050e172129323a434b515960676d72797e83888c909399989a9c9d9e9e9f9f9f9e9e9d9b999898928f8c8884807b756f6a625f58524c443d332d261d150c040000000000000000000000000004111e2a3744515d6a778490939393938f8376695c504336291d1003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c26303d46515b646e737f8791969da0a7a8aaa8a4a2a0a0a0a1998c7f7266594c3f3326190c00000000000000000000030b131a202427282d2d2d2d2d2d2d292825211b140c0300000000000000000000000000000000000000000000000000020b12191f2326272d2d2d2d2d2d2d282724201a130b03000000000000000000000000000000000000000000060b12181c1f2024282a2b2c2d2d2d2d2d2625221e18120a01000000131f2c3946525f6c7985929faca295887b6f6255483c2f2215111c262f3845515d67707d8a939ea9a59e9184796d60626f7c8895a2ac9f9386796c605346392d201300000007131f2c38434f5963707d899593897d70675d5145515d676e7b8490959f9f948f898481807e7e7f82858a91969e9691857b6e685d5245505c666f7c879294897c6f63584e43372b1c1106000000000007131f2c38434f5963707d899593897d70675d51494c5966727f8c999e9184776b5e5144383844505c666f7d89939e988f82756c61564c505c666f7c879294897c6f63584e43372b1c110600000013202c3946535f6c7986929faca093877a6d6054473a2d211a25303b45505a606d79839199a3a59f93887e707c87929fa49a8f82756a5f53473c32261b0f01000000000000000000000714212d3a46535f697784919eabb5ab9d9184786c60544b40342b20160d0500000000000000000000000000061218242f3a434f59616e7b837e78716c65605b53493f33271b0f0300000714202d3946525e6876828f9ca8b2ab9e9185796d60574d41382d2417110a02000000000000000000000002091019222935404b55606c7884919dabb0a69a8e8174665c5145382c1f130600000916222f3c4955626f7c8895acb6a79a8d81746753493f312a25262a2d30394044515b616d7a85929f9c9ea1a9ac9f92867a6d61584e433a312c2924252a2d3139424b55606c7783827e7a76736f6a6054473b2e22150800000000000000000006131f2c3946525f6c7985929facb8ada39c9898989898989898989898989898999a9b9d9fa3aaaaacaba39f9a938f8780796f6a615950483f362d22190f05000000000000000007131f2c38434e5865727e8b98a2aeab9e9184786c6053463b30251a0e00000000000000000000000000000000000814212e3a47535f6a7683909ca9aea2988b7f7265594f43382c1f1307000000000000000000030d172029333b444c555c606b6f797f848b9095999c9fa4aba7a9a9a8a7a6a6a7a7a8a9a8a6aaa29f9c9995918c87817c766f6a615d564f443f382f271e160d0400000000000000000000000004111e2a3744515d6a7784909d9f9f9c8f8376695c504336291d100300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17232e38424e58626d73808c9299a0a8acaaa39f9b979594939394958c7f7266594c3f3326190c000000000000000000010b151d252b303435393939393939393534312c261e150c000000000000000000000000000000000000000000000000000b141d242b303334393939393939393534302b251d150b01000000000000000000000000000000000000020a11171d23292c2d3134373839393939393933322f2a231c130a000000131f2c3946525f6c7985929faca295887b6f6255483c2f221517222d38424e58606d7984919ea5a99e938a7d70675d626f7c8995a2ac9f9386796c605346392d20130000000915222f3b4854606b7683909a8e81756b60554b4e58606d798390969f99928b827c78747372727375797e848e939d9791847a6d605a504a545f6a74808d988f82766a605447382e23170c00000000000915222f3b4854606b7683909a8e81756b60554b414c5966727f8c999e9184776b5e514436414c56606d7883909d9f92867b6e615a50444a545f6a74808d988f82766a605447382e23170c000000121f2c3945525f6c7885929faba194877a6e6154473b2e21202a36424d57616c74818e95a0a89e938c7f736c74808d97a29f93877c6f62584e43372b1e1308000000000000000000000815222e3b4855616e7b8896a0acafa3998c7f72665b5042392e22190e0500000000000000000000000000000007131d28313d46535f696e77716c65605b53504941382d22170b0000000814212e3b4754616e7a87939facafa3998c7f72675d51453b2f261b1206000000000000000000000000000000071018242f3944505b66727e8b99a3aeac9f9285796d6053463a2d2013080000091623303c4956636f7c8996a2afa69a8d8073675a4d403025191a1e21272e343f46525e6873808c99a3abadb3a89c8f8275685e52463c3128201d19191e2027303944505b656c7675716d68666260584e43372b1f130600000000000000000006131f2c3946525f6c7985929facb8a79c918c8b8b8b8b8b8b8b8b8b8b8b8b8b8c8d8e909298999da0a7aaaca49f99928d837c706b625a50483e342b21170d0300000000000000030f1b27323d4754606d7a85929facaca1968a7d7063574d42362a1c110600000000000000000000000000000004101c2934404b55626e7b88949fabac9f92867a6d6054473d32271b0f030000000000000000010b151f29333b454d565d676d747c848c91969da0a7a9aca8a9a19e9c9b9a9a999a9a9b9d9fa2a9a6aaa9a7a09d99928e89827c746d686059504a423930281f160c01000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54606a727f8b929fa3abaca49f98928e8b8887868687898b7f7266594c3f3326190c00000000000000000009131d272f373c40414646464646464642413d3730271e0e050000000000000000000000000000000000000000000000030d1d262e363c3f414646464646464641403c372f271d13090000000000000000000000000000000000030b141b22272f34383a3e4144454646464646463f3e3a352e251c12070000131f2c3946525f6c7985929faca295887b6f6255483c2f22151c28333f4a545f6a73808d96a1aca2978e81756b6155626f7c8995a2ac9f9386796c605346392d2013000004101c2934404b55636f7c899493877c6f62594f4754606a74808d95a09892877e766f6c6566656566666d7179818e939d968e81756c61554b4e58616e7b869294897c6f62544a3f34281c100300000004101c2934404b55636f7c899493877c6f62594f433f4c5966727f8c999e9184776b5e51443846525e68727f8b959f958b7f72695e53483e424e58616e7b869294897c6f62544a3f34281c10030000111e2b3844515e6b7784919eaaa295887c6f6255493c2f2428323a46525e69707e8a939da8a0958e81776c606d7a85929fa49a8f82756a5f53473a2f24190d010000000000000000000c1825323f4b5865727e8b98a8b2ac9f92867a6e61544a3f30271d100700000000000000000000000000000000010c161f2a36424d575f616a64605b535049443f382f261b11060000030f1b27333f495364717e8b9aa4afac9f92867a6e61554b4033291d140a000000000000000000000000000000000007121d28333f4a54616d7a86929facaea298897d706356493d2f24190d01000916222f3c4955626f7c8895aab4a79b8e817468564c41362a24201d191c232a36414c56616e7a86929facb9b3a9978a7e7164564c41342a1f161d1d1d1d151e27333f49535b606a6864615e5655544e463c32271b0f0300000000000000000006131f2c3946525f6c7985929facb2a5988c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80818386888c91959c9ea6acaba39f9591867d716c625a50463d33291f140900000000000000000a16202c3945515d6774818e9aa7b1a89b8f8275695e5246382e23170b00000000000000000000000000000006131f2c3845515c6774808d9aa6b0a79b8e8174685d5245392b21160a00000000000000000007121d27313b454d575e686d79808791959ea1a8acaaa29f9b979791908e8d8d8d8d8e8f909297979a9ea0a8ababa39f9b948f87817a706b605b544b433a31281d1307000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000001040707121f2c3844505c666f7c87929fa4afaaa39a938d86817e7b7a797a7a7c7e7d6f6356493c302316090000000000000000030f1a252f3941484d4e535353535353534f4d4942393020170d02000000000000000000000000000000000000000000010b151f2e3840474c4d535353535353534e4d4841392f251a0f03000000000000000000000000000000030c151d262d33394045474a4e51525353535353534c4b463f372e23180d0200131f2c3946525f6c7985929faca295887b6f6255483c2f221a242b3844505b666f7c87929fa8a69f92857a6e615956626f7c8995a2ac9f9386796c605346392d2013000006131f2c3845515c6775818e9b8f82756a5f53474d57626f7c87939f9f92867d716c62605b535858545c60676d77818e959e938a7e71675d5146525e6974818d9a8e8174665c5044382c1f120600000006131f2c3845515c6775818e9b8f82756a5f53473d3f4c5966727f8c999e9184776b5e5144424e58616d7a85929f999083786c60574d42363c46525e6974818d9a8e8174665c5044382c1f12060000101d293643505c6976838f9ca9a4978b7e7164564c413529303a44505a616e7b85929ea5a3989183796d655d6873808d98a39f93877c6f62564c4135291d1104000000000000000004101d2935404b556875828f9ba8b5a99c908376685e5242382d1e150b000000000000000000000000000000000000040d1a26313b454d53555d57535049443f38332d261d140a00000005121f2b3744505b6575818e9bacb6a99c8f8276685e5243392f21170b020000000000000000000000000000000000010b17222d3846525d6875828f9ca8b4aa9a8d807367564c4135291d1104000814212e3b4754616e7a8798a2aeaa9d908377685e52463c352f2c2924272625303a46525e6876828f9ca9b6ada197877b6e6154483b302a2a2a2a2a2a2a2a2a222d38414950535d5b5854524c4947433c342b20150a0000000000000000000006131f2c3946525f6c7985929facada093877a7272727272727272727272727273737477797c8084898f949da0a7afa7a09892877e716c61584e453b30251a0d040000000000000004111d2935414b55626f7c88959fabac9f92877b6e61544a3f34281c100300000000000000000000000000000714202d3a4753606d7985929eabaca095897c6f63564c413529190f040000000000000000040e18242f39434d575e696e7a828d9399a0a8ada8a19e98928e8a878583818180808081828385878a8d9196999ea1a9aca69f99928d847d736c665c554b433a2f24180d010000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000000000000000000000000000000000000000206080d1113141d2935404b55606d78839099a3aeaba3989288817a75716f6d6d6d6e6f716f6b6054483b2f22150900000000000000000814202b37414b53595b606060606060605c59544b4232291f140900000000000000000000000000000000000000000007121d2731404a52585a606060606060605b59534b41372b2014080000000000000000000000000000000b151e272f383f444b5153575b5d5e5f6060606060595751493f352a1e120600131f2c3946525f6c7985929faca295887b6f6255483c2f221f2a36424d57606c78839099a3ab9f948b7e71685e5256626f7c8995a2ac9f9386796c605346392d201300000714202d3a4753606d79859296897c6f63584e46535f6975828f9a9f948b7f726b615a5350494b4b4b51555d656d78839099999184796d6053474d56616e7b88959285796d6053463a2d2013070000000714202d3a4753606d79859296897c6f63584e43353f4c5966727f8c999e9184776b5e513f4a54606a74818e979f92877c6f665b50453b3136424d56616e7b88959285796d6053463a2d20130700000d1a2633404d596673808c99a9a79b8e8174685d52453b3136414c56616c75828f97a2a59f92867c6f675d56616e7a86929fa49a8e8174685d5245392c20150a000000000000000006131f2c3845515d677884919eabb6ac998c7f7266564c412f261c0c030000000000000000000000000000000000000009141f29333b424648504a46443f38332d27221b140b020000000613202d394653606c7885929eabb3a9988b7f7265564c4131271d0f050000000000000000000000000000000000000006111c2935414c5665727f8b98aab4aa9d918477685d5245392c201306000714202d3a46525e697885929fabac9f92867a6e61584e45403a39352f3433333236414c566673808c99a6b3ab9e928578695e53463a3737373737373737373737372f383f4446504f4b4746413c3b37322b2620180f0600000000000000000006131f2c3946525f6c7985929facada093877a6d656565656565656565656565666768666d6f73777c828990959fa4acaaa299928b7e716a60574d42362a1f160c01000000000000010d18242f3a47535f6a7683909da9afa3998c7f73665c5044382b1f14090a0a0a0a0a0a0a0a0a0a0a0a0a0a121f2b37434e5864717e8b97a2adaa9d9083776b6054443a2f2419070000000000000000020c16202935404b555e696e7b8390949fa4abaaa29f96918b86817e7b78767574737374747577787b7d8084888d92979ea1a8aba39f96918780786d675d554b4035291d11040000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214191d2021242c3945515d67727f8b95a0abafa39992867d746d6864626160606162656360594f43382c1f130700000000000000000c1824303c48535d64686c6c6c6c6c6c6c68655d54443b3025190e0000000000000000000000000000000000000000000c18232f3943525c64676c6c6c6c6c6c6c68645d53483c3024180c000000000000000000000000000007121d273039414950555c6064676a6b6c6c6c6c6c6c66635b51463a2f22160a00131f2c3946525f6c7985929faca295887b6f6255483c2f2228313a46525e69727f8b959faba3999082776c60564c56626f7c8995a2ac9f9386796c605346392d201300000a1724313d4a5764707d8a989184786c6053464855616e7b88949e9c9083786c60595046443f3f3f40454b535c666e7b878e8a86827c6f62554846535f6976839097897d7063564a3d2f23180c0000000a1724313d4a5764707d8a989184786c6053463c313f4c5966727f8c999e9184776b5e5144505b666f7c87939f968d80736a5f544a3f3329303b46535f6976839097897d7063564a3d2f23180c00000a1723303d4a5663707d8997a1ac9f92867a6d60574d43393946525e68717e8a949ea89e938b7f726a5f55525e6874818d9aa49f92867a6d6054473d32271b0f03000000000000000714202d3a4753606d7a86939facafa49a897c6f6356493c3023140a0000000000000000000000000000000000000000030d17212931363a3b443e3937332d27221b17110a02000000000815222e3b4855616e7b8897a1adada197887b6e6255483b3022150b0000000000000000000000000000000000000000000d1924303c4855626f7b8898a2aeaca095877a6d6054473a2d2114070005111e2a36424d566976828f9caaafa3998c80736a5f58514b4745414240403f3f3f3e4a5764717d8a97a4b0a99c8f827669574d4244444444444444444444444444444444444444444444444444443b3a37312a21180e03000000000000000006131f2c3946525f6c7985929facada093877a6d605858585858585858585858595a545c6062666b6f767c838d939aa3ababa39f92867c6f695e52463e31281d13070000000000000007131d2b37434e5864717e8b97a2adab9e9184786d6053463b31251a16161616161616161616161616161616212e3a47535f6a7683909ca9aea2988b7f7265594f4332281e1308000000000000000008131e28323a45515d676e7b8491959fa6afa7a098928c847f7a75716e6969686767666767686a696e7173777b80858b91969fa2aaa9a199938c81796d675d5145392c2013060000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000000000000000000000000000000060c10151a1e2124292c2d30333f4a54606d7985929ea7b1a79f92877d706b615e565554535354565856544f473d32271b0f0300000000000000000e1a2734404d59646f7479797979797979756f65564d42362a1c11060000000000000000000000000000000000000004101c2934404b55646e7479797979797979746f64594d4034271a0e00000000000000000000000000040d18232e39434b535b60676d71747778797979797979726d63574b3e3225180c00131f2c3946525f6c7985929faca295887b6f6255483c2f242f3a43505a616e7b86929fa7a89f92867c6e655b504956626f7c8995a2ac9f9386796c605346392d20130004111d2935414c566874818e9a8d8073655b50444b5566737f8c99a096897d70665b50473e37332d2e3439414a545f697380827e7a766f6a5f5347424d5765727f8c988d817467554b4034291c10040004111d2935414c566874818e9a8d8073655b504437333f4c5966727f8c999e9184776b5e514c56606c7883909a9e9184796d60584e42382d212a36424d5765727f8c988d817467554b4034291c1004000713202d3a4653606d7985929eaaa2988c7f72695f554b43424f59616d7a85929ea6a1968f81756d62584e4c56616e7b87939fa2988b7f7265584e43372b1f1306000000000000000915222f3c4855626f7b889aa4afac9f93867a6d6054473a2d211407000000000000000000000000000000000000000000060f171f262a2d2e37312d2b27221b17110b060000000000000a1724303d4a5763707d8a96a9b3ab9e928578695f53473a2e2114030000000000000000000000000000000000000000000813202d394653606c7985929facb1a795897c6f6256493c2f23160900020e1925303f4b5865727e8b98a2aeab9f92867c6f6a605d5554524c4e4d4d4c4c4b4b4b5663707c8996a3afa79b8e8174685b505050505050505050505050505050505050505050505050505050504847433c332a201509000000000000000006131f2c3946525f6c7985929facada093877a6d60544c4c4c4c4c4c4c4c4c4c4c4d4a5053555960636a6f7980889299a3abaea39891857b6e615a50433a2f24180d00000000000000010f1b26323c4753606d7985929fabada1968a7d7063574d42362a23232323232323232323232323232323232934404b55626e7b88949fabac9f92867a6d6054473d3221160c0100000000000000010d1925303a44505a606d79839096a0a8b0a69e9591867f79726d6764615e575b5a5a5a5a5b5c575e6164676a6e73797e848c92989fa7aba49f938e82796d6053473a2d2014070000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000000000000000000000000000000030a11171c1f262b2e2f35393a3d4044505b66727f8b97a1adaca0958c7f736b6159524c4847464747494b4948433d352b21160a0000000000000000000e1b2835414e5b687481868686868686868175695e5246382d22170b0000000000000000000000000000000000000006131f2c3845515c677480868686868686868174685b4e4135281b0e000000000000000000000000010c161f2834404b555c656c71797d8184858686868686867f7266594c3f3326190c00131f2c3946525f6c7985929faca295887b6f6255483c2f2935414c55616c75828f98a2aca0968c80736a5f53494956626f7c8995a2ac9f9386796c605346392d2013000713202c3945525d6877849199897c6f62534945515d677683909d9e9184786c60544a3f352b272223282f38424d57636e7375716d68625f584e433b4854616e7b8797908477675c5145382c1f1306000713202c3945525d6877849199897c6f6253493f33333f4c5966727f8c999e9184776b5e53535d68717e8b959e93897d70675d51463c2f261c26313b4854616e7b8797908477675c5145382c1f13060006131f2c3845515c6773808c98a2aa9f92867b6e675d554c4a54616b75818e97a1a59e91847a6d605b514646535f697683909caa9d9083776a6054473b2e221509000000000000000b1724313e4a5764717d8a97acb6aa9e918477675d5145392c20130600000000000000000000000000000000000000000000060d141a1e21222a24201f1b17110b0600000000000000000c1926323f4c5965727f8c98a5b2a99c8f837669574d42372b1e120600000000000000000000000000000000000000000006121f2b3844505b667783909daab1a4978b7e7164584b3e3125180b00000914212d3a4754606d7a85929fa7aea29891847c726d6763605d565b5a59595858585857626f7c8995a2afa79a8d8074675d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d55534e463c31261a0f020000000000000006131f2c3946525f6c7985929facada093877a6d6054473f3f3f3f3f3f3f3f3f40403f4446494f545860676d737e879299a3aeaaa1978f82766c61554b4135291d1207000000000000000a151f2c3845515d6774808d9aa6b0a89c8f8275695e5346382e3030303030303030303030303030303030303845515c6774808d9aa6b0a79b8e8174685d5245392c201304000000000000000005111d2935414c56626d75818e959fa8b0a69e948f837b726d66605d5554534d4e4e4d4d4d4e4f4d525457585f62666d71797f8690959ea5afa59e948d8073665a4d4033271a0d0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000000000000000000000003090c151c23282c31373a3b4145474a4d4e53606c7884919ea9b1a79d9083786c60594f46413c3a3a3a3b3c3e3c3b38322b23190f040000000000000000000916232f3c4956626f7c89959393939392867b6e61544a3f33281c0f030000000000000000000000000000000000000714202d3a4753606d7985929393939395897c6f6356493c3023160900000000000000000000000007131d28313a45515c676d777e848a8e909192999393938c7f7266594c3f3326190c00131f2c3946525f6c7985929faca295887b6f6255483c2f303845515d67707d8a939eaaa49a9184796d60584e414956626f7c8995a2ac9f9386796c605346392d2013000714212d3a4754606d7a87969286796d6053464753606d7a86939f998d8073655b5042382d231b17181d26303b45525c63666864615d56534e463c3a46535e697885919286796d6053473a2d201407000714212d3a4754606d7a87969286796d6053463a2d333f4c5966727f8c999e9184776b606060606d7a85929e978e81746b60554b40342a1d14212d3a46535e697885919286796d6053473a2d2014070004101c2834404b55616e7a86929fa6a2989083796d675e56515c66707d8a939ea99e938a7d70685d52493f424d5765717e8b98a3a095897c6f6256493c31261a0e020000000000000c1926323f4c5965727f8c98a5b2a99c8f837669554b4135291d1104000000000000000000000000000000000000000000000003090e1214151d1713120f0b06000000000000000000000e1b2834414e5b6774818e9aa7b3a79a8d8074675a4d4131261a0e02000000000000000000000000000000000000000000030f1c28333f4a546875818e9ba8b3a6998d8073665a4d4033271a0d00000713202c3945525d68737f8c95a0a8aaa19691867f7974706d6869686766666565656464646f7c8995a2afa6998c7f736a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a625f584e43372b1f12060000000000000006131f2c3946525f6c7985929facada093877a6d6054473a3232323232323232332e34383a3d43484e555c606c717e87929fa5afa99f948a7e71675d5145392e23180c0000000000000004101d2935404b55626e7b88949fabac9f93877b6e61544a3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4753606d7985929eabaca095897c6f63564c4135291d110400000000000000000713202d3946525e68717e8b939ea7b1a79e948f82796e69605c54514b484642424140404141424246484a4e53545c60666d727b838f939ea8afa69a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000000000000000000000000050d141a1e262e34383c4247484c525457595b5563707d8996a0acab9f95897d70665b504745403a37322d2e2f32302f2c2721191007000000000000000000000915222e3b4854606a7783909daa9fa3998c7f73665b5044382b1f1409000000000000000000000000000000000006121f2b37434e5864717e8a97a29f9f9d9083776b6054483b2f2215090000000000000000000000010d18242f3a43515b606d79818b91969a9d9e9fa39f9f998c7f7266594c3f3326190c00131f2c3946525f6c7985929faca295887b6f6255483c2e38424e58606d7a84919ea6a99f93887d70675c51463c4956626f7c8995a2ac9f9386796c605346392d2013000a1623303d495663707d8996908377665c51454956626f7c8999a4978a7d706453493f2f261c0f0b0b151e2a33404a5257595b5754524c47433c3436424d576976828f99897c6f6256493c2f231609000a1623303d495663707d8996908377665c5145382c333f4c5966727f8c999e9184776d6d6d6d6d74808d979e92857a6d61594f433b322920171e2a36424d576976828f99897c6f6256493c2f23160900000c18232e3946525e68727f8b949fa89f958f82796e68615a606d7884919ea5a1978e81756b61564c41373b4754606d7a86929fa79a8d807467574d42372b1e12060000000000000d192633404c5966737f8c99a6b2a89b8e8175685b4e422f24180d010000000000000000000000000000000000000000000000000002050708110b060503000000000000000000000000101c2936434f5c6976828f9ca9b2a5998c7f7266594c3f3326190900000000000000000000000000000000000000000000000b17222d404d5a6773808d9aa6b3a89b8e8175685b4f4235281c0f000004111d2935414c56606d79839096a0a7a8a198928c85807d7a787675737372727271717171707c8995a2afa5988c7f777777777777777777777777777777777777777777777777777777777777776e6a5f53473a2e2114080000000000000006131f2c3946525f6c7985929facada093877a6d6054473a2d252525252525252623282c2d32383d434b515a616c727f8b939ea9b0a69e91847a6d60544b4034281c1004000000000000000c18242f3947535f6a7683909ca9afa4998c8073665c504949494949494949494949494949494949494949494e5864717e8b97a2adaa9d9083776b6054443a2f24190d010000000000000006121f2b37434e58616d7a85929ea5afa9a0958f82796d675f57514a45403b3a3631343433343430363a3b3e43474b51545c60696e79818f96a0aca79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000000000000000000080f171f252a30383f44464d5355565d60636668696775818e9ba8b2aa9d9083776b605b5353514b47433c3731292423221f1b160f07000000000000000000000007131f2c38434e5865727e8b98a2aeab9e9184786c6053463b30251a0e00000000000000000000000000000000000814212e3a47535f6a7683909ca9aea2988b7f7265594f43382c1f1307000000000000000000000004111d2935414b55626d75818e939ea1a8aaa29f9c9998988c7f7266594c3f3326190c00131f2c3946525f6c7985929faca295887b6f6255483c343f4a54606a74808d96a1ada1978e81746b60554b403c4956626f7c8995a2ac9f9386796c605346392d2013000c1925323f4c5865727f8b988e817467544b404b5864717e8b97a398877b6e6154473b2d21140a00030c18212e3840474b4d4f4b4746413a37322a31404d596673808c988b7e7165584b3e3225180b000c1925323f4c5865727f8b988e817467544b403428333f4c5966727f8c999e9184797a7a7a7a7a7c87929f978b7e7168605b544d443b32291d1a2531404d596673808c988b7e7165584b3e3225180b000007121d2a36414c56606c78829096a1a79e948f837a716c6268727f8c96a0a69e91857a6d61594f443a303945525d6875828f9bac9e918477695f53473a2e2114080000000000000d1a2734404d5a6773808d9aa6b3a79a8d8074675a4d4134271a070000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000101d2a3643505d697683909ca9b1a4978a7e7164574b3e3124180b0000000000000000000000000000000000000000000000061926323f4c5965727f8c98a5b2a89c8f8275695c4f4236291c0f0000010d19242f3a45515c666e7b8490959fa3aaa29f97928d898784838180807f7f7e7e7e7e7d7d7f8c98a5b2ab9e9184838383838383838383838383838383838383838383838383838383838383837c6e6255483b2f2215080000000000000006131f2c3946525f6c7985929facada093877a6d6054473a2d2119191919191919171c1f20272c30394045505a626d74818e97a1adada1968c7f73665c5145382c1f14090000000000000007121d2b37434e5864717e8a97a1adab9e9184796d6056565656565656565656565656565656565656565656565f6a7683909ca9aea2988b7f7265594f4332281e130800000000000000000815212e3a47535f6a74818e97a2adada2979083796d675d554d444039352f2d2a252727272728252a2d2e31373940454b51575f676d7884919eaaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000000000000000000020a121a212931363e424a5053575f6266686d70737576777986929facb1a4988b7e716e6c6564605d55534e47433c352f281f180f0a04000000000000000000000000030f1b27323d4754606d7a85929facaca1968a7d7063574d42362a1c110600000000000000000000000000000004101c2934404b55626e7b88949fabac9f92867a6d6054473d32271b0f0300000000000000000000000613202c3945515d67727f8b939ea5ada49d98928f8d8c8b8b7f7266594c3f3326190c00131f2c3946525f6c7985929faca295887b6f6255483c3844505c666f7c87939fa9a69e92857a6d60594f43393c4956626f7c8995a2ac9f9386796c605346392d2013000d1a2733404d5a6673808d998c7f7366594c404c5966727f8c999f928579695e52463a2d2014020000060f1c262e353b3f40423e3a3935302b2625323e4b5865717e8b988c7f7266594c3f3326190c000d1a2733404d5a6673808d998c7f7366594c402e23333f4c5966727f8c99a096918686868686868892999e92857c78716c665e564d443b2f261b25323e4b5865717e8b988c7f7266594c3f3326190c0000000d1925303b44505b666e7b849197a1a69e9590857e756f6d7a85929fa89f948a7e71685d52473e322935414c5664717e8a9aa4a096887b6e6255483b2f2215080000000000000e1b2734414e5a6774818d9aa7b3a69a8d8073675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2a3744515d6a7783909daab0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4b1a99c908376695d5043362a1d1000000008131e2834404b545e696e7b838d92999fa2a9a29e9a9696918f8e8d8c8c8b8b8b8b8a8a8a8c919ba7b4ada19691909090909090909090909090909090909090909090909090909090909090887c6f6255493c2f2216090000000000000006131f2c3946525f6c7985929facada093877a6d6054473a2d21140c0c0c0c0c060c1012131b1e272e343e47515b606d7985919ea7b1a99e9185796d6053463b31251a0e02000000000000010f1a26313c4653606d7985929eacada1968a7d70646363636363636363636363636363636363636363636363636e7b88949fabac9f92867a6d6054473d3221160c010000000000000005111d2935414c56626f7c87939fa9b0a69f92857b6e675d554b433c342e2924211e1a1b1a1a1a1b1a1e2021262b2e343940454d555c667784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000000000000020b141c242c333b424650545c6065696e73777a7d80818384869298a2aeb3a69a8d807d7b7975716d67625f58534e454039312a211a1108000000000000000000000000000a16202c3945515d6774818e9aa7b1a89b8f8275695e5246382e23170b00000000000000000000000000000006131f2c3845515c6774808d9aa6b0a79b8e8174685d5245392b21160a0000000000000000000000000714212d3a4754606d7a85929fa6ada39c928d8682807f7f7f7c6f6255493c2f22160900131f2c3946525f6c7985929faca295887b6f6255483c424d57606d78839099a4aa9e948a7e71685d52473d303c4956626f7c8995a2ac9f9386796c605346392d2013000e1b2734414e5a6774818d988b7e7265584b404d5a6773808d9a9e9185786b574d42362a1e11050000000a131c242a2f323335312e2d29241e1b24313e4a5764717d8a978d8073665a4d4033271a0d000e1b2734414e5a6774818d988b7e7265584b3f3226333f4c5966727f8c99a8a09e939393939393959fa3a1979289847e786e685e564d41382d2224313e4a5764717d8a978d8073665a4d4033271a0d00000008141e28333f4a545e696e7b8591969fa69f97918a827c76808d97a2a3998f82766c61564c41352c242f3a4754616d7a87939fa1988c7f7265594c3f3226190c0000000000000e1b2835414e5b6874818e9ba7b3a6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2b3844515e6b7784919eaaafa396897c706356493d3023160a00000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1aa9d9083776a5d5044372a1d11000000010c18232e39424d575e696e7980878e92989b9ea1a9a8a19e9c9b9a999998989897979797989ba3adb8b2a8a19e9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d95887b6e6255483b2f2215080000000000000006131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000003060a0c151d2328353f45515d67717e8b95a0acada1978b7e7164574d42362a1e12050000000000000009151f2c3845515c6673808d9aa4afa99c8f82757070707070707070707070707070707070707070707070707074808d9aa6b0a79b8e8174685d5245392c20130400000000000000000713202d3946525e6874818e9aa4afab9f948b7e71695e554b433a3128231c1814120e090d0d0e090e1214151a1d23282e343c434b546a7784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000000000000000000020b141c262e363e454d535a61666d71767b8084868a8c8e90919298a2aab4b5a89d928d8a8885817e7a756f6a625f58514b433c332c231a120800000000000000000000000004111d2935414b55626f7c88959fabac9f92877b6e61544a3f34281c100300000000000000000000000000000714202d3a4753606d7985929eabaca095897c6f63564c413529190f04000000000000000000000004101c2934404b5565727f8b98a2aea79c918c807a75737272726f6a5f54473b2e22150800131f2c3946525f6c7985929faca295887b6f6255483c46535f69727f8c95a0aba2988f82766c61564c41352f3c4956626f7c8995a2ac9f9386796c605346392d2013000f1b2835424e5b6875818e978a7e7164574b414d5a6774808d9a9d9184776a5e514430251a0e02000000010a12191f232626282421201d19131723303d4a5663707d89968d8174675a4e4134271b0e000f1b2835424e5b6875818e978a7e7164574b3e3126333f4c5966727f8c99a8a09393939393939393939496999e96918b827a6e685e53493f332723303d4a5663707d89968d8174675a4e4134271b0e000000020b17222d38424d575f696f7c8490949fa3a19e948f888287929fa99f92877c6e625a50443a3028232d3946525e687783909997928e8376695c504336291d100300000000000e1b2835414e5b6874818e9ba7b3a6998d8073665a4d4033271a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2b3845525e6b7885919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0aa9e9184776b5e5144382b1e110000000007121d27303b454d575e676d747b81868b8e929796989a9b9c9d9d9d9e9e9e9e9e9f9f9f9fa4acb6c0b6aea9a79f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa8aaaaaaaaab94887b6e6155483b2e2215080000000000000006131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000030b1218232935414b55606c7883909da9b3a99d908377695e53463a2d2114060000000000000004101c2834404b54616e7b87939facac9f93877d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d85929fabaca095897c6f63564c4135291d110400000000000000000714212e3a4754616d7a86929facb0a69c9082766c62574d433930281f18120d07050c111517181c1c1c1c1c1c1c181d23283144515d6a7784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000000000000000a141c262e38404850575e616c71787e83888d90939a999b9c9e9fa2aab4b1b2aea49d9a9797928e8b86817c756f6a605d554e463e352c241a11080000000000000000000000010d18242f3a47535f6a7683909da9afa3998c7f73665c5044382b1f14090a0a0a0a0a0a0a0a0a0a0a0a0a0a121f2b37434e5864717e8b97a2adaa9d9083776b6054443a2f24190700000000000000000000000006131f2c3845515c677683909daaaca0958c7f746d6866656565625f584e43372b1f130600131f2c3946525f6c7985929faca295887b6f62554844505a616e7b86929fa7a79f92867b6e615a50443a302f3c4956626f7c8995a2ac9f9386796c605346392d2013000f1c2935424f5c6875828f978a7d7064574a414e5a6774818d9a9d9184776a5e51442f24180d0100000000040c13181d2020201d1814120f0916232f3c4956626f7c89958e8175685b4e4235281b0f000f1c2935424f5c6875828f978a7d7064574a3d3126333f4c5966727f8c99a09689868686868686868687898d92989e948f847a6e655b5044372b232f3c4956626f7c89958e8175685b4e4235281b0f0000000006111c262f3b454d575f6a6f7a828d92999fa69e9c948f9299a3a2978d80746a5f534b454039342e2a36414c566673808d8c8985817e7064574a3d3124170a0000000000000e1b2734414e5a6774818d9aa7b3a69a8d8073675a4d4034271a0d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2b3845525e6b7884919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0aa9d9184776a5e5144372b1e1100000000000b151e29333b454d555d60696e747a7e8285888a8c8d8e8f9090919191919192929292939aa4afbbaea49d9a93939393939393939393939393939393939393939393939b9ea5afafa499877a6d6154473a2e2114070000000000000003131f2c3946525f6c7985929facada093877a6d6054473a2d21140c0c0c0c0c0c0c0c07060400071118242f3a44505b65717e8b97a2adab9f95877b6e6154483b2e23170c00000000000000000c18232e3946535f6976828f9ca9afa499938a89898989898989898989898989898989898989898989898989899297a2adaa9d9084776b6054443a2f24190d010000000000000005111e2a36424d5666727f8c98a3aeab9f94897c6f635a50453b31271e160d07000911181d212425292929292929292929292a3744515d6a7784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000000000000000009121c262e38404a525a61696e767e848b9095999d9fa4aca8a9a8a6a5a4a4a4a5a6a8aaa6a9a19e9b98928e88827c736d675f584f473e362c231a1007000000000000000000000007131d2b37434e5864717e8b97a2adab9e9184786d6053463b31251a16161616161616161616161616161616212e3a47535f6a7683909ca9aea2988b7f7265594f4332281e13080000000000000000000000000714202d3a4753606d7986929facac9d9083786c605d5659585855544e463c32261b0f0300131f2c3946525f6c7985929faca295887b6f6255484c56616c76828f98a2aba0958c7f72695e53483e32282f3c4956626f7c8995a2ac9f9386796c605346392d2013000f1b2835424e5b6875818e978a7e7164574b404d5a6773808d9a9e9184786b554b4035291d1004000000080d161d24292c2d2c2924211f1a151723303d4a5663707d89968d8174675a4e4134271b0e000f1b2835424e5b6875818e978a7e7164574b3e3126333f4c5966727f8c999e918479797979797979797a7c808590959f969082776c6053463c3126303d4a5663707d89968d8174675a4e4134271b0e00000000000a141d29333c454e585f686d78808790959ea0a69e9c9fa3ab9f92857a6d65605c54514b443f3830303d495663707d83807c7874706c6155493c3023160a0000000000000d1a2734404d5a6773808d9aa6b3a79a8d8174675a4e4134271b090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2b3844515e6b7784919eaab0a396897d7063564a3d3023170a00000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a99d9083766a5d5043372a1d100000000000030c172129333b434b51575f62686d7175787b7d7f808283838484848485858585858687939facb9a99d928d86868686868686868686868686868686868686868686868e939eaaac9f9386796c605346392d2013060000000000040a0f131f2c3946525f6c7985929facada093877a6d6054473a2d211919191919191919191313100c0707131d27333f4953606d7985929fabb1a7988b7e7265544a3f34281c10030000000000000007121d2a36424d5764707d8a96a1adaba49f9796969696969696969696969696969696969696969696969696969fa2a9aea2988b7f7265594f4332281e130800000000000000000714202d3a46525e697784909daab4aa9c9083766b6054483f33291f150c040009121b22292e313236363636363636363636363744515d6a7784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000000000006101b242e38404a525c636c717b838a91969d9fa7aaacaba39f9d9b999897979898999b9d9fa3ababaaa29f9b948f8780796e6a615950483e352c22180d0400000000000000000000010f1b26323c4753606d7985929fabada1968a7d7063574d42362a23232323232323232323232323232323232934404b55626e7b88949fabac9f92867a6d6054473d3221160c010000000000000000000000000916232f3c4956626f7c8999a3aea49a8b7e71665b524c4c4c4c4947433c342a20150a0000131f2c3946525f6c7985929faca295887b6f625548525d68717e8a949faaa4999083786d60574d42362c232f3c4956626f7c8995a2ac9f9386796c605346392d2013000e1b2734414e5a6774818d988b7f7265584c404d596673808c999f928578675d5145392c20130600000811191f282f35393a39352f2e2b26201824313e4a5764717d8a978d8073665a4d4033271a0d000e1b2734414e5a6774818d988b7f7265584c3f3226333f4c5966727f8c999e9184776c6c6c6c6c666c6d6f737b8390969f948b7e7165574d42372b313e4a5764717d8a978d8073665a4d4033271a0d0000000000020b17202a333c464e565e666d737c838b91969ea1a9acafaa9d90837d77716d66605d55504a423d353b4854606b7077736f6c656461594f44392d2014080000000000000d192633404c5966737f8c99a6b2a89b8f8275685c4f4230251a0e0200000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000111e2a3744515d6a7784909daab0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000c1825323f4b5865727e8b98a5b1a99c8f8276695c504336291d100000000000040d161e2429313940454d53565d606468696e707274757676777777787878787879797c8995a2afa79a8d807979797979797979797979797979797979797979797979818e9ba8ab9e928578665b5044382b1f120600000000070e151b1f222c3946525f6c7985929facada093877a6d6054473a2d26262626262626262626201f1c18120b0b17222d3845515d6774818e9aabb5a89c8f8275665c5044382c1f120600000000000000000e1a26313b4653606d7984919eabb5afaca3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3abadb3ac9f92867a6d6054473d3221160c0100000000000000000814212e3b4754616e7b8795a0acaea2988a7e7164594f44362d21170d030006111b242d343a3d3e43434343434343434343434344515d6a7784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000000000000030c18222d36404a525c646e737e8590949da0a8abaaa29f9b9992908e8c8b8b8a8b8b8c8e9092999a9ea1a9aca69e99928d837c706b615a50473e342a1f160c01000000000000000000000a151f2c3845515d6774808d9aa6b0a89c8f8275695e5346382e3030303030303030303030303030303030303845515c6774808d9aa6b0a79b8e8174685d5245392c201304000000000000000000000000000a1724313d4a5764707d8a97abac9f93867a6d61544a413f3f3f3c3b37322a22190e040000131f2c3946525f6c7985929faca295887b6f62554f59606d7a85929ea6a89f93877c6f665c50453b3124232f3c4956626f7c8995a2ac9f9386796c605346392d2013000d1a2733404d5a6673808d998c7f7366594c404b5865727e8b989f93867a6d6053473a2d20140900030d19232b313a40454745403b3a37312a2125323e4b5865717e8b988c7f7266594c3f3326190c000d1a2733404d5a6673808d998c7f7366594c402e23333f4c5966727f8c999e9184776b606060605b606163696e7a84919e9d908377695f53463a2d323e4b5865717e8b988c7f7266594c3f3326190c000000000000050e18212a343c444c545c606a6f787e848b9297a1adb8aca0959089837e79726d67605c544f45403a444f5960636a6662605b53554f473e33281c10040000000000000b1825313e4b5864717e8b97a4b1a99d9083766a574d42362a1e1105000000000000000000000000000000000000000000000003080c0e0e0f0b07070401000000000000000000000000101d2a3643505d697683909ca9b1a5988b7e7265584b3f3225180700000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685c4f4235291c0f00000000010c161f282f35393a3e3f42474c525458575f6163656768696a6a6a6b6b6b6b6b6c6c6f7c8995a2afa89b8e82756c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c7783909daaa99d9083766a544a3f33281c0f0300000007101920262b2e2f3946525f6c7985929facada093877a6d6054473a33333333333333333333332d2c28231d150c111b2935404b5564717d8a99a3afac9f9285796d6053463a2d201307000000000000000009141f2c3844505c6673808c99a3afbbb9b1acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa7a9afb8bab1a79b8e8174685d5245392c2013040000000000000000000b1825323e4b5865717e8b98a7b1ac9f9285796d6053473d32201b0f0500010c18222d363f454a4b4f4f4f4f4f4f4f4f4f4f4f4f4f515d6a7784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000000000b151e2a343f48525c646e73808a92979fa6aca9a29f98928e8a868381807f7e7e7e7f80818386898d92979ea0a8aba39f9591867d716c61594f463c31281e13080000000000000000000004101d2935404b55626e7b88949fabac9f93877b6e61544a3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4753606d7985929eabaca095897c6f63564c4135291d1104000000000000000000000000000b1825313e4b5864717e8b97a4ab9e918478685e5242382f32322f2e2b2620191007000000131f2c3946525f6c7985929faca295887b6f625554606b74818e97a1ada1968d80746a60544a3f33291f232f3c4956626f7c8995a2ac9f9386796c605346392d2013000c1925323f4c5865727f8b988e817468554b404a5663707d8996a49a897c6f6356493c30251a0e090c151f2b353d434b5153514b4847433c332f2633404d596673808c988b7e7165584b3e3225180b000c1925323f4c5865727f8b988e817468554b403428333f4c5966727f8c999e9184776b5e53534a505354565e68727e8b9aa095887b6e6155483b2e33404d596673808c988b7e7165584b3e3225180b00000000000000060f18222a323a424b51585f666c71787e85929eabadaba7a09d95908b847f79726d666059514b433d474f54565d595653504949443e352c21170b000000000000000a1723303d4a5663707d8996aab4ab9f928578695e52463a2d20140700000000000000000000000000000000000000000001090f14181a1b1c181413110d0805010000000000000000000f1c2835424f5b6875818e9ba8b3a6998c807366594d402f23180c00000000000000000000000000000000000000000000010e1b2834414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e0000000008131e28313a4145474b4c4d4e4f5052504d535557595a5b5c5d5d5e5e5e5e5e5f5f626f7c8995a2afa99c908376655b60606060606060606060606060606060605e697885929faba79b8e8174685b4e412d22170b000000040e19222a32373b3c3f46525f6c7985929facada093877a6d6054473f3f3f3f3f3f3f3f3f3f3f3f3a38342e271e150c18242f3a4754606d7a86929facaea298887b6e6255483b2f221508000000000000000003101c28343f4a54616e7b87929facb9b1a7a0939393939393939393939393939393939393939393939b9ea5afb8aca095897c6f63564c4135291d1104000000000000000004101d2935404b556875828e9ba8b5a89b8f8275675d5145392c1f1309000005111d29343f485056585c5c5c5c5c5c5c5c5c5c5c5c5c5c5d6a7784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000000000007121d27303c46505a646e73808d929fa2a9aea59e97928c86817d7a77757372717171727375777a7d81858b91969fa3aba7a09892877e716b61584e433a2f24190c03000000000000000000000c18242f3947535f6a7683909ca9afa4998c8073665c504949494949494949494949494949494949494949494e5864717e8b97a2adaa9d9083776b6054443a2f24190d01000000000000000000000000000c1925323f4c5865727f8b98a5a99c8f827669564c412f26252522221f1b150e0700000000131f2c3946525f6c7985929faca295887b6f62555c666f7d88939fa9a59e9184796d60584e42382e2117232f3c4956626f7c8995a2ac9f9386796c605346392d2013000a1623303d495663707d8996908377675c51454754616e7a8796a1988b7f7265574d42362a201a19191e27313d474f555d605d5555534e4641382a36424d576976828f99897c6f6256493c2f231609000a1623303d495663707d8996908377675c5145382c333f4c5966727f8c999e9184776b5e51463f4446474d56616d7a87939f978a7e7164574b3e3136424d576976828f99897c6f6256493c2f23160900000000000000000610182029303940454e545b60666d7a85929fa9a19e989ea0a09d97918c857f78706b605d554e463d444849514d4946443f3839332c231a1005000000000000000815222e3b4855616e7b8898a2aeada297877b6e6154473b2e21140a0000000000000000000000000000000000000000030b131a20242728292521201d1913110d0802000000000000000d1a2734404d5a6773808d9aa6b3a89b8e817568554b4034291c100400000000000000000000000000000000000000000005121e2a36424d576976838f9ca9b2a5988c7f7265594c3f3226190c000000010d19242f3a434c525457595a5b5c5d5e5d5a54484a4c4d4f5050515151515252525663707d8996a3b0ab9e9285796c605353535353535353535353535353535354616e7b8798a2aeaa988c7f7265594c3f322619060000000a15202a343c4347494c4c525f6c7985929facada093877a6d60544c4c4c4c4c4c4c4c4c4c4c4c4c4645403930271d1213202c3945525d687783909daab4aa978a7d7064574a3d3124170a0000000000000000000c17232e3846525e6975828f9ca8b2aca095898686868686868686868686868686868686868686868e939ea9b4aa9d9084776b6054443a2f24190d01000000000000000006131f2c3845515d677884919eabb5ab988b7e7265554b4035291d100400000915212e3a45505a62656969696969696969696969696969696a7784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000c18232e39434e58626c73808d929ca4adaaa39f938e857f7a75706d67686665646465656668676d7074797e848c9299a1a9aaa29992877d706a5f554c4135291e150a0000000000000000000007121d2b37434e5864717e8a97a1adab9e9184796d6056565656565656565656565656565656565656565656565f6a7683909ca9aea2988b7f7265594f4332281e130800000000000000000000000000000c1925323f4c5865727f8b98a5a89b8e8275685b4f42302814191615130f0a040000000000131f2c3946525f6c7985929faca295887b6f6257606d7984919aa4a99e938a7d70675d51463c30261c16232f3c4956626f7c8995a2ac9f9386796c605346392d2013000714212d3a4754606d7a87969286796d60534646525e687884919e9c8f8275695e52463c332a262524293039434f5960676d6765625f58534a41363a46535f697885919286796d6053473a2d201407000714212d3a4754606d7a87969286796d6053463a2d333f4c5966727f8c999e9184776b5e51443338393b46525d687784919e998c7f7366594c40333a46535f697885919286796d6053473a2d201407000000000000000000060e171e272e343c424a505b66727f8c98a2a197918c91969d9fa19e97918b837d746d675f584f473d3b3d44403c3937332d2d28211a110800000000000000000613202d394653606c7985929facb3a9968a7d7063574a3d31261b0f01000000000000000000000000000000000000000b151d252b30343536312d2c2924201d19130c070100000000000c1925323f4c5865727f8b98abb5aa9d908477675c5145382c1f13060000000000000000000000000000000000000000000714212d3a46535f697885929fabb4aa968a7d7063574a3d3024170a00000004111d2935414c565d6064656668696a6b69665e54423f414243434444444545454a5764717d8a97a4b0ada297887b6f625548464646464646464646464646414c5665717e8b98aaaea298897c6f6256493c2f2316090000030f1b26323c464e54555959595f6c7985929facada093877a6d60595959595959595959595959595953514b43392e2318111d2935414c566875818e9ba8b2a5998c7f7266594c3f3326190c00000000000000000006111c2a36424d5763707d8a96a1acaa9d9083797979797979797979797979797979797979797979818e9ba7aea2988b7f7265594f4332281e13080000000000000000000714202d3a4753606d7986939facaea399887b6f6255483c2f24180c0000000b1724313d4a56626c71767676767676767676767676767676767784909daaa79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000004101c2834404b555f6a717e8b929da4aeaaa298928b817a736d6863605d5559585857585859555d6063676d717980879197a0a8aba39992867c6f675d51453d30261c1106000000000000000000010f1a26313c4653606d7985929eacada1968a7d70646363636363636363636363636363636363636363636363636e7b88949fabac9f92867a6d6054473d3221160c0100000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0908060300000000000000131f2c3946525f6c7985929faca195887b6e625f69737f8c95a0aca2978e81756b61554b40342b1e1516232f3c4956626f7c8995a2ac9f9386796c605346392d2013000713202c3945525d6877849199897c6f635349414d566774818e9a9f92877b6e61584e453c3631322f353a424b55606b707a76726e6a645c53483c3b4855616e7b8897908477675c5145382c1f1306000713202c3945525d6877849199897c6f6353493f33333f4c5966727f8c999e9184776b5e5144382e2e35414c566a7683909d9a8d8073675a4d40343b4855616e7b8897908477675c5145382c1f130600000000000000000000050c151d23282f394653606c7884919eaa9e91857f848a90959c9fa19e95918981796e6a60594f463c3237332f2d2b27221b1c17100800000000000000000006121f2b3844505b667683909ca9b3a79a8d807467584e43372b1e1308000000000000000000000000000000000000060f1d272f373c4041423e3a39352f2d29251e18120b0300000000091623303c4956636f7c8999a4afac9f9286796d6053473a2d22170b0000000000000000000000000000000000000000000815222e3b4855616e7b8897a2adaea298887b6e6155483b2e2215080000000613202c3945525d686d71727374757778767066544b403435363737373838383f4b5865727e8b98a5b1b3a9988b7f7265594f42392e393939393939392d3945525d6875828e9ba8ac9f9285796d6053463a2d201307000006131f2b37434e585f62666666666c7985929facada093877a6d666666666666666666666666666666605c554b4034281c1019242f404d596673808c99a6b3a79b8e8174685b4e4135281b0e000000000000000000000e1a25303b4653606c7884919eabaca095897c6f6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7a86929facac9f92867a6d6054473d3221160c010000000000000000000916222f3c4955626f7c889aa4afac9f9286796d6053463a2d2013070000000b1825323e4b5865717e828282828282828282828282828282828286929faca79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000006131f2c3845515c676f7c86929fa4aeaaa29892867e756d68605d5654514b4d4c4b4b4b4c4d4b5153555c60676d737d859196a0a8aba29891847a6d60594f42382e23170c0000000000000000000009151f2c3845515c6673808d9aa4afa99c8f82757070707070707070707070707070707070707070707070707074808d9aa6b0a79b8e8174685d5245392c2013040000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929faca194887b6e61626e7b86929fa8a69f92857b6e61594f433a2f22190c16232f3c4956626f7c8995a2ac9f9386796c605346392d20130004111d2935414c566875818e9a8d8074655b5044495663707d8996a0998d80736a5f574e4642403f3f41454c545d67707d86837f7b746e64584c40424d5765727f8c988e817467554b4034291c10040004111d2935414c566875818e9a8d8074655b504437333f4c5966727f8c999e9184776b5e51443b3b3b3c44505c667783909d998d8073665a4d4037424d5765727f8c988e817467554b4034291c10040000000000000000000000030b121b27333f4953636f7c8996a1a3998c7f73787d83898f949da0a09d938e847c706b60584e443b302523201f1b1711100b0500000000000000000000030f1c28333f4a546774808d9aaab4aa9d9184776a5f53473a2f24190b0200000000000000000000000000000000030e18212f3941484d4e4f4b4745413a39353029241d150d030000000714202d3a4753606d7a86939facaea399897d706353493f33271b0f030000000000000000000000000000000000000004111d2935414c5565717e8b98a9b3ac9f9285786d6053463a2d2013070000000714212d3a4754606d7a7e7f80818283858276665c5145382f2c2924262a2d37434e586774818e9aa7b4b7aa9d9083776b60544b40352f2b2623282b2f38414c56606d7a85929faca99b8e8275665c5144382c1f120600000815222e3b47545f6a6f72727272727985929facada093877a727272727272727272727272727272726d675c5145382c1f131824313e4b5764717e8a97a4b1a89c8f8275695c4f4236291c0f0000000000000000000009141f2b3844505b66727f8c99a3aea79a8d8174675c606060606060606060606060605765717e8b98a2aea79b8e8174685d5245392c201304000000000000000000000b1824313e4b5764717e8a97acb6aa9d908477665c5144382c1f12060000010d1a2734404d5a6773808d8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f9298a2aea79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000004111d2935414c56606d79839198a2aeaea39892867d716c615e56524c474541403f3e3e3e3f404045474b51555c606b6f7b849196a1abaaa0968e81746b60544a3f34281c110600000000000000000004101c2834404b54616e7b87939facac9f93877d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d85929fabaca095897c6f63564c4135291d11040000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929faca194877a6e616c76828f98a3ab9f948b7e72685e52473e31281d100916232f3c4956626f7c8995a2ac9f9386796c605346392d201300010d19242f3d4a5764707d8a989184786c6053464653606c7884919e9f92877c6f695f58534d4d4c4c4c51565d666d7983918f8c888174675a4e4147535f6977839097897d7063564a3d2f23180c0000010d19242f3d4a5764707d8a989184786c6053463c323f4c5966727f8c999e9184776b5e5148484848494e56606d7985929f988b7f7265584c3f3a47535f6977839097897d7063564a3d2f23180c0000000000000000000000000005121f2b3744505b6574808d9aa89f92867a6e6c70767c828991959fa39d9691867d706a5f564c41362a2113120f0b0600000000000000000000000000000b17222d3d4a5763707d8a98a2aeaca095887c6f62564c4135291d140a000000000000000000000000000000000915202a33414b53595b5c5854524c4746413a352f271f150b0100000613202c3945515d677784909daab4ab9a8d8073655b5044372b1f140a000000000000000000000000000000000000010c13202c3945515d6775828e9ba8b5a89c8f8275665c5044382b1f12060000000714212d3a4754606d7a878c8d8e8f909186796d60544a403a39352f31363a3f47535f6a7783909daab6b8aca095897d70665c5145413a37312e34383b424a525e68727f8c98a2ada1978a7d7164544a4034281c100400000916222f3c4955626f7c7f7f7f7f7f7f86929facb3a6998c807f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6053463a2d20131724303d4a5763707d8a96a3b0a99c908376695d5043362a1d1000000000000000000000030f1c28333f4a54616e7a86929facab9f9285796d60535353535353535353535353535f697683909caaaca095897c6f63564c4135291d1104000000000000000000000c1926333f4c5966727f8c99a5b2a99c8f827669544a4034281c10040000010d1a2734404d5a6773808d9a9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9fa2aab4a79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000713202c3945525d68727f8c95a0aaafa59f92867d706b625a524c45413a39352f32313132322f35383a40454b515960696e7b849199a3aea89e93897d70665c5044382d22170b000000000000000000000c18232e3946535f6976828f9ca9afa499938a89898989898989898989898989898989898989898989898989899297a2adaa9d9084776b6054443a2f24190d010000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929faca094877a6d68717e8b949faaa3999083776c60564d41352c1f160c0916232f3c4956626f7c8995a2ac9f9386796c605346392d201300000813202d3a4653606d79859296897c7063584e44505b66717e8b959f9991847b6f6a615f57595859555d60686d78818e959c93877c6f625548424d57616e7b88959285796d6053463a2d2013070000000813202d3a4653606d79859296897c7063584e43373f4c5966727f8c999e9184776b5e545454545556585f68707d8a98a298897d7063564a3d424d57616e7b88959285796d6053463a2d201307000000000000000000000000000613202d394653606c7884919eac9b8f82756860646b6f767d838c9299a2a09892867c6f685e52463d32271b1003000000000000000000000000000000000614202d3a4753606d7985929facb1a79a8d8073685d52453b2f261b1106000000000000000000000000000006101a26313c45535d64686964605d5654524c45403931271d1207000004101d2935404b556773808d9aa9b3ab9e9184786c6053463c2f261b1106000000000000000000000000000000000007131d28333f4a54606d7a86929facb1a7988b7f7265544a3f34281c10030000000613202c3945515d67778390999b9c9d988a7d71665b514b4745404343424648505a626f7b8895a0acb8bcb1a79d9083796d605b524c464242413f44464d545b616d7a85919eaaa99e9184796d6053463a2e23180c0000000c1925323f4c5865727f8b8c8c8c8c8c9299a3aeb4a89c928c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877a6d6054473a2d21141623303d495663707c8996a3afaa9d9083776a5d5044372a1d1100000000000000000000000b17222d3846525e6875828e9ba8ada2978a7e7164574d42464646464646463f4a54626e7b88949fabaa9d9084776b6054443a2f24190d01000000000000000000000d1a2633404d596673808c99a6b3a79a8e8174675b4e412e23180c000000010d1a2734404d5a6773808d9aa6a9a9a9a9a9a9a9a9a9a9a9a9a9a9acaeb4aca79a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000004111d2935404b55606d7a85929fa7b1a99d938b7e716b60595046413a352f2c2924252524252524292c2e343940454f575e696f7c87929fa7afa59d9183786d60544a3f33281c0f0300000000000000000007121d2a36424d5764707d8a96a1adaba49f9796969696969696969696969696969696969696969696969696969fa2a9aea2988b7f7265594f4332281e1308000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929faca093867a6d6d7a85929ea6a89f92867c6e655b50443b30231a0d040916232f3c4956626f7c8995a2ac9f9386796c605346392d2013000006131f2c3845515c6775818e9b8f82756a6054474a54606c78839098a09691847c746e696766656567676d727a828e939e958d80746a5f534746535e6974818e9a8e8174665c5044382c1f120600000006131f2c3845515c6775818e9b8f82756a6054473e3f4c5966727f8c999e9184776b61616161616162656a6f7a84919e9f9285796d6053463a46535e6974818e9a8e8174665c5044382c1f1206000000000000000000000000000815222f3b4855626e7b8896a1a49a8b7e7164565960636b70787f879297a2a29891847a6e61594f44382c1e13080000000000000000000000000000000006131f2c3845515c6775828f9ba8b2ab9f92857a6d60574d41382d2217110a020000000000000000000001081018222b37424e57646f7475716d6865615e56514b43392f24180c0000010d18242f3d495663707c8997a1adaca196897d7063584e41382d22170f06000000000000000000000000000000071118242f3844505b66717e8b98a2aeaca095887b6e6155483b2e23170b0000000004111d2935414c556673808d99a3a8aa9d9083786c605d5553514b50504d53555a626c74818e9aa7b1b6b4b6aca0958d80736d605d56534d4e4e4a5053575e666c75828f97a1ada1978c7f73665c5145382c1c12070000000c1925323f4c5865727f8b98999999999fa3abb4b9ada49c99999999999999999999999999999993877a6d6054473a2d211416222f3c4955626f7c8895a2afaa9e9184776b5e5144382b1e11000000000000000000000006111c2a36414c5663707d8996a0aca99c8f8276695e5246382d393939393844505c6673808d99a6aea2988b7f7265594f4332281e130800000000000000000000000e1a2734414d5a6774808d9aa7b3a69a8d8073675a4d4034271a07000000010d1a2734404d5a6773808d9a9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000613202c3945515d6773808d97a2adada1978e81746c61594f473e36302924201d181918181819181d1f23282f343d454d57606a727f8c95a0acaca0958b7e71665b5044382b1f1308000000000000000000000e1a26313b4653606d7984919eabb5afaca3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3abadb3ac9f92867a6d6054473d3221160c01000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929faca39986796d75818e97a2aca0968c80736a5f53493f32291f1108000916232f3c4956626f7c8995a2ac9f9386796c605346392d2013000004101c2834404b55636f7c899494887c6f62594f44505b666e7b869298a0969187807b777473727273767a7f858f939e969083796d60584e434e58616e7b869294897c6f62544a3f34281c100300000004101c2834404b55636f7c899494887c6f62594f443f4c5966727f8c999e9184776e6e6e6e6e6e6e6f72757c839096a0978d8074665c5145434e58616e7b869294897c6f62544a3f34281c1003000000000000000000000000000b1825323e4b5865717e8b98a89f93877a6d61544f545960666d737d859297a2a1968f82756b6054483a2f24190d0100000000000000000000000000000004101c2934404b5563707d8a96a1acaea2988c7f73695e53493f3327221b140b090603000001000205080d1319222a343c47535f6a7481827e7a76716d68605d554b4035291d100400000713202d3a4653606d7985929eacb2a89c8f82756a5f53493f332721180f0802000000000000000000000003091119232935404b55606c7884919daab3a99d908477695f53463a2d1c110600000000010d19242f3b4854616e7b86929fa9ab9f958c7f736d6762605d555d5d575f61656d717e8a939da9afa9a7a9aba79c928c7f746d68615f575b5b545c6062696e78808d949ea9a59e9184796d60544b4034281c0b000000000c1925323f4c5865727f8b98a5a5a5a5acaeb4bdbfb6ada8a6a5a5a5a5a5a5a5a5a5a5a5a5a5a093877a6d6054473a2d211416222f3c4955626f7c8895a2afab9e9184786b5e5145382b1e120000000000000000000000000d1925303b4854606b7784919daaac9f93877b6e6153493f33272d2d2d3a4653606d7984919eabac9f92867a6d6054473d3221160c0100000000000000000000000e1b2834414e5b6774818e9aa7b3a6998c807366594d4033261a0d000000010d1a2734404d5a6773808d939393939393939393939393939393939393939393938d8074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000714202d3a4753606d7a85929fa9b2a89e91857a6d605a50473d352a251e1913110d070b0b0b070c1013181d2329333b454e58606d7883909da7b1a79e9184786c6053463a3024190d0100000000000000000009141f2c3844505c6673808c99a3afbbb9b1acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa7a9afb8bab1a79b8e8174685d5245392c20130400000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929fac9f928679707d89939ea9a59d9184796d60584e41382d20170d00000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130000000c18232e394854606b76828f9c8f82756c61564c4a545f69707d8692979f99928d888481807f7f8082868b91979e9691847b6e675c51464b55606a74818d998f82766a605442382e23170c00000000000c18232e394854606b76828f9c8f82756c61564c414c5966727f8c999e91847b7b7b7b7b7b7b7b7c7e82879095a09892857a6d61544b404b55606a74818d998f82766a605442382e23170c00000000000000000000000000010e1b2834414e5b6774818e9aa79e918477685e5246484f545c606b707c85929fa59e93897d7063564c4135291d1104000000000000000000000000000000000c18232f394653606c7884919ea8b2aa9f92867b6e655b50443e332d261d1a1312100b060e090e1214191e2429343c46505a626e7b878f8b86827e7a766d675d5145392c1f1306000006121f2c3844505c6673808d9aa4afaa9e94887c6f655b50443d332a2219140e09060400000100000406090e141a232b353d45515d67717e8a95a0acada2978b7e7265574d42362a1e0a0000000000000814212d3a46535e6974818e97a1aba79c918c8079736f6d676a6a6a6a696e71777e87929fa5afa59d9b9c9fa6a49c918c807a726e6969686768666d6f747b828d929da6a69e938a7e71675d5142392e23180c000000000c1925323f4c5865727f8b989f9f9f9fa0aeb4bcb9b0a8a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f93877a6d6054473a2d211416232f3c4956626f7c8995a2afaa9d9184776a5e5144372b1e1100000000000000000000000008141e2c38444f5965727f8c98a3aea4998c7f73655b5044372b1f2a36414c5663707d8a97a1ada79b8e8174685d5245392c2013040000000000000000000000000f1c2835424f5b6875818e9ba8b2a5998c7f7266594c3f3326190c000000010d1a2734404d5a6773808686868686868686868686868686868686868686868686868074675a4d4134271a0e0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000006121e2b37424d5765717e8b98a2aeaca0968b7e71685d52483e352b2319130d08040100000000000004070c12182129333d44505c66707d89959fabaca0968a7d7064564c4135291d110400000000000000000003101c28343f4a54616e7b87929facb9b1a7a0939393939393939393939393939393939393939393939b9ea5afb8aca095897c6f63564c4135291d110400000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929fac9f9285797984919ea5a99d93897d70675c51463c2f261b0e0500000916232f3c4956626f7c8995a2ac9f9386796c605346392d201300000007121d2c38434f5963707d8994948a7d70685d52454d57606b707d858f949c9f9a95918e8c8b8c8d8f92989e9c938e847b6e695f554b45515c676f7c879394897c6f63584e4330261c1106000000000007121d2c38434f5963707d8994948a7d70685d52454c5966727f8c99a196918787878787878788898b8f93999e9691867d6f685d524245515c676f7c879394897c6f63584e4330261c11060000000000000000000000000004111d2a3744505d6a7783909da89b8e827568564c413d424a5159606a707d8a939ea69c8f8276685d5245392c2013070000000000000000000000000000000007121f2b3844505b66727f8b96a1acaea2988f82776c605a50443f382f2b26201f1c171b1a1b1a1e2124292f353e464e58626c75828f9999928f8b8682796d6053473a2d201407000003101c28343f4a54616e7b87939fabb0a69c9083776c60584e453c342a251e1a1312100c070e070c1013131a1f262a353d47505a606d7984919ea7b1a99f9285796d6053473b31261a0e00000000000005121e2a36424d57616e7b859299a3aba39c928d84807c7a7877767677787b7e838b9299a3aea69d938e90949fa6a39c928d857f7b777675747576797c80868f949da4a69f948e81746c61554b4030271d1207000000000c1925323f4c5865727f8b939393939393a2aab4b3a89e9693939393939393939393939393939393877a6d6054473a2d21141623303d495663707c8996a3afaa9d9083776a5d5044372a1d1100000000000000000000000002101c27333d4754616d7a86929facab9e9184786c6053463a2f242d3946525e6875828f9ba9aca095897c6f63564c4135291d11040000000000000000000000000f1b2835424e5b6875818e9ba8b2a6998c7f7366594c403326190d000000000d1926333f4c58646e73797979797979797979797979797979797979797979797979746e64584c3f33261a0d0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000814212e3a47535f697683909daab4aa9e9184786d60564c41362d2319110802000000000000000000000001070f172128343f4a54606b7783909daab2a89b8f8275685d5245392c201307000000000000000000000c17232e3846525e6975828f9ca8b2aca095898686868686868686868686868686868686868686868e939ea9b4aa9d9084776b6054443a2f24190d0100000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929fab9e918578808d96a0aca1978e81746b60554b40342a1d140a0000000916232f3c4956626f7c8995a2ac9f9386796c605346392d2013000000000f1b27323d4854606b7682909991847a6d605b51484f59606b707b828a8f939a9a9d9a9998989a9c9a99928f8981796e695f574d47505a606d798491988f82766b6054463d321e150a000000000000000f1b27323d4854606b7682909991847a6d605b514c5966727f8c99a8a19e949494949494949495989c9a97928d847d6f6b60564c47505a606d798491988f82766b6054463d321e150a000000000000000000000000000004101d2935404b556b7885919ea6998c807366594d40303940444f58616b75818e9ba99f92867a6d6054473a2d21140700000000000000000000000000000000030f1c28333f4a54606d7984919ea6b0aa9e948c7f726c615a5049413c37312d2b2823272728252a2d2f353a41454f585f6a717e8b939ea39f9c998f8275675d5145392c1f13060000000c17232e3846535f6975828e99a3afab9f948b7f726a60574e463e36302a25201f1c181b1a1b181c1f20262b31363f474f59616c74808d96a1adada2978d8073675d5145392a1f1409000000000000020e1a25313b46525e69707d879299a1a9a49c96918d8986858483838485888b90959fa3aba59d948e818390949da5a49d97928c8884828181828385898d92989ea6a49f948f82796d605a5043392f1e150b00000000000c1925323f4c5865727f8686868686868998a2aeafa2968c87868686868686868686868686868686867a6d6054473a2d21141824313e4b5764717e8a97a4b1a99c8f8376695c504336291d10000000000000000000000000000b16202d3946525d6875818e9ba7aca096897c7063554b4135292e3a4754616d7a86929facaa9d9084776b6054443a2f24190d010000000000000000000000000e1b2834414e5b6774818e9aa7b3a6998d8073665a4d4033271a0d000000000b17232f3b47525c64676c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c67645c52473c3023170b0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000815222f3b4855626e7b88959fabaea3988b7e72665c50443a2f241b1107000000000000000000000000000000050f17232e38424f5964717e8a98a2aeac9f92867a6d6054473a2d2114080000000000000000000006111c2a36424d5763707d8a96a1acaa9d9083797979797979797979797979797979797979797979818e9ba7aea2988b7f7265594f4332281e13080000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929faa9d91847b87929fa8a69e92857a6d61594f43392e22180b020000000916232f3c4956626f7c8995a2ac9f9386796c605346392d2013000000000a16212c38444f59626f7c8692978e81746d625a50474f5960696e767d83878b8e909192929291908e8b86827c756d675f574d474f59626c73808d9592867c6e62594f44342b200c03000000000000000a16212c38444f59626f7c8692978e81746d625a505966727f8c9393939393939393939399929291908d8a8580796f6b60594f474f59626c73808d9592867c6e62594f44342b200c03000000000000000000000000000006131f2c3945515d677986929fa5988b7f7265584c3f322e343d464f59626f7c8997a2a3998a7d7164574a3e3124170b00000000000000000000000000000000000b17222d3845515c67717e8b949ea9b0a69f92877e716c605b534d47423c3a38342e34343531363a3b41454c5159616a6f7c86929fa5aea99f93877c6f62554b4035291d100400000006111c2a36424d57626e7b87929fa8b0a69f92877c6f695f585046413b36312d2c282327272723282c2d31373b42465159606b717e8a929da8b1a79f92857a6d61554b4035291d10040000000000000009141f2a36424d57606b717e8792979fa2a8a19e999a9391909090919297989da0a7a8a19e938e82797a828e939da0a8a19e9996918f8e8e8f9092989a9fa3a7a09a938d82796d675d51483e31281d0c0300000000000b1824313e4a56626d7279797979797986929facada093877a7979797979797979797979797979797976685d5245392c20131926333f4c5966727f8c99a5b2a79b8e8174685b4e4135281b0e0000000000000000000000000005111d2935414c56636f7c8995a0aca89b8e8174675d5145392c37434e5865727f8b99a3aea2988b7f7265594f4332281e1308000000000000000000000000000e1b2734414e5a6774818d9aa7b3a79a8d8074675a4d4134271a080000000007131f2b36404a52585a6060606060606060606060606060606060606060606060605a58524a40362b1f13070000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000030f1c28333f4a5465727f8b98a7b1ac9f92867a6d60544a3f32281e1209000000000000000000000000000000000006111c26303d4753606d7a85929facaea3998b7e7164584b3e3025190e02000000000000000000000e1a25303b4653606c7884919eabaca095897c6f6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7a86929facac9f92867a6d6054473d3221160c010000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929faa9d9083839099a3aa9f948a7e71685d52473d30271d0f06000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130000000004101c27333d47535f6a737f8c95938c7f726c615950444f575f616b70767b7e8183858586858583817e7a756f6a605d554d445059606b717e8b92958c7f736a5f53473d3222190f000000000000000004101c27333d47535f6a737f8c95938c7f726c61595966727f86868686868686868686868686858483807d79736d6760594f445059606b717e8b92958c7f736a5f53473d3222190f0000000000000000000000000000000714202d3a4753606d7a8699a3a4978b7e7164584b3e312328343e4653606c7985929fab998c7f7266594c3f3326190c000000000000000000000000000000000006111c2834404b55616c75828f97a2abafa39992877e726c655f57534d4946443f41414141424246484c52555d606b707c859298a2aeada2978f82756a5f5343392f24180c00000000000e1a26313b47535f6974808d96a0abaea39991857b6e6a615a524c46423c3a38342e3434342e34383a3c42474d535b626b707d86929fa4aeaaa0958b7f72685e5243392f24180d0100000000000000030e1a25303b454f59626c717d858d92989d9fa4aca49f9e9d9d9d9d9ea1a9aba49f9c96918a81786d6d78818991959c9fa3a8a09e9c9b9a9b9c9fa2aaa39f9b95908880786d675d554b40362c1f160c0000000000000915222e3a46515b62656c6c6c6c6c7985929facada093877a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5d564c4135291d111c2934404b556774818e9aa7b3a6998c807366594d4033261a0d00000000000000000000000000010d1924303a4854606b7783909daaac9f92857a6d6054473c313b4754606a7783909dabac9f92867a6d6054473d3221160c01000000000000000000000000000d1a2733404d5a6673808d99a6b3a89b8e8175685b4e422f24190d01000000020e19242e3840474c4d5353535353535353535353535353535353535353535353534d4c4740382f24190e030000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000006121f2b3844505b6675828f9ba8b5a89b8f8275685d5242382e20160c000000000000000000000000000000000000000a15202c3945515d6775828e9ba8b4ab9b8e817468564c41362a1e11050000000000000000000009141f2b3844505b66727f8c99a3aea79a8d8174675c606060606060606060606060605765717e8b98a2aea79b8e8174685d5245392c201304000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929fac9f928790959faba2988f82766c61564c41352b1e150b00000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d201300000000000b16212b37434e58606d7883909793887e716b625a514a4d53596163696e71747678797979787674716d68626058514b4a505a616b707d8792979083786d60584e43352b2110070000000000000000000b16212b37434e58606d7883909793887e716b625a636d727979797979797979797979797978777673716d67605d554f4a505a616b707d8792979083786d60584e43352b2110070000000000000000000000000000000613202d394653606c7986929fa5988b7e7265584b3f3025212b3744505b657784909da79a8d8074675a4d4134271a0e0100000000000000000000000000000000000c18232e3943505a616e7b859299a3afaba39992877f776e69615f575553504a4e4e4d4e4f4d5354565d60676d747d859297a1aaaea49e92857b6e61584e4331271d1207000000000009141f2b37424d57606d79849199a4afaba19791847c706c615e56534d494644404141414141404546494d53575f616d727d869298a2aeaca2989083786c60564c4131281d120700000000000000000009141f29333d47505a626b6f7a80868c90939a999b9d9e9e9f9f9f9e9d9c9a9993908b847d746d66666d747d848a8f92999a9c9d9e9f9f9f9e9d9b9998928f89837d746d665d554c43392f241a0d0400000000000006121e29343f49515658606060606c7985929facada093877a6d6060606060606060606060606060605f524c443a2f2419131f2c3845515c677783909daab4aa988b7e7165584b3e3225180b000000000000000000000000000008131e2c38434f5965727f8b98a2aea2988b7e7165574d4237404b55626f7c8895a0aca79b8e8174685d5245392c20130400000000000000000000000000000c1825323f4b5865727e8b98a5b1a99c8f837669554c4135291d11040000000008121c262e363b3f40464646464646464646464646464646464646464646464646413f3c362f261d1208000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000613202d394653606c7885929fabb2a9988b7e7165564c4130261c0d040000000000000000000000000000000000000004101d2935404b5565717e8b98aab3ab9e918478685e5246392d20140700000000000000000000030f1c28333f4a54616e7a86929facab9f9285796d60535353535353535353535353535f697683909caaaca095897c6f63564c4135291d1104000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929faca39992999fa7a79f92867b6e615a50443a3023190c0300000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130000000000050f1a26313c44505c666e7b85929992867d716c605c544e464f55575e6165676a6b6c6c6c6b6a6765615e56544e454e545c606c717d86929992857b6e665c50463c3123190f00000000000000000000050f1a26313c44505c666e7b85929992867d716c605c63666c6c6c6c6c6c6c6c6c6c6c6c6c6b6b696764605c55514b4e545c606c717d86929992857b6e665c50463c3123190f0000000000000000000000000000000005121f2b3744505b657885929ea6998c807366564c41362e2e2e3844505b667784909da79a8d8074675a4d4134271a0e01000000000000000000000000000000000007121d27303e46525e69707d87929fa4acaba399938c827b746e696562605c545b5a5a5b5c575e6164686d737a808a9297a1a9afa59d928a7e70695e52463c321f150b010000000000030e1a26313c45515d676f7d87939fa4aea9a19691867e756e68615e575653514a4e4e4d4e4e4b515356575f62696e767f879298a2aaafa49a92867c6f665b50443a301f160c01000000000000000000030d17212c353f48505960686d737a7f83878a8c8e90919192929292908f8d8a86837e79706c605c5c606b70787d82868a8d8f919292929292908f8c8986827d776f6b605c544c433a31271d120800000000000000010d18232d373f464a4c5353535f6c7985929facada093877a6d6054535353535353535353535353535345413a32281e1314202d3a4753606d7986929facaea298887c6f6255493c2f2216090000000000000000000000000000020f1b27323d4754606d7a86929facaa9c908376695f53473845515c6774808d9aa7aca095897c6f63564c4135291d110400000000000000000000000000000a1724313d4a5764707d8a97abb5ab9e918478675d5145392c20130600000000010a141c242b2f33343939393939393939393939393939393939393939393939393433302b241d140b01000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000815222f3b4855626e7b8897a2adada197877b6e6154483b2f21140a0000000000000000000000000000000000000000010d18242f3b4855616e7b8898a2aeada196877a6e6154473b2e21140800000000000000000000000b17222d3846525e6875828e9ba8ada2978a7e7164574d42464646464646463f4a54626e7b88949fabaa9d9084776b6054443a2f24190d01000000000000000000000000000000000000000c1926323f4c5965727f8c98a5a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929facaba39fa3ababa0958c7f72695f53483e32281e11070000000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130000000000000a152028343f4a545f696f7d87929892877e736d665f58524c484d5254585b5d5e5f5f5f5e5d5b5854524c474b51575f666d737e87929892877d6f695f544a3f342a20110700000000000000000000000a152028343f4a545f696f7d87929892877e736d665f586060606060606060606060605f5f5e5d5a5753514b4b51575f666d737e87929892877d6f695f544a3f342a20110700000000000000000000000000000000030f1b27333f49536a7784909da99c8f8276685e52463f3b3b3b404653606c7985929fac998c7f7266594c3f3326190c000000000000000000000000000000000000000b151e2a36424d56606b717f8b939aa3ababa49f948f86817b76726f6d6668686767686869696e71757a7f858d929ea2a9afa59e938d80746c61574d42342a200d030000000000000009151f2935404b55606b727f8b929da4ada9a198928a817a746e696562605c545b5a5a5a5b545c606266696e747b828b9299a2aaaea39f93887e706a5f544a3f32291e0d040000000000000000000000050f1a232d363f474f565d60686e72767b7d7f82838485858685858482807d7a76716d66615a51515960666c71767a7d80828485858685858382807d7a75706b636059514a423a31281f150b00000000000000000006111b252d343a3e3f4646525f6c7985929facada093877a6d6054474646464646464646464646464639352f282016101d2935404b5563707d8a99a3aeac9f9285796d6053463a2d2013070000000000000000000000000000000a16202c3945515d6774818e9aa7ab9f94887b6e62544a3f4653606d7985929fabaa9d9084776b6054443a3024190d0100000000000000000000000000000916222f3c4955626f7c8899a3aeaca196877a6d6054473a2d2114080000000000020a12191f2326272d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2726231f19120b0200000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000a1724313d4a5764707d8a97a9b3ab9e918578695e53463a2d2114020000000000000000000000000000000000000000000714212d3a46535f697885929fabb2a896897d7063564a3d3023170a000000000000000000000006111c2a36414c5663707d8996a0aca99c8f8276695e5246382d393939393844505c6673808d99a6aea2988b7f7265594f4332281e1308000000000000000000000000000000000003060809192633404c5966737f8c99a6a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929facb5afacafafa4999083786d60574d42362c20160c000000000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d2013000000000000030c17232e38424d57606b717e8a9299928b80786f6a605d56524c46474b4e505252535252504e4b47464b51555d606a6e787f889299928a7e716b60574d42382e22180e000000000000000000000000030c17232e38424d57606b717e8a9299928b80786f6a605d56524c5353535353535353535251504d4a474b51555d606a6e787f889299928a7e716b60574d42382e22180e0000000000000000000000000000000000000b17222d414e5a6774818d9aa99f92867a6d6159504a4847484b515b636f7c8998a2a49a8a7e7164574b3e3124180b00000000000000000000000000000000000000030c1925303b444f59626d727f889299a1a8afa69f99928e88837f7c797775747474747576787b7e82868c92979da4adaba39f938e81786d605a50453b3022180e0000000000000000030d18242f3a434f59626d74808d929ca3adaaa29f938e86807b76726f6d6669686767676869666d6f72777b81868f949fa3ababa39f918c7f726c61584e42382d20170d0000000000000000000000000008111b242d353d444c52565e6165696e71737577777879797978777573716e6864605c545044454f545b6064686d717376777879797978777573706d67636059544f44403930281f160d030000000000000000000009131b23292e31323946525f6c7985929facada093877a6d6054473a3939393939393939393939392c29241e160e19222c3945515d6774818e9aabb4a99c908376665c5044382c1f120600000000000000000000000000000004111d2935414c55626f7c88959faba6998d8073665c50444d5764717e8a97a2ada2988b7f7265594f4332281e13080000000000000000000000000000000713202d3a4653606d7986929facb2a896897c6f6356493c3025190e00000000000001080e1317191a20202020202020202020202020252728292622211f1a20201a1a17130e08010000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000c1926333f4c5966727f8c99a5b2a99c8f827669574d42362a1e120500000000000000000000000000000000000000000005121e2b37424d576a7683909da9b2a5988c7f7265594c3f3226190c0000000000000000000000000d1925303b4854606b7784919daaac9f93877b6e6153493f33272d2d2d3a4653606d7984919eabac9f92867a6d6054473d3221160c01000000000000000000000000000000040a0f1315161a2734404d5a6773808d9aa6a79b8e8174685b4e4135281b0e0200000000000000000000131f2c3946525f6c7985929facb8bbb9b2a89f93877c6f665c50453b31241a0e04000000000003050916232f3c4956626f7c8995a2ac9f9386796c605346392d20130000000000000006111c26303c454f59616c717e879298928d837c736d68605d5653514a4a484847464748484a4a5053555d60676d737b838c939892877e716c61594f453c30261c0f060000000000000000000000000006111c26303c454f59616c717e879298928d837c736d68605d5653514a4a484847464748484a4a5053555d60676d737b838c939892877e716c61594f453c30261c0f06000000000000000000000000000000000000061724313d4a5764707d8a97a2a3988d80736b605c54555455555c606d75828f9caa9f93877a6e6154473b2e211408000000000000000000000000000000000000000009141f29323d47505a626d727e8791969ea5acaba39f9a95908c8885848281818081828385878b8f92989fa2a9ada8a099928d81786d665c50483e33291f100600000000000000000007131d28313d47515b606c77808c919ea1a9aea59e98928d87837f7c79777674747474747677797c7f83888e92999fa6aea8a199928b7f736d635a50463c2f261c0e05000000000000000000000000000009121b232b323a41454c5254565e616466686a6b6b6c6c6c6b6a696764615e5653514a423e3d424a5053565e616467696a6b6c6c6c6b6a686663605d55554f48433d342e271e160d040000000000000000000000010911181e22242c3946525f6c7985929facada093877a6d6054473a2d2d2d2d2d2d2d2d2d2d2d2d201d19130e17202935404b55606d7985929fabb1a7988c7f7265544a3f34281c1003000000000000000000000000000000010d19242f3a47545f6a7783909da9ab9e9184796d605346525e6976828f9ca9ac9f92867a6d6054473d3221160c0200000000000000000000000000000006131f2c3845515c677783909daab2a6998c7f7366564d41362a1c11060000000000000002070b0d0d131313131313131313151e252c31343536322f2e2b26201f1c18120b0300000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000e1b2834414e5b6774818e9aa7b3a69a8d8073675a4d4031251a0e02000000000000000000000000000000000000000000020e1a2631414e5b6874818e9ba7b3a79a8d8074675a4d4134271a0e00000000000000000000000008141e2c38444f5965727f8c98a3aea4998c7f73655b5044372b1f2a36414c5663707d8a97a1ada79b8e8174685d5245392c201304000000000000000000000000000000070f151b1f2222262b38434e586875828f9ba8a79a8d8074675a4d4134271a0e0100000000000000000000131f2c3946525f6c7985929facacacacada1968d80746a60544a3f33291f120900010407070c10121316232f3c4956626f7c8995a2ac9f9386796c605346392d201300000000000000000a151e2a333d47505a626c717d869196959087807a736d6863605c54575554545354545557545c6063676d727a7f8690959691867d716c625a50473d332a1e150a0000000000000000000000000000000a151e2a333d47505a626c717d869196959087807a736d6863605c54575554545354545557545c6063676d727a7f8690959691867d716c625a50473d332a1e150a000000000000000000000000000000000000000714202d3a4753606d7a85929ea89f93887d726d666362616263676d737f8b949ea69d908376685e5246392d2014070000000000000000000000000000000000000000020d17202b353f48515b626c717d848e939da0a7abaca79f9d989892908f8e8d8d8e8f909298979c9fa3aaada9a29f96918780786c665c544a3f362c21170d00000000000000000000010c161f2b353f44505b656c747f8a92979ea6acaaa29f9a93908c898684828181808181828486898c90959a9fa3ababa49f9691877e736d635b51473e342a1d140a00000000000000000000000000000000091119202830353b4146474d525457595b5d5e5e5f5f5f5f5d5c5a5754524c46444039302f383f44464c5254575a5c5e5f5f5f5f5f5d5c595653514b48443d383228231c150c040000000000000000000000000000060d12151f2c3946525f6c7985929facada093877a6d6054473a2d212020202020202020201413110d0f182029323b45515d67727e8b97a2adab9f95887b6e6155483b2e23170c000000000000000000000000000000000008131e2b37434e5865717e8b97a2ada1968a7d7063564c54616e7b87939faca79b8e8174685d5245392c2013040000000000000000000000000000000004101c2834404b556774818e9aabb5a99c908376685e5246382e23170c0100000000000000000000010606060606060008111e272f373d4042433f3b3a37312d2c29231d150d04000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000101c2936434f5c6976828f9ca9b2a5988c7f7265594c3f322619090000000000000000000000000000000000000000000000091a2733404d5a6673808d99a6b3a89b8e8175685b4f4235281c0f00000000000000000000000002101c27333d4754616d7a86929facab9e9184786c6053463a2f242d3946525e6875828f9ba9aca095897c6f63564c4135291d1104000000000000000000000000000007101920272b2e2f31363e4754606a7885919eabaa998c7f7266594c3f3326190c0000000000000000000000131f2c3946525f6c7985929f9f9f9f9fa59e9184796d60584e42382e21170d02080d111314181c1f201f232f3c4956626f7c89959f9f9f9386796c605346392d20130000000000000000030c18212b353e48505a626b707c848e9399928d85807a75706d666664626160606061626466666d70757a7f858c9298938e847c706b625a50483e352b21180c03000000000000000000000000000000030c18212b353e48505a626b707c848e9399928d85807a75706d666664626160606061626466666d70757a7f858c9298938e847c706b625a50483e352b21180c03000000000000000000000000000000000000000613202c3945515d67727f8c96a1a49a92877f7873706e6e6e7073798088939fa69f948a7e7164564d41362a1e1105000000000000000000000000000000000000000000050e19232d363f49515a626b6f7a818990959c9fa6a9aca9aaa29f9d9b9b9a9a9b9b9c9fa2aaa8acaaa9a19e97928c847c736c665b544a42382e241a0f050000000000000000000000040d192327333f49535b606d737d858f949da0a7acaca49f9c989892918f8e8d8d8d8e8f919298999d9fa7acaca69f99938d847d716c635b51493f352c22180b020000000000000000000000000000000000070e161e24293036393b4246474a4c4f50515252535252514f4d4a4746413b38342e27262d33383a4146474a4d4f515252535252504f4d4a4745403a38332c272118120b03000000000000000000000000000000000106131f2c3946525f6c7985929facada093877a6d6054473a2d21141313131313131313060b0f151a212a323b444e58606d7984919ea9b2a89d908376695f53463a2d1c11060000000000000000000000000000000000010f1b26323c4753606d7985929faba99b8e8275685d525966737f8c99a4aca095897c6f63564c4135291d110400000000000000000000000000000000000c18232e3e4a5764717e8a99a3afac9f93877b6e61544a3f34281d13070000000000000000000000000000000000040e1a232f3941484d4f504c4847433d3a38342f271f160e040000000000000000000001040606111e2a3744515d6a7784909daaa99c8f8376695c504336291d10060000000000000000000000000000000000101d2a3743505d6a7683909da9b1a4978a7e7164574b3e3124180b00000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5b2a99c908376695d5043362a1d10000000000000000000000000000b16202d3946525d6875818e9ba7aca096897c7063554b4135292e3a4754616d7a86929facaa9d9084776b6054443a2f24190d0100000000000000000000000000040f19222b32373b3c3f4246505a626f7c8997a1ada298897d7063564a3d3023170a0000000000000000000000131f2c3946525f6c798692939393939393938a7d70675d51463d30261c0f080d13191d202125292b2c2c292f3c4956626f7c89939393939386796c605346392d2013000000000000000000060f19232c363f485059616a6f7a818a919697928c86817d797673706f6e6d6c6d6e6f707376797d81858c929796918a817a6f6a615950483f362c23190f060000000000000000000000000000000000060f19232c363f485059616a6f7a818a919697928c86817d797673706f6e6d6c6d6e6f707376797d81858c929796918a817a6f6a615950483f362c23190f06000000000000000000000000000000000000000004111d2935404b55606d79849197a1a399928b84807d7b7a7b7d80858d939aa4a0968f82766c6155443b3025190e020000000000000000000000000000000000000000000008111b242d373f48505960686d757d83898f94989c9fa3aba7a8aaa8a7a7a7a7a8a9a9a7a5a8a09e9a97918c8580796f6b605b544a423830261c110800000000000000000000000000071017222d384149505b636b707b828990959c9fa4acaca9aaa39f9d9c9b9a9a9a9b9c9d9fa3aaaaababa39f9b948f878079706b625a514940372e231a100600000000000000000000000000000000000000040c13191e252a2d30363a3b3e4042444445464646454442403e3b3936302c28231c1c22282b3036393a3e40434445464646454442403d3a39352f2c27211b160c070000000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a6d6054473a2d21140c0c0c0c0d090e1114171b1f262b333b444c56606a73808c96a1adada1968a7e7164574d42362a1e0a000000000000000000000000000000000000000a151f2c3945515d6774808d9aa6ac9f92867a6d6154606b7784919eabaa9d9084776b6054443a3024190d0100000000000000000000000000000000000714212d3a4754606d7a86929facafa4998c7f72665c50443a2f24181007000000000000000000000000000000030c16202c35414b53595b5c5955534e4a47454039312820160c020000000000000004090e111213131e2a3744515d6a7784909daaa99c8f8376695c504336291d13130807050200000000000000000000000000111e2a3744515d6a7783909daab0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1aa9d9083776a5d5044372a1d110000000000000000000000000005111d2935414c56636f7c8995a0aca89b8e8174675d5145392c37434e5865727f8b99a3aea2988b7f7265594f4332281e130800000000000000000000000000000a15202b343c4347494c4d5359616c75818e9ba9aa9f92867a6d6054473a2d2114070000000000000000000000131f2c3946525f6c7986868686868686868681756c61554b40342b1e150c13191e24292c2d323638393836323c4956626f7c86868686868686796c605346392d20130000000000000000000007111a242d363f474f5860686d747d848c929898928e8a8582807d7b7b7a797a7b7b7d8082858a8e929898928c847d746d675f584f473f362d241a11070000000000000000000000000000000000000007111a242d363f474f5860686d747d848c929898928e8a8582807d7b7b7a797a7b7b7d8082858a8e929898928c847d746d675f584f473f362d241a1107000000000000000000000000000000000000000000010d18242f3a45515d676e7c8592979fa39f96918c89888788898d91979fa49d9691847b6e615a504532291f140800000000000000000000000000000000000000000000000009121b252d363f474f565e616b70787d82878b909299989a9c9d9e9f9f9f9e9e9d9c9b999696918d89857f7a736d676059504a42382f261e140a00000000000000000000000000000006111b262f383f44515961696e757d83898f939a9c9fa2aaa7a8aaa9a7a7a7a7a7a9a9a8a6a9a29e9b99928e88827c746d676059504840372e251c110800000000000000000000000000000000000000000002080d14191e20252a2d2e31333537383839393938373634312e2d2a251f1c181211171c1f252a2d2e313436373839393938373533302d2c29241d1c160f0a04000000000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a6d6054473a2d211919191919191a191e2022272b31373e454d565e686f7c87929fa8b1a79e9184786d6053463b31261a0e0000000000000000000000000000000000000004101d2935404b55626f7b88949faba3998b7e726557636f7c8996a0aca2988b7f7265594f4332281e13080000000000000000000000000000000000000713202c3945525d6876838f9ca9b3ab9e9184796d60554b4035292219100903000000000000000000000000040c151e28323d47535d65686965625f585653514b433a32281e1308000000000000080f151a1d1f2020202a3744515d6a7784909d9f9f9c8f8376695c504336292020201514120e09030000000000000000000000121e2b3845515e6b7884919eabafa396897c706356493d3023160a00000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1aa9d9184776a5e5144372b1e1100000000000000000000000000010d1924303a4854606b7783909daaac9f92857a6d6054473c313b4754606a7783909dabac9f92867a6d6054473d3221160c0100000000000000000000000000030f1b27323c464e545559575f616b707e8a939eaaa3988e8174675d5145392c2013060000000000000000000000121f2b3844515d6974797979797979797979756f65594f433a342e261e191e252a3035393a3f43454645433f3a4754606a6f79797979797979766c5f5346392d2013000000000000000000000009121b242d353e464e565d606b70797f858c91969a97928f8d8a888787868787888a8c8f92979a96918c857f79706b605d554e463d352d241b120900000000000000000000000000000000000000000009121b242d353e464e565d606b70797f858c91969a97928f8d8a888787868787888a8c8f92979a96918c857f79706b605d554e463d352d241b1209000000000000000000000000000000000000000000000007131d2935404b555f6a6f7d858f949c9fa09e999695949596999ea19f9b938e847b6e695e52483e3320170d020000000000000000000000000000000000000000000000000009131b242d353d444c525960656c70767b7f8386898b8d8f9091929292929190908e8c8a8784807c79726d67605d554f443f382f261d140c02000000000000000000000000000000000a141d262d3340474f575e616b70777d82878b8f9298989a9b9d9e9e9f9f9f9e9d9d9b999797928e8a86817c766f6a605d554f473e362e251c130a00000000000000000000000000000000000000000000000002080e1114191e20212426282a2b2b2c2c2c2c2a29272421201e1914100c07060b0f13191d20212427292b2c2c2c2c2c2a29262320201d1813100b050000000000000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a6d6054473a2d2525252525262627252a2d2d33373c434750575f686e7a849199a3afaa9f958b7e71665c504438291f140900000000000000000000000000000000000000000c18242f3947535f6a7683909ca9ab9d908376695f6774818e9aa8ac9f92867a6d6054473d3221160c0200000000000000000000000000000000000004111d2935414c5664717e8a97a1adaca0968b7e71675d51453e342b221a140e09060400000101000205060c10161e27303a444f59656f7576726e6a6763605c554c443a3025190d010000000009121920262a2c2c2d2d2d3744515d6a778490939393938f8376695c5043362d2d2d2d22211e1a140e0600000000000000000000121f2c3845525f6b7885929eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0aa9e9184776b5e5144382b1e11000000000000000000000000000008131e2c38434f5965727f8b98a2aea2988b7e7165574d4237404b55626f7c8895a0aca79b8e8174685d5245392c201304000000000000000000000000000006131f2b37434e5860626567696e747d86929fa5a49f92867b6e61554c4135291d11040000000000000000000000101c2935414d5862696c6c6c6c6c6c6c6c6c68655d535246443f383026252a30363a4145474b4f525352504c47454e5860626c6c6c6c6c6c6c6c645a4f43372b1e1200000000000000000000000009121b232c343c434c525961676d737a7f84898e91979899979594939393949597999897918e89847f7a736d676159514c433c342c231b1209000000000000000000000000000000000000000000000009121b232c343c434c525961676d737a7f84898e91979899979594939393949597999897918e89847f7a736d676159514c433c342c231b1209000000000000000000000000000000000000000000000000010c18242f39434e58606b6f7b828a8f94979a9d9e9e9f9f9e9d9a99928f89817a6e695e574d42362c220e0500000000000000000000000000000000000000000000000000000109121b232b323a41464f535b6063696e7276797c7f8182848585868685848483817f7d7b7773706d66605d55514b433d332d261d140b020000000000000000000000000000000000020b141b2227353e454d525960636b70757b7e8285888b8d8f9091929292929191908e8c8a8885817e7a746f6a626058514b433d352d241c130a0100000000000000000000000000000000000000000000000000000205090e11141417191c1d1e1f1f201f1f1e1c1a171414110d08040000000003080d111314171a1c1e1f1f201f1f1d1c1a171413110d070100000000000000000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a6d6054473a32323232323232333430363a3b3f44464e535a61696e7a839096a1abaea3989083786c60544a3f34281c1003000000000000000000000000000000000000000007121d2b37434e5864717e8a97a1ab9f95887b6e616d7985929faba79b8e8174685d5245392c20130400000000000000000000000000000000000000010d19242f3a4653606d7985929ea9b2a89e9184796d605a50463d342a251f1a1313100c070e0e080e1114171c1f283039424c56606b7581837f7b7774706d675e564c4135291d110500000008121b242b313638393939393844515d6a77838686868686868276695c504337393939392e2d2b261f180f06000000000000000000121f2b3845525e6b7884919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0aa9d9184776a5e5144372b1e110000000000000000000000000000020f1b27323d4754606d7a86929facaa9c908376695f53473845515c6774808d9aa7aca095897c6f63564c4135291d110400000000000000000000000000000815222e3b4754606a6f7274777b81879298a2a39f928c7f72695f53433a2f24190d0100000000000000000000000d1925303b4650585d5f60606060606060605b5e60605f53504a42382e30363a41464c5254585c5e5f5f5c5853514b4e5456606060606060605f5a52493e33271b0f0000000000000000000000000009111a222b313a41454f555d60686d72787d8185888b8d8f919292939292918f8d8b8885817d78726d68605d554f45413a312a221a11090000000000000000000000000000000000000000000000000009111a222b313a41454f555d60686d72787d8185888b8d8f919292939292918f8d8b8885817d78726d68605d554f45413a312a221a1109000000000000000000000000000000000000000000000000000007121d27313c464f5960696e777d82888b8e909192929291908d8b86827d746d685e574d453b30241a100000000000000000000000000000000000000000000000000000000000091019202830363d41495053575e6165676d6f7274757778787979787877767472706e696763605c54514c45403a3128221c140b0200000000000000000000000000000000000000020a1117232c333b42464f54596063696e7276797c7e808283848585868585848382807d7b7975716d68625f58544e45403a312b231b120a01000000000000000000000000000000000000000000000000000000000000020507080b0d0f11111213131312110f0d0b080705010000000000000000010507070b0d10111213131312110f0d0a07060401000000000000000000000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a6d6054473f3f3f3f3f3f3f3f404042424647495053585f626c717b839095a0a8afa59f92867c6f655b5042382e23170c000000000000000000000000000000000000000000010f1a26313c4653606d7985929eaca7998c7f7366717d8a98a2aca095897c6f63564c4135291d1104000000000000000000000000000000000000000008131f2c3845515c6773808c97a1adada1968d80746c61584e463e36302a26201f1c181b1a1b1b191e2023282c313a424a545d68707d898f8c8884807d796d685e5246392d2013070000040f19242d353d424546464646453d4f5b6771777979797979797670665a4e3b44464646463b3a37312a21180e030000000000000000111e2b3844515e6b7784919eaab0a396897d7063564a3d3023170a00000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a99d9083766a5d5043372a1d100000000000000000000000000000000a16202c3945515d6774818e9aa7ab9f94887b6e62544a3f4653606d7985929fabaa9d9084776b6054443a3024190d0100000000000000000000000000000916222f3c4955626f7c7f8084888e9299a29f99928c80746d63574d4231281e130800000000000000000000000008141f2a343e464d51525353535353535761686b6c6c6c605c544a3f353a41464c52565d6065696b6c6b6965605c554e474953535353535353534f4940372c21160a00000000000000000000000000000810191f282f353e434b51565d60666c7074787b7e80828485858685858482807e7b7874706c66605d56514b433e352f281f1910080000000000000000000000000000000000000000000000000000000810191f282f353e434b51565d60666c7074787b7e80828485858685858482807e7b7874706c66605d56514b433e352f281f191008000000000000000000000000000000000000000000000000000000010b151f2a343d474f575e656c70767b7e8183848586858483817e7b756f6b605d564d453b33291f1208000000000000000000000000000000000000000000000000000000000000070e161e252a2f383f44464d5354555c60636567696a6b6c6c6c6b6b6a69686663615e575653504a45413a352f281f17110a020000000000000000000000000000000000000000000006111a202930363d44484f54565e6165666d6f7174757778787979787877767573716f6d6664605d56534e47433d352f281f1911090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a6d60544c4c4c4c4c4c4c4c4c4c4d4e4d5254535b60636a6e757e859195a0a7afa59d938b7f726a5f53493f30261c1106000000000000000000000000000000000000000000000a151f2c3845515c6773808d9aa4aa9d9184776a75828e9baaaa9d9084776b6054443a3024190d01000000000000000000000000000000000000000004101c2834404b55606d7a85929ea7b1a89d928a7e706a60585046423b36312d2c282327272728252a2d2e34383e434c545c666d7a84919c9896918d89857a6d6154473a2e21140700000915202b353f474e5253535353514948555f676a6c6c6c6c6c6c69665e54474851535353534846423c332a1f14090000000000000000111e2a3744515d6a7784909daab0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000c1825323f4b5865727e8b98a5b1a99c8f8276695c504336291d1000000000000000000000000000000004111d2935414c55626f7c88959faba6998d8073665c50444d5764717e8a97a2ada2988b7f7265594f4332281e13080000000000000000000000000000000e1a2734414d5a6774808c8d90959b9fa098928e877f746e645b51453c311f160c01000000000000000000000000020d18222c343b4144464646464646505c6873787979796d665c504441454c52565e61686d727678797876726d675f584e464646464646464646433e372e251b1005000000000000000000000000000000070d161e2429313a40454c52545b6063656c6e717476777879797978777674716e6c6563605b54524c4540393129241e160d070000000000000000000000000000000000000000000000000000000000070d161e2429313a40454c52545b6063656c6e717476777879797978777674716e6c6563605b54524c4540393129241e160d070000000000000000000000000000000000000000000000000000000000030d18222b353d454d535b6063696e71747677787978777674716e69636059524c433b332921170d0000000000000000000000000000000000000000000000000000000000000000050c13191d262d33373b4246484b515356585a5c5d5e5f5f5f5f5e5d5d5b595754534d4946443f38352f29241d160d0600000000000000000000000000000000000000000000000000080e171f252a33383d44484d5254545c60626567686a6b6b6c6c6c6b6a6a68666462605c5454524c47433c383229241d160d07000000000000000000000000000000000000000004080a0b1313131313131311110e0b060100000000000000000004090e11121313131313131313070705010000000000000000000000060b0e1011131313131313130a0a0804000000000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a6d6058585858585858585859595a5b565e6164656c70757c828a9297a0a8afa59e938e81746d62584e41382d1e150a000000000000000000000000000000000000000000000004101c2834404b55616e7b87939faca095887b6f7985929faca3988b7f7265594f4332281e1308000000000000000000000000000000000000000000000c18232e3945525d68727f8c959faaaea49f92867c6f6a625a524d46423c3a38342e343434353036393b3f444650565d666d78828f96a0a8a09e988d8074685e5246392d20130700000e1a26313d4751595e5f6060605e56544f555b5d6060606060605c5a544d53555d6060606055534d453c31261a0e0200000000000000101d2a3643505d697683909ca9b1a5988b7e7265584b3f3225180700000000000000000000000000000000000000000000000d1a2733404d5a6673808d99a6b3a89b8f8275685c4f4235291c0f000000000000000000000000000000010d19242f3a47545f6a7783909da9ab9e9184796d605346525e6976828f9ca9ac9f92867a6d6054473d3221160c020000000000000000000000000000000e1a2734414d5a6774808d9a9da0a7a0969186817b726d645c53493f332a1f0d04000000000000000000000000000006101a222a303538393939393945525e6b7885868686786d60534a4c51565e61686d737a7f82858685837f796f6a5f584e42382e393939393937332c251c13090000000000000000000000000000000000040c13191f282f353a41454a5053535b60626567696a6b6c6c6c6b6a69676562605b5353504a45413a352f281f19130c0400000000000000000000000000000000000000000000000000000000000000040c13191f282f353a41454a5053535b60626567696a6b6c6c6c6b6a69676562605b5353504a45413a352f281f19130c0400000000000000000000000000000000000000000000000000000000000000060f19232b333b41495053575f6164676a6b6b6c6c6b6a6764615e57544f45413a312921170f0500000000000000000000000000000000000000000000000000000000000000000002080b141b22272b31363a3b404547494c4e4f5152525353525151504e4c4a4846423d3a38342e29241e18130c04000000000000000000000000000000000000000000000000000000050d141a21272c33383b4246474a505355585a5c5d5e5f5f5f5f5e5e5d5b59575553504a4745413a37312b272018130c0400000000000000000000000000000000000000050c11141717202020202020201e1d1b17120c0400000000000000080f151a1d1f20202020202020201413110d080200000000000000040b11171a1d1e20202020202020171614100b0500000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a6d656565656565656565656566676869696e7074787d81878f939ea1a9aca49f938e81786d605b51463c2f261b0c030000000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9a7998c7f737d8a98a2ac9f92867a6d6054473d3221160c020000000000000000000000000000000000000000000007121d2935414c56606d78839098a2acaea29892857c716c615e57534d494645404141414141424146474a50535a61686d78818e949fa8b0a69f92857a6d61564c4135291d11050000111d2a36424e59636a6c6c6c6c6b636059514a51535353535353504e50575f626a6c6c6c6c6c5f574d42372b1e1205000000000000000f1b2835424e5b6875818e9ba8b3a6998c807366594d402f24180c00000000000000000000000000000000000000000000020e1b2835414e5b6874818e9ba7b4a79a8e8174675b4e4134281b0e0000000000000000000000000000000008131e2b37434e5865717e8b97a2ada1968a7d7063564c54616e7b87939faca79b8e8174685d5245392c201304000000000000000000000000000000000e1a2734414d5a6774808d9aa5a9aa9e91847d78716c605d554b43392f24180c050000000000000000000000000000000810181f25292b2c2d2d2d3643505d6976839098897c6f635a56555d60686d737a80858b8f9192928f8b847c6f6a5f544a3f34282d2d2d2d2b27211b130a0100000000000000000000000000000000000001080d161d24292f35383f444649505355585a5c5e5f5f605f5f5e5c5a585553504946443f38352f29241d160d080100000000000000000000000000000000000000000000000000000000000000000001080d161d24292f35383f444649505355585a5c5e5f5f605f5f5e5c5a585553504946443f38352f29241d160d080100000000000000000000000000000000000000000000000000000000000000000007111920292f383f44464d5355585b5d5e5f5f5f5e5d5a5854524d48443d352f281f170f05000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1f252a2d2f34383a3c3f4142444545464645454443413f3d3b3a36312d2c28231c19130d0701000000000000000000000000000000000000000000000000000000000002090e161c21272c30363a3b3f4446494b4d4f5051525253525251504f4d4a4846443f3a39352f2b26201b160d0701000000000000000000000000000000000000000810171c2123242d2d2d2d2d2d2d2b2a27231d160e06000000000009121920262a2c2c2d2d2d2d2d2d2d21201d19130c050000000000050e161d22272a2a2d2d2d2d2d2d2d2423201c171008000000000000000000000000000000000006131f2c3946525f6c7985929facada093877a72727272727272727272727273737576787a7d8184898e93999ea6ada8a19a938c81786d665c50493f342a1d140a0000000000000000000000000000000000000000000000000007121d2b37424d5764717d8a97a1aa9d908377818e9baaa79b8e8174685d5245392c2013040000000000000000000000000000000000000000000000000d19242f3a44505c666e7b86929aa4afaaa29792867e756e69615f575653514b4e4e4d4e4e4f4c5254545c60646c717a828e939ea6b0a89f948c7f72685e52443a3025190d010000121f2c3845525e6a757979797978706b605c544d4546464646434b515a61696e777979797976695f53463a2d211407000000000000000d1a2734404d5a6773808d9aa6b3a89b8e817568554b4035291d100400000000000000000000000000000000000000000005121e2b37424d57697683909ca9b2a5988c7f7265594c3f3226190c00000000000000000000000000000000010f1b26323c4753606d7985929faba99b8e8275685d525966737f8c99a4aca095897c6f63564c4135291d1104000000000000000000000000000000000e1a2734414d5a6774808d95999c9fa096918a847e756d675d554b40352921160b00000000000000000000000000000000060d14191c1f1f20202834414e5b6774818e9a8e81756c656364676d737a80868d92989c9e9f9e9c9691857c6f665c5044382b1f2020201e1b16100901000000000000000000000000000000000000000000040c13181e24292d3338393f4446484b4d4f515252535252514f4d4b4846443f3938332d29241e18120c0400000000000000000000000000000000000000000000000000000000000000000000000000040c13181e24292d3338393f4446484b4d4f515252535252514f4d4b4846443f3938332d29241e18120c04000000000000000000000000000000000000000000000000000000000000000000000000070e171d262d33373b4246484b4e505152535251504e4b4746423b383229241e160d05000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f141a1e2123292c2d303234363738393939383837363533302e2d2a25201f1c17110d0801000000000000000000000000000000000000000000000000000000000000000000050b10161c1f252a2d2e34383a3c3e414244454546464545444342403e3c3a38342e2c29241e1b150f0a04000000000000000000000000000000000000000008121a22282d3031393939393939393837332e2820180e0400000008121b242b31363839393939393939392e2d2a251e160e05000000040e1720272e3336373939393939393931302d28221a11080000000000000000000000000000000006131f2c3946525f6c7985929facb2a5988c7f7f7f7f7f7f7f7f7f7f7f7f7f7f80818385878a8d91969b9fa4ababa39f9691887f776d665c544a3f372d22180b0200000000000000000000000000000000000000000000000000000e1a26313c4653606d7984919eaba095887b85929faba095897c6f63564c4135291d110400000000000000000000000000000000000000000000000008131e28343f4a545f69717e88939fa3afa9a298928b827b746e696662605c545b5a5a5a5b5c565e6164666d71767e848f949ea5afaaa1968f82786c60564c4132281e130800000013202c3946535f6c7987868686847d736d665f575146413e454d555c606c717b83868686867b6e6155483b2e221508000000000000000c1825323f4b5865727e8b98abb5aa9d908477675d5145392c1f13060000000000000000000000000000000000000000000714212d3a46535f697885929fabb4aa968a7d7063574a3d3024170a00000000000000000000000000000000000a151f2c3945515d6774808d9aa6ac9f92867a6d6154606b7784919eabaa9d9084776b6054443a3024190d01000000000000000000000000000000000e1a2734414d5a67748087898c90949da09e96918a81796d675d51453d33271c10030000000000000000000000000000000002080d101213131825323f4b5865727e8b98938b7f75717071747a80858d92989fa2aaa4a3a5a8a1979083786d6053463a2f24190d13120f0a0500000000000000000000000000000000000000000000000001070d13191c22282b2d3337393b3e41434445464646454443413e3b3937332d2b28221c19130d070100000000000000000000000000000000000000000000000000000000000000000000000000000001070d13191c22282b2d3337393b3e41434445464646454443413e3b3937332d2b28221c19130d07010000000000000000000000000000000000000000000000000000000000000000000000000000050b141b22272b31363a3b3e4143444546454443413e3b3a36302c272119130c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214181c1f20232527292a2b2c2c2c2c2b2a2a28262421211e1a1312100c060000000000000000000000000000000000000000000000000000000000000000000000000000050b1014191e2023282c2d2f3234353738383939393837373533312f2d2b2823201d19130f0a0400000000000000000000000000000000000000000005101a242c33393c3e4646464646464644433f39322a20160c0100040f19242d353d42454646464646464646463936302820160c0200000b16202932393f4344464646464646463d3c39332c231a100500000000000000000000000000000006131f2c3946525f6c7985929facb8a79c918c8b8b8b8b8b8b8b8b8b8b8b8c8c8d8e909297979a9ea1a8acaba39f99928d847d736c655c544a42382e241b100600000000000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a4a79c8f828f97a2aa9d9084776b6054443a3024190d01000000000000000000000000000000000000000000000000010b17232e38424d57616c727f8c919fa3abaaa39f938f86817b76726f6d66696867676768686a686e7174797d838a91969fa6afa9a19891847a6d665b50443a3020160c020000000b1825323e4b5865717e8b9296918780786e69625b524c4550575f676d747e869095948d8074695f53463a2d211407000000000000000916232f3c4956626f7c8999a3afac9f92867a6d6053473a2d22170b0000000000000000000000000000000000000000000815222e3b4855616e7b8898a2aeaea298887b6e6155483b2e221508000000000000000000000000000000000004101d2935404b55626f7b88949faba3998b7e726557636f7c8996a0aca2988b7f7265594f4332281e130800000000000000000000000000000000000713202d3a4653606d787b7c7f838990959fa09d938e82796d60594f44382c1f1409000000000000000000000000000000000000000305060815222f3b4855626e7b88959b918b827e7d7e81858c92989fa2a29f9a9796989c9f9f958a7d7164554c4135291d110405020000000000000000000000000000000000000000000000000000000001080d11171c1f22272b2d2f323436373839393938373634322f2d2b27221f1c17110d08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080d11171c1f22272b2d2f323436373839393938373634322f2d2b27221f1c17110d08010000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1f262a2d2e31343738383939383734312e2d2a251f1b160d08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205070c10131416191b1c1e1f1f20201f1e1e1d1b19171514120e09060300000000000000000000000000000000000000000000000000000000000000000000000000000000000002090e1114171c1f20222527292a2b2c2c2c2c2b2b2a28262422201f1c1713110d080100000000000000000000000000000000000000000000000c17222c363e45494a53535353535353514f4b443c32281d1206000915202b353f474e5253535353535353535346413a32281e13080006111d27323b444a4f51535353535353534a49443e362c22170b00000000000000000000000000000006131f2c3946525f6c7985929facb8ada39c98989898989898989898989898999a9b9c9ea1a9a7aba9a8a19e99928e87817a706b605b534a423930261c12090000000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87939fac9e948f949ea9a3988b7f7265594f4332281e1308000000000000000000000000000000000000000000000000000006111c26303c45505a636d737f8b9299a1a8aea59e98928d87837f7c79777674747474747577787a7d81848a90949ea1a9afa8a19792867c6f685e544a3f32281e0e04000000000b1724313d4a56626d73808c9399938d837b726d615e56515a61696e79818a9298958f82786d60574d42372b1e1205000000000000000714202d3a4753606d7a86929facafa399897d7063544a3f33281c0f030000000000000000000000000000000000000004111d2935414c5665727e8b98aab3ab9f9285786c605346392d2013060000000000000000000000000000000000000c18242f3947535f6a7683909ca9ab9d908376695f6774818e9aa8ac9f92867a6d6054473d3221160c02000000000000000000000000000000000006121f2b3844505c666d6e6f72767c838f949fa59e948e81746b6054483b31251a0e020000000000000000000000000000000000000000000814212e3a47535f6a7784919d9b948f8b898a8d92989fa2a29f98928d8a898b90949c9c8f8276675d5145392c201306000000000000000000000000000000000000000000000000000000000000000000060b0f12171b1f20222527292b2c2c2d2c2c2b29272522201f1b17120f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f12171b1f20222527292b2c2c2d2c2c2b29272522201f1b17120f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f141a1e212225282a2b2c2c2c2b2a272521201e1a140f0b04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040607090c0e0f1112121313121211100e0c0a0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205060c10121316181a1c1d1e1f1f201f1f1e1d1c1a17151312100b06040100000000000000000000000000000000000000000000000004111c28333e48505557606060606060605e5c564e44392e23170b010e1a26313d4751595e5f606060606060605f524c443a3025190d010b17222e39444d555b5d60606060606060575550483e33281c1004000000000000000000000000000006131f2c3946525f6c7985929facacacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a6a6a8a9a8a6aba39f9c9996918c87817b746d6761595049413930271e140a0000000000000000000000000000000000000000000000000000000000000c17232e3846535e6975828f9ca8a69e9c9ea6ac9f92867a6d6054473d3221160c020000000000000000000000000000000000000000000000000000000a141e2a333e48515b636d737f8791969fa4acaaa29f9a93908c898684828181808181828385878a8e91979c9fa6adaca59d9691857c6f6a60564c42382d20160c00000000000915212e3a45505a636e74818e939f9590867e756d68605c606c717b838e939f969083796d665c50453c31261a0e020000000000000006131f2c3945515d677783909daab5ab9a8d8073665b5044382b1f140a000000000000000000000000000000000000010c13202c3945525d6875828f9ba8b5a89b8f8275665b5044382b1f120600000000000000000000000000000000000007121d2b37434e5864717e8a97a1ab9f95887b6e616d7985929faba79b8e8174685d5245392c20130400000000000000000000000000000000000003101c28343f4a545c606162666b6f79828f97a1a69d93897d7063574d42362a1e120500000000000000000000000000000000000000000006121e2b37424e5765727e8b95a09e9c9896979a9fa2a39f98928c85817e7d7e838c929f92867a6d6054473a2d211407000000000000000000000000000000000000000000000000000000000000000000000003060b0f121315181a1c1e1f1f201f1f1e1c1a181513120f0b0603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060b0f121315181a1c1e1f1f201f1f1e1c1a181513120f0b0603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e121415181b1d1e1f201f1e1d1b181414110e090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030607090b0e0f1112121313121211100f0d0b09070603000000000000000000000000000000000000000000000000000000000814212d3945505a61646c6c6c6c6c6c6c6b6760564b3f33271b0e04111d2a36424e59636a6c6c6c6c6c6c6c6c6c5e564c41362a1d11050e1a27333f4a555f676a6c6c6c6c6c6c6c64615a5044392d201408000000000000000000000000000006131f2c3946525f6c7985929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9f9e9d9c9b99979992908c89847f7b746e69605d554f443f382f271e150c0200000000000000000000000000000000000000000000000000000000000006111c2a36424d5763707d8a96a1acaaa8aab0a79b8e8174685d5245392c20130400000000000000000000000000000000000000000000000000000000020c18212c363f49515b636d727d848e939a9fa6acaca49f9d999992918f8e8d8d8d8e8f909298979a9ea1a9abaca7a09d938e847c6f6a60584e443a2f261c0e05000000000005111d29343f48525b606d78818f959f98928b827a706b676d747e8690959d9891847b6e675d544a3f332a1f1409000000000000000004101d2935404b556673808d99a9b3ab9e9184786c6053463d2f261c1106000000000000000000000000000000000008131e28343f4a54606d7a86929facb1a7988b7e7265544a3f33281c0f03000000000000000000000000000000000000010f1a26313c4653606d7985929eaca7998c7f7366717d8a98a2aca095897c6f63564c4135291d1104000000000000000000000000000000000000000b17232e38424a505354565960676d7a85919eaba59c8f8276695e53463a2d211407000000000000000000000000000000000000000000020e1a26313c4653606c78839097a1a8a4a3a4aaa29f98928d86807a74717072767f8c94998a7d7063574a3d3024170a0000000000000000000000000000000000000000000000000000000000000000000000000000030506080b0e1011121313131211100e0b080605030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030506080b0e1011121313131211100e0b0806050300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507080b0e101112131211100e0b0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001040613131313131313130d0c0a070200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303c4955616c71797979797979797772675c4f43372a1d1106121f2c3845525e6a75797979797979797976685e5246392d201307101d2a36434f5b67717779797979797979706c6155493c3023160a000000000000000000000000000006131f2c3946525f6c798592939393939393939393939393939393939398929291918f8e8d8b8886837f7c78736e69615f57514c433e332d261d150c0300000000000000000000000000000000000000000000000000000000000000000e1a25313b4653606c7884919e9f9f9f9f9fa095897c6f63564c4135291d11040000000000000000000000000000000000000000000000000000000000060f1a242d374049515b626b6f7a818790949b9fa3ababa9aba39f9d9c9b9a9a9a9b9b9d9fa2aaa7ababaca49f9c959189817a6e6a60584e463d32281d140a000000000000010c18222d364044505c666d79829095a09f938f857d746f79818a9298a09992867c6f695e554b42382e21180e030000000000000000000c18242f3c4956636f7c8997a1adada196897d7063584e42382d22170f06000000000000000000000000000000081119242f3844505c66727e8b98a3aeaca095877b6e6154483b2d22170b00000000000000000000000000000000000000000a151f2c3845515c6773808d9aa4aa9d9184776a75828e9baaaa9d9084776b6054443a3024190d010000000000000000000000000000000000000006111c2630383f444647494f555e68727f8c99a3ab9f94877b6e6154483b2e2115080000000000000000000000000000000000000000000009151f2b3844505b666f7c8591969c9f9f9e9c98928d86807a736d686463656d76828f998d8073665a4d4033271a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070d111320202020202020201a1917130e0700000000000000000000000000000000000000000000000000000000000000000000000000000000000002080c101212131313131313131306040000000000000000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717e8686868686868684776b5e5144382b1e110613202c3946535f6c7987868686868686867a6d6154473a2e211407111e2a3744515d6a7783868686868686867e7064574a3d3124170a000000000000000000000000000006131f2c3946525f6c798686868686868686868686868686868686868686858585848381807e7c7976736f6c65615e57534d45413a3127221b140b0300000000000000000000000000000000000000000000000000000000000000000009141f2b3844505b66737f8c999393939393939084776b6054443a3024190d0100000000000000000000000000000000000000000000000000000000000008121c252e374048515960686d757c83898e92999b9fa2a9a6a8a9a9a7a7a7a7a7a8aaa9a8a6aaa29f9c9a938f89847d746d685f584e463d342b20160b020000000000000006111b2428343f4a545d676d7a839196a19e979188807b838e929fa29f93877d706a5f574d433a30261c0f06000000000000000000000713202d3a4653606d7985919eabb2a89c8f82766a60544a3f3328211810080200000000000000000000000309111a232935414c56606d7884919eaab3a99d908377695e53463a2d1c1106000000000000000000000000000000000000000004101c2834404b55616e7b87939faca095887b6f7985929faca3988b7f7265594f4332281e13080000000000000000000000000000000000000000000a141e262e34383a3b3d434c56606d7a86929faca6978a7e7164574b3e3124180b00000000000000000000000000000000000000000000030f1c28333f4a545f6a6f7c848c909292918f8b86807b746e68605d56565b64707d8a998f8275685c4f4235291c0f0200000000000000000000000000050a0d0f10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100f0d0a05000000000000000000000000000000000000000000000105090b0b131313131309090703000000000000000003070b0d0e1313131311100e0a0600000306080913131313100f0d09040004090e111213131313130a090704000000000000000000000000000000000003080b0d0e13131313070604000000000000000005090d0f1013131312110f0c07010000000000000000000000000000000000000000000000000000000000000000040c13181d202d2d2d2d2d2d2d2d2626231f19120a01000000000000000000000000000000000000000000000000000000000000000000000000000000060d13181c1e1f202020202020202013100c07010000000000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a93939393939184776b5e5144382b1e110613202c3946535f6c7986929393939393877a6d6154473a2e211407111e2a3744515d6a77849093939393938a7d7064574a3d3124170a000000000000000000000000000005121f2b3844515d6974797979797979797979797979797979797979797979787877767573716f6d666662605b53534d47423c352f281f17110a0200000000000000000000000000000000000000000000000000000000000000000000030f1c28333f4a54616e7a8786868686868686867f7265594f4332281e130800000000000000000000000000000000000000000000000000000000000000000a131c252e363f474f565d606a6f767c81868b8e929797999b9c9e9e9f9f9f9e9e9d9d9b999798928f8b87827d78706b605d564e463c342b22190e05000000000000000000091217232e38424b555d686e7b849197a2a19a938d8890959da59d928b7f726b61584e453b31281e140a000000000000000000000006121f2b3844505c6673808d99a4afaa9f94897c6f665b50443d332a2219140e09060400000100000406090e151a232b353d45525d68717e8b96a0acada1978b7e7165574d42362a1e0a000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9a7998c7f737d8a98a2ac9f92867a6d6054473d3221160c02000000000000000000000000000000000000000000020c141c23282b2d2e313a45525d687783909daaa6998d8073665a4d4033271a0d00000000000000000000000000000000000000000000000b17222d38424e585f6a6f797f83858684827f7a736e69615e56524c4a54606d7987868683776a5e5144372b1e11040000000000000000000000030a1016191c1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1c1916100a0300000000000000000000000000000000000000060c1115171820202020201615130f0a040000000001080e13171a1a202020201e1d1a16110b0a0f131516202020201c1b1915100a0f151a1d1f2020202020171614100b050000000000000000000000000001080e14171a1b202020201413100c0701000000020a1015191c1c2020201f1e1b18130c05000000000000000000000000000000000000000000000000000000000000040d161d24292c393939393939393933322f2a241c130a00000000000000000000000000000000000000000000000000000000000000000000000000000710181f24282b2c2d2d2d2d2d2d2d2d1f1c18120b0300000000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a979f9f9f9e9184776b5e5144382b1e110613202c3946535f6c7986929f9f9f9f94877a6d6154473a2e211407111e2a3744515d6a7784909d9f9f9f978a7d7064574a3d3124170a000000000000000000000000000003101c2935414d5862696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a6968666462605c545653504946423b373129241e160d06000000000000000000000000000000000000000000000000000000000000000000000000000b17222d3846525e686e797979797979797979726d6256473d3220160c020000000000000000000000000000000000000000000000000000000000000000010a131c242d353d444c525860626a6f757a7e8285888a8d8e909192929292929191908e8c8a8985827f7b75706c656059524c433c332b22191007000000000000000000000006111c263039434c565e696f7c859299a3a49f9a959da0a79e948d80746d62594f463c33291f160c02000000000000000000000003101c28343f4a54616e7b87939fabb0a69d9083786c60594f453c342a251f1a1312100c070e070c1013131a1f262b353d47505a606d7a84919ea8b2a99e9285796d6053473b31251a0e0000000000000000000000000000000000000000000007121d2b37424d5764717d8a97a1aa9d908377818e9baaa79b8e8174685d5245392c2013040000000000000000000000000000000000000000000000020a11171c1f20212935414c566774818e9aa7a79a8d8174675a4e4134271b0e010000000000000000000000000000000000000000000006111c262f3c464e585f676d727678797876726d68615e56524c454145515d67757979797771675b4f43362a1d100400000000000000000000040d151c21262929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292926211c150d0400000000000000000000000000000000000911181d2124252d2d2d2d2d23221f1b160f070000020b12191f2326272d2d2d2d2a2927221c15151b1f22232d2d2d2d292825211b141920262a2c2c2d2d2d2d2423201c1610080000000000000000000000020b131a1f2426272d2d2d2c201f1d18120b0300040c141b212528292d2d2d2b2a28231e170f0600000000000000000000000000000000000000000000000000000000010c161f282f35394646464646464646403f3b352e261c120700000000000000000000000000000000000000000000000000000000000000000000000006101922293035383939393939393939392c29231d150d03000000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4acaa9e9184776b5e5144382b1e110613202c3946535f6c7986929facaca094877a6d6154473a2e211407111e2a3744515d6a7784909daaaca3978a7d7064574a3d3124170a0000000000000000000000000000000d1925303b4650585d5f606060606060606060606060606060606060605f5f5e5e5c5b5a585553514b4946443f3836312b261f19130c04000000000000000000000000000000000000000000000000000000000000000000000000000006111c2a36414d565e616c6c6c6c6c6c6c6c6c65625b5146342b210e0400000000000000000000000000000000000000000000000000000000000000000000010a121b232b323a41454e54586062686d7175797b7e80818384858586858584848381807e7c7975726e6963605b534f45413a312a21191007000000000000000000000000000a141e27313a444d575f6a707d879299a49f9f9f9fa9a0958f82786d605b51473e342a21170d04000000000000000000000000000b17232e3846535e6975818e99a3aeab9f958b7f726b60574e463e36302a25201f1c181b1a1b181c1f20262b31373f474f59626c74818e97a1adada1978d8073675c514538291f140900000000000000000000000000000000000000000000000e1a26313c4653606d7984919eaba095887b85929faba095897c6f63564c4135291d110400000000000000000000000000000000000000000000000000060b10121319242f404d5a6673808d99a6a79b8e8174685b4e4135281b0e0200000000000000000000000000000000000000000000000a141d2a343c464e555d6065696c6c6b6965615e56524d46413b35414b555d6b6c6c6c6a675f564b3f33271b0e02000000000000000000030d161f262d3235363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363635322d261f160d0300000000000000000000000000000009121b22292e31323939393939302f2c2721191007010b141d242b303334393939393736332e271f20272b2e2f393939393635312c261e242b3136383939393939302f2c28211a1108000000000000000000010b141d242b303334393939392d2c29241d150d030c161e262d3235363939393837342f2921180f0000000000000000000000000000000000000000000000000000000007131d28313a404553535353535353534d4b4740382e24190e0200000000000000000000000000000000000000000000000000000000000000000000020d18222b343b414445464646464646464638342f271f150b010000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0aa9e9184776b5e5144382b1e110613202c3946535f6c7986929facada094877a6d6154473a2e211407111e2a3744515d6a7784909daab0a3978a7d7064574a3d3124170a00000000000000000000000000000008141f2a343e464d51525353535353535353535353535353535353535352525251504e4d4b494645403c3937332d2a251f1a150d0801000000000000000000000000000000000000000000000000000000000000000000000000000000000e1925303b444d52545f6060606060606060585651493f3422190f00000000000000000000000000000000000000000000000000000000000000000000000000091119202830353d43474e54565e6164656c6e717375767778797979787877767573716f6d6665615f57535049413d352f281f180f070000000000000000000000000000020c151f28323b454e58606b717e8793939393939393969083796d665c50493f352c22190f05000000000000000000000000000006111c2a36424d57616e7b86929fa8b1a79f92877d6f6a5f585046413b36312d2c282327272723282c2d31373c42475159606b717e8b939da9b1a79e92857a6d61554b4034291c1004000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a4a79c8f828f97a2aa9d9084776b6054443a3024190d010000000000000000000000000000000000000000000000000000000306081926323f4c5965727f8c98a5a79b8e8174685b4e4135281b0e020000000000000000000000000000000000000000000000020b18222a343c434b5154595d5f5f5e5c5854524c46423b36302f3a434b515e6060605e5b564d44392e22170b000000000000000000000a151f2831383e424343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343423e3831281f150a000000000000000000000000000006111b242d343a3d3e46464646463c3b38322b23190f08121d262f363c3f414646464644423f3931292b32373b3c4646464643413d3830282d353d424546464646463d3c38332c231a1005000000000000000008131d262f363c4041464646463a39352f271f150b141e2830383e41434646464544403a332a210f050000000000000000000000000000000000000000000000000000010d18242f3a434b515f606060606060605957524a40352a1f13070000000000000000000000000000000000000000000000000000000000000000000008131f29343d464c5152535353535353535345403931271d12070000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4acaa9e9184776b5e5144382b1e110613202c3946535f6c7986929facaca094877a6d6154473a2e211407111e2a3744515d6a7784909daaaca3978a7d7064574a3d3124170a000000000000000000000000000000020d18222c343b41444646464646464646464646464646464646464646464545444342403e3c3a38342e2d2b27221b1a140e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000008141f29323b4146475353535353535353534c4a463f372d2310070000000000000000000000000000000000000000000000000000000000000000000000000000070e161e242932373d43484c5254535b6062646668696b6b6c6c6c6b6b6a6a68666462605c5455534d46443f382f29241e160d0600000000000000000000000000000000030d162029333c464f59616c727f8686868686868686847b6e675d544a3f372d231a1007000000000000000000000000000000000e1a25313b46535f6973808d96a0abaea39991857c6f6a615a524d46423c3a38342e3434342e34383a3c42474d535b626b707d86929fa5afaa9f958b7e71685e5243392f23180c00000000000000000000000000000000000000000000000003101c28343f4a54616e7b87939fac9e948f949ea9a3988b7f7265594f4332281e13080000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e02000000000000000000000000000000000000000000000000061018222a313a4145474c50525352504c4746413a36302a2528313a414547535353514f4b443b32281d110600000000000000000005101c26313a42494e50505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050504e49423a31261c1005000000000000000000000000010c18222d363f454a4b53535353534948433d352b21160e19242f3840474c4d53535353514f4a433b31343d434749535353534f4e49423a30353f474e5253535353534a48443e352c21160b00000000000000030e1a242f3841474c4e535353534745403931271d121b26303a42494e4f53535352504c453c3321170d030000000000000000000000000000000000000000000000000004111d2935404b555d6c6c6c6c6c6c6c6c66635c52473b2f23170a000000000000000000000000000000000000000000000000000000000000000000000c1824303b464f575d5f606060606060605f514b43392f23180c0000000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a979f9f9f9e9184776b5e5144382b1e110613202c3946535f6c7986929f9f9f9f94877a6d6154473a2e211407111e2a3744515d6a7784909d9f9f9f978a7d7064574a3d3124170a0000000000000000000000000000000006101a222a303538393939393939393939393939393939393939393939393837363533312f2d2c2823201f1b17110e09030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d1720293036393b4646464646464646463f3e3a342d251b1100000000000000000000000000000000000000000000000000000000000000000000000000000000040c131920272b32383a41464749505355575a5b5d5e5f5f5f5f5f5e5e5d5b59575653514a4846423b37332d261d19130c04000000000000000000000000000000000000040e17212a343d47505a626d727979797979797979786e695e554b42382e251b1108000000000000000000000000000000000009141f2a36424d57606d79849199a3afaba19791857c716c615e56534d494644404141414141404546494e53575f616d727d869298a3aeaba2989083776c60564c4131271d1207000000000000000000000000000000000000000000000000000c17232e3846535e6975828f9ca8a69e9c9ea6ac9f92867a6d6054473d3221160c020000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e02000000000000000000000000000000000000000000000000000610181f282f35393a3f43454645433f3a3936302a251f191f282f35393a46464644433f39322920160b000000000000000000000a16212d38424c545a5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5a544c42382d21160a00000000000000000000000005111d29343f48505658606060606056544f473d32271b131f2b36404a52585a606060605d5b554d43393d464e5456606060605c5a544c42333d4751595e5f6060606057554f473e33281c100400000000000008141f2b36414a52585a6060605f5e514b43392f2418212d38424c545a5c6060605e5c574f4533291f1409000000000000000000000000000000000000000000000000000613202c3945515d677679797979797979736e63574b3f3226190c00000000000000000000000000000000000000000000000000000000000000000003101c2835414c5761696c6c6c6c6c6c6c6c6c5c554b4034291c100400000000000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a93939393939184776b5e5144382b1e110613202c3946535f6c7986929393939393877a6d6154473a2e211407111e2a3744515d6a77849093939393938a7d7064574a3d3124170a00000000000000000000000000000000000810181f25292b2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2b2b2928272522201f1c1813120f0b06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e171f252a2d2e39393939393939393932312e29231b1309000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d151b21272c3035393a3f4446484b4d4e505152525352525151504e4d4b494644403b3a36312b27221b140b08010000000000000000000000000000000000000000050f18222b353e48515b62656c6c6c6c6c6c6c6c6b615e574d433a30261c1309000000000000000000000000000000000000030e1a26313b45515d676f7c87929fa4aea9a19791867e756e68615e575653514a4e4e4d4e4e4b515356575f62696e767f879298a2aaafa39992857c6e655b50443a301f150b010000000000000000000000000000000000000000000000000006111c2a36424d5763707d8a96a1acaaa8aab0a79b8e8174685d5245392c201304000000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e020000000000000000000000000000000000000000000000000000060d161d24292c2d323639393836322e2d2a251e19140d161d24292c2d3939393736332e2820170e04000000000000000000000d1926323e49545e666969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969665e54493e3226190d0000000000000000000000000915212e3a45505a62656c6c6c6c6c6360594f43382c1f1723303c47525c64676c6c6c6c6a675f554a3f434e5860626c6c6c6c69655e54453b424e59636a6c6c6c6c6c6361594f44382c2014070000000000000b1724303c47525c64676c6c6c6c6a5d554b4035291d25323e49545e66696c6c6c6b686157453b31251a0e020000000000000000000000000000000000000000000000000714202d3a4753606d7986868686868686807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000005121e2b3844515d6973787979797979797976675c5145382c1f130600000000000000000000000000000000000000000000000000000000000b1724313e4a5764717e8686868686868684776b5e5144382b1e110613202c3946535f6c7987868686868686867a6d6154473a2e211407111e2a3744515d6a7783868686868686867e7064574a3d3124170a000000000000000000000000000000000000060d14191c1f1f202020202020202020202020202020202020201f1f1f1e1d1b1a18161313100c070503000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d14191e20212c2d2d2d2d2d2d2d2d2524221e1811090100000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f161b1e25292d2d3337393b3e40424344454646464545444342403e3c3a38342e2d2a261f1b17110a020000000000000000000000000000000000000000000000061019232c363f4951565860606060606060605e54524d453b31281e140a010000000000000000000000000000000000000009141f2935404b55606a717e8b929ca4afa9a198928a817b746e696562605c545b5a5a5a5b545c6063666a6e747b828b9299a2aaaca49f92877d706a5f53493f32281e0d030000000000000000000000000000000000000000000000000003090e1a25313b4653606c7884919e9f9f9f9f9fa095897c6f63564c4135291d1109030000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e02000000000000000000000000000000000000000000000000000000040c13181d2021262a2c2c2b292521201d19130e09040c13181d20212d2d2d2b2a27221d160e0500000000000000000000000f1c2935424e5a6670767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767670665a4e4235291c0f0000000000000000000000000b1724313d4a56626c7179797979796f6b6054483b2f221a26333f4c58646e74797979797771675b4f424754606a6f79797979767065574d4245525e6a757979797979706b6155483c2f2316090000000000000d1a2633404c58646e747979797975675d5145392c1f2835414e5a667076797979787368574d42362a1e12050000000000000000000000000000000000000000000000000714202d3a4753606d7a8693939393938c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c788586868686868686796d6053473a2d20140700000000000000000000000000000000000000000000000000000000000a1723303c4955616c71797979797979797772675c4f43372a1d1106121f2c3845525e6a75797979797979797976685e5246392d201307101d2a36434f5b67717779797979797979706c6155493c3023160a0000000000000000000000000000000000000002080d1012131313131313131313131313131313131313131313121211100f0d0b09070604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e111414202020202020202020191816120d060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f13191d2022272b2d2f313335363838393939383837373533312f2d2c2823211e1a140f0b06000000000000000000000000000000000000000000000000000007111a242d373f464a4c5353535353535353524846423b33291f160c020000000000000000000000000000000000000000030c18242f39434e58626d73808d929fa4acaaa29f938e86807b76726f6d6669686767676869666d6f72777b81868f949fa3ababa39a938c7f726b61584e41382d20160c00000000000000000000000000000000000000000000000000050d141a1e212b3844505b66737f8c999393939393939084776b6054443a30241e1a140d0500000000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e020000000000000000000000000000000000000000000000000000000001070d111314191d1f201f1d191413110d0802000001070d1113142020201e1d1b17110b04000000000000000000000000101d293643505c6976828383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838276695c504336291d100000000000000000000000000b1825323e4b5865717e86868686867d6f6356493c30231a2734414d5a6774808686868683776a5d51404b55626f7c868686868276695e534646535f6c7987868686867d7063574a3d3024170a0000000000010e1b2734414e5a67748086868687796d6053473a2d202936434f5c6976828686868578695e53463a2d2114070000000000000000000000000000000000000000000000000714202d3a4753606d7a86939f9f9f998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929393939393867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000814212d3945505a61646c6c6c6c6c6c6c6b6760564b3f33271b0e04111d2a36424e59636a6c6c6c6c6c6c6c6c6c5e564c41362a1d11050e1a27333f4a555f676a6c6c6c6c6c6c6c64615a5044392d201408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507081313131313131313130c0b090601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d1113171b1f20222427282a2b2c2c2c2c2c2b2b2a28262423201f1c1814120e0903000000000000000000000000000000000000000000000000000000000008121b252d343a3e3f4646464646464646453b3a36302921170d040000000000000000000000000000000000000000000007121d27313d46505a636e73808c939aa1a9aea59e98928d87837f7c79777674747474747677797c7f83888e92999fa6afa8a09992887f726d62594f463c2f261b0e04000000000000000000000000000000000000000000000000050f171f252a2d2e333f4a54616e7a8786868686868686867f7265594f43322e2d2a251f170f05000000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e02000000000000000000000000000000000000000000000000000000000000010406070c10121312100c070705010000000000000104060713131311100e0b06000000000000000000000000000013202d394653606c79868f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f86796c605346392d20130000000000000000000000000b1825323e4b5865717e8b939393897c6f6356493c30231a2734414d5a6774808d93939084776a5d5145515d6774818e939393877b6e61544a3f535f6c79869293938a7d7063574a3d3024170a0000000000000b1825313e4b5864717e8b9399897c6f6356493c30232633404d596673808c9397877b6e6154483b2e2115070000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0aca6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929f9f9f9f93867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000004111c28333e48505557606060606060605e5c564e44392e23170b010e1a26313d4751595e5f606060606060605f524c443a3025190d010b17222e39444d555b5d60606060606060575550483e33281c1004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105060b0f121315181a1b1d1e1f1f201f1f1e1e1d1b1a18161312100c070502000000000000000000000000000000000000000000000000000000000000000009131b23292e31323939393939393939382e2d2a251f170f050000000000000000000000000000000000000000000000010b151f2b343f48525c646e737f8892979ea5acaaa29f9a93908c898684828181808181828486898c90959b9fa3ababa39f9691877e726d635b51473e332a1d140a000000000000000000000000000000000000000000000000030d17212931363a3b464646525e686e797979797979797979726d62564746463b3a36312921170d030000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202d394653606c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9386796c605346392d20130000000000000000000000000b1825323e4b5865717e8b989f96897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5d514753606d7a85929fa4998c8073665c5044535f6c7986929f968a7d7063574a3d3024170a0000000000000915222f3c4855626f7b8898988c7f7265594c3f302424303d4a5763707d8a96978a7e7164574a3e2e23180c0000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabaca093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000c17222c363e45494a53535353535353514f4b443c32281d1206000915202b353f474e5253535353535353535346413a32281e13080006111d27323b444a4f51535353535353534a49443e362c22170b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060809131313131312070705010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105090b0b1313131313130d0d0b07070b0d0d1313131313130b0b09050100000000000000000000000000000000000000000000000000000000000000000000030506080b0d0f101112131313121211100f0d0b09070604000000000000000000000000000000000000000000000000000000000000000000000000010911181e2224252d2d2d2d2d2d2d2d2b21201e1a140d0500000000000000000000000000000000000000000000000000030d19222d36404a525c646d727d858f939da0a7acaca49f9c989892918f8e8d8d8d8e8f919299999da0a7acaca49f99928d847d716c635b51493f352c21180b0200000000000000000000000000000000000000000000000009141f29333b4246485353534d565e616c6c6c6c6c6c6c6c6c65625b515353534846423b33291f14090000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e02000000000000000000000000000000000000000000000000000000000000000003070b0d0e13131313131312100d0a06050300000000000000000000000000000000000000000000000000000013202d394653606c7986939f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9386796c605346392d20130000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5d514e5764717e8b98a2ab9e9184796d605346535f6c7986929f968a7d7063574a3d3024170a0000000000000613202d394653606c7985929b8e817568564c413529212e3a4754616d7a87969a8d807467544b4034281c100400000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000005101a242c33393c3e4646464646464644433f39322a20160c0100040f19242d353d42454646464646464646463936302820160c0200000b16202932393f4344464646464646463d3c39332c231a100500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f12151520202020201f1413110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c111517182020202020201a1917131317191a202020202020181715110c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d1216181920202020202020201f1514120e090200000000000000000000000000000000000000000000000000000007101b242e38404a525b636b707a828990959c9fa4abaca9aaa39f9d9c9b9a9a9a9b9c9d9fa3abaaababa39f9a938f8780796f6b615a51493f372d231a0f06000000000000000000000000000000000000000000000000020e1a25313b454d535f6060606060605d5f60606060606060605c6060606060605f534d453b31251a0e0200000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000000000000000000000000000000000000000000001080e13171a1a20202020201f1e1d1a1613120f0b060000000000000000000000000000000000000000000000000013202d394653606c798693939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939386796c605346392d20130000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5d51535f6a7683909caaa9a1978a7d7064574d535f6c7986929f968a7d7063574a3d3024170a00000000000006121f2b3844505b6676838f9c918477685d5246392d202d3946525e687884919d908376665c5145382c1f130600000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000008121a22282d3031393939393939393837332e2820180e0400000008121b242b31363839393939393939392e2d2a251e160e05000000040e1720272e3336373939393939393931302d28221a110800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e151b1f21222c2d2d2d2d2c21201d19130c04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000911181d2124252d2d2d2d2d2d2726231f1f2326272d2d2d2d2d2d2524211d1811090000000000000000000000000000000000000000000000020608080b0e1011121313131312100f0d0a0706040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000106090b0c1313131313131313120807050200000000000000000000000000000000000000000000000000000000000009121c262e384049515961686e757d83898f93999c9fa2aaa7a8aaa9a7a7a7a7a7a9a9a8a6a9a19e9b99928e87827c736d67605950483f372d251b11080000000000000000000000000000000000000000000000000005121e2a36424d575e6c6c6c6c6c6c6c6a665f55535353545e66696c6c6c6c6c6c6c5e574d42362a1e120500000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e020000000000000000000000000000000000000000000000000000000000020b12191f2326272d2d2d2d2d2c2b2a2723201f1b17110a02000000000000000000000000000000000000000000000013202d394653606c798686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c605346392d20130000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5d4a54626e7b88949f9f9c9f9c8f8276695e53535f6c7986929f968a7d7063574a3d3024170a000000000000030f1c28333f4a546773808d9a96877a6d6154473a2e212a36414c566875818e9b9286796d6053463a2d20130700000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000810171c2123242d2d2d2d2d2d2d2b2a27231d160e06000000000009121920262a2c2c2d2d2d2d2d2d2d21201d19130c050000000000050e161d22272a2a2d2d2d2d2d2d2d2423201c1710080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101820262b2e2f3939393939382e2d29251e160e04000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b22292e313239393939393934332f2b2b2f333439393939393932312e29221b1209000000000000000000000000000000000000000306090f121415181a1c1e1f1f20201f1e1d1c19171413100d0704000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141c262e373f474f565e616b70777d82878b8f9298989a9b9d9e9e9f9f9f9e9d9d9b999797928e8a86817b756f6a605d554f473e362d251c130900000000000000000000000000000000000000000000000000000714212d3a46535e69767979797979797771665b4f464e5a66707679797979797976695e53463a2d21140700000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e0200000000000000000000000000000000000000000000000000000000010b141d242b303334393939393939383734302d2b27221b140b080000000000000000000000000000000000000000000013202d3946535f6c767979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979766c5f5346392d20130000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5d515c6673808d9a9f948f949f93877b6e61544a5f6c7986929f968a7d7063574a3d3024170a000000000000000b17222d3e4a5764717d8a9796897d7063564a3d302325303f4c5965727f8c9898897c6f6256493c2f23160800000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000050c11141717202020202020201e1d1b17120c0400000000000000080f151a1d1f20202020202020201413110d080200000000000000040b11171a1d1e20202020202020171614100b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e18222a31373a3c4646464646453a3935302820160c0200000000000000000000000000000000000000000000000000000000000000000000000000000006111b242d343a3d3e464646464646403f3b36363b3f404646464646463e3d3a342d241b110600000000000000000000000000000000040a0f13151a1f21222527292a2c2c2d2c2c2b2a28262320201d1813100c0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000406070a0d0f11121313131212100e0c0906060300000000000000000000000000000000000000000000000000000000000000020a141c252e353d444c525960636b70757b7e8285888b8d8f9091929292929191908e8c8a8885817d7a746e6a626058514b433d352c241c130a0100000000000000000000000000000000000000000000000000000815212e3b4854616e7b86868686868683776a5d50444f5c6976828686868686867b6e6154483b2e21150800000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0e020000000000000000000000000000000000000000000000000000000008121d262f363c3f414646464646464543403d3937332d261d1a110a010000000000000000000000000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e120000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5d53606d7985929e978f828f99998c8073665c505f6c7986929f968a7d7063574a3d3024170a000000000000000615212e3b4854616e7b8797998c7f7366594c40302523303c4956636f7c8999988b7f7265584c3f3025190d01060606000000000000000000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000004080a0b1313131313131311110e0b060100000000000000000004090e11121313131313131313070705010000000000000000000000060b0e1011131313131313130a0a08040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15202a343c4347485353535353524746413a32281e13080000000000000000000000000000000000000000000000000000000000000000000000000000010c18222d363f454a4b5353535353534d4c474040474c4d5353535353534b4a453f362d22180c0100000000000000000000000000040a0f151b1f21262b2e2f32343637383939393938373533302d2c29241f1c18120c0700000000000000000000000000000000000000000000000000000000000000000000000000000001070c10131416191c1d1f1f20201f1e1d1b191613120f0b06000000000000000000000000000000000000000000000000000000000000020a131c232c323b41464f54596063686e7276797c7e808283848585868585848382807d7b7974716d68625f58544e454039312b231a120a010000000000000000000000000000000000000000000000000000000815212e3b4854616e7b87939393939083776a5d50444f5c6976828f93939393877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a79b8e8174685b4e4135281b0709080603000000000000000000000000000000000000000000000000030e19242f3840474c4d53535353535251504d4946443f382f2b231c130a01000000000000000000000000000000000000000f1b27333e49525a5f60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605f5a52493e33271b0f0000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5d5764707d8a979e92857a86929e9184796d60535f6c7986929f968a7d7063574a3d3024170a000000000000030714212d3a46535e697885929b8f827568574d42362a202d3a4753606d7a86929b8e817568564c41362a1d11131313130b0b09050100000000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b26313c464e53555f606060605f54524c443a3025190c030000000000000000000000000000000000000000000000000000000000000000000000000005111d29343f485056586060606060605a58524a4a52585a606060606060585650483f34291d1105000000000000000000000001070d161b20262b2e31373a3b3e4143444546464646454342403d3a39352f2c28231d18120b030000000000000000000000000000000000000000000000000000000000000000000000040a0f12181c1f202326282a2b2c2c2c2c2b2a282523201f1c17110f0a0300000000000000000000000000000000000000000000000000000000010a111a202930363d44484f54565e6165666d6f7174757778787979787877767573716f6d6664605d56534e47433c352f271f19110800000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b87949f9f9d9083776a5d50444f5c6976828f9c9f9f94877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a89b8e8275685b4f422f2418191615130f0a040000000000000000000000000000000000000000000007131f2b36404a52585a60606060605f5e5d5a56535049413d352e251c130a000000000000000000000000000000000000000a16212c3740494f535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534f4940372c21160a0000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5d5e6975828f9c9a8d8075828f9b978a7d7064575f6c7986929f968a7d7063574a3d3024170a0000000001090f14181e2a36424d576975828f9c918578695e52463a2d202c3845515d677783909d918477685e5246392d202020202020181715110c06000000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0e1111131313131313131308070502000000000000000000000105090b0c13131313131313130f0e0c08040000000000000000000000000000000000000000000000000004090c0e0f131313131313130c0b09060100000000000000000000000000000004090c0e0f1313131313131310060503000000000000000006121f2b37434e585f626c6c6c6c6c6b615e564c4135291e150b000000000000000000000000000000000000000000000000000000000000000000000000000915212e3a45505a62656c6c6c6c6c6c67645c52525c64676c6c6c6c6c6c65625a50453a2e21150900000000000000000000040c131820272b32373b3c4347484b4d4f51525253535251504f4c4a4745403a38342e28231c150c070000000000000000000000000000000000000000000000000000000000000000040a0f161b1d23292c2d303335373839393939383635322f2d2b28221c1b150e090300000000000000000000000000000000000000000000000000000000080e171e252a32383d44484d5254545c60626567686a6b6b6c6c6c6b6a6a68666462605c5454524c47433c373229241d150d070000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8794a1aa9d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5a99c8f827669554b403529252522221f1b150e070000000000000000000000000000000000000000000b1723303c47525c64676c6c6c6c6c6c6b6a6763605b534f473f372e251c100700000000000000000000000000000000000005101b252e373e4346464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646433e372e251b10050000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a53616e7b87939f95887c707d8a979c8f8276695e5f6c7986929f968a7d7063574a3d3024170a000000030b131a2024272531404c5966737f8c9997877b6e6154483b2e2d2935404b556774818d9a96877a6d6154473a2e2d2d2d2d2d2d2524211d1811090000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000040b12171b1d1e20202020202020201514120e090300000000000000060c1115171820202020202020201b1b18140f090100000000000000000000000000000000000000000002091015191b1c20202020202020191816120d0700000000000000000000000002091015191b1c202020202020201c13120f0b060000000000000815212e3a47535f6a6f7979797979786d685e52463d30271c12070000000000000000000000000000000000000000000000000000000000000000000000000b1724313d4a56626c71797979797979736e645858646e73797979797979716c62564a3d3124170b000000000000000000060d161d242932383c4347494e5355585a5c5d5f5f605f5f5e5d5b595653514b46454039342e271e191009010000000000000000000000000000000000000000000000000000000000060b151b21272c2f34383a3d40424445464646454543413f3c3938332d2b26201a150b0600000000000000000000000000000000000000000000000000000000050d141921272c33383b4146474a505355585a5c5d5e5f5f5f5f5e5e5d5b59575553504a4745413a37312b272018120b03000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8794a1a99d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4aa9e918477675d5145392f32322f2e2b262019100700000000000000000000000000000000000000000d1a26333f4c58646e74797979797979787673706c656059514940372e22190f0400000000000000000000000000000000000009131c252c33373939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393937332c251c1309000000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a5b65737f8c999d9083766d7985919e93877b6e615f6c7986929f968a7d7063574a3d3024170a0000010b151d252b303435393d4a5763707d8a96978a7d7064574a3d2d39392f3e4b5864717e8b97968a7d7063574a3d2d39393939393932312e29221b120900000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000060e161d23272a2b2d2d2d2d2d2d2d2d22211e1a140e0600000000000911181d2224252d2d2d2d2d2d2d2d282724201a130b0300000000000000000000000000000000000000030c141b212528292d2d2d2d2d2d2d2625221e18110901000000000000000000030c141b212528292d2d2d2d2d2d2d29201f1b17110a02000000000915222f3c4855626f7c8786868686857a6d61594f42392e23180c0300000000000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8686868686868073675a5a6773808686868686867e7165584b3e3225180b0000000000000000060f181f282f353d43474e5355585f626567696a6b6c6c6c6c6b6a686663605d5553514b444039302b221b130b020000000000000000000000000000000000000000000000000000020a111720262b323839404547494c4f50525253535251504e4c4946443f3837312b262017110a0200000000000000000000000000000000000000000000000000000002080e161c21272c3036393b3f4446494b4d4f5051525253525251504f4d4a4846443f3a39352f2b26201b150c070100000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b87949c9c9c9083776a5d50444f5c6976828f9c9c9c94877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000b1724313e4a5764717d8a97acac9f93867a6d605347403f3f3f3c3b37322a22190e04000000000000000000000000000000000000000e1a2734414d5a6774808686868686858483807d78706b635b514940342b20160a000000000000000000000000000000000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b27211b130a01000000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a606c7884919e988b7e716673808d9a998c8073665c6c7986929f968a7d7063574a3d3024170a000009131d272f373c404146464754616d7a8796998d80736653493f46464646464855626e7b8898998c807366544a3f464646464646463e3d3a342d241b1106000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000000000e1820282e33363839393939393939392e2d2b261f180f0600000009121b23292e313239393939393939393534312c251d150b000000000000000000000000000000000000020c151e252c3134353939393939393932312e29231b13090000000000000000000c151e262c31343539393939393939362d2b27221b140b020000000815212e3a47535f6a73808d9693978e81746b60544a4034281f140900000000000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b939393938d8073675a5a6773808d939393938b7e7165584b3e3225180b00000000000000061018212a313a40454e54585f62676a6e71747677787979797978767573706d6764605c54514a423d342d251d140b01000000000000000000000000000000000000000000000000040b141c222832373d43484b515356595b5d5e5f5f5f5f5e5d5b585653504a47433c373127221b140b0300000000000000000000000000000000000000000000000000000000050b10161c1f252a2d2e34383a3c3e414244454546464545444342403e3c3a38342e2c29241e1a150f0a04000000000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b878f8f8f8f8f83776a5d50444f5c6976828f8f8f8f8f877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000a1623303d495663707c899aa4afa4998a7e71645b514b4c4c4c4947433c342a20150a000000000000000000000000000000000000000e1a2734414d5a6774808d939393989291908d89837d726d635b51463d32271b0f04000000000000000000000000000000000000010910161b1e202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201e1b1610090100000000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a63707d89969f92857a6d626f7b88959e9184796d606c7986929f968a7d7063574a3d3024170a00030f1a252f3941484d4e535353525e687884919c8f8276655b505353535353535353606c7985929c8f8276665b5053535353535353534b4a453f362d22180c010000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000000060f202a32393f434446464646464646463b3a37312a21180e030006111b242d343a3d3f464646464646464642403d372f271d0b02000000000000000000000000000000000009141e2730373d4142464646464646463f3e3a352d251b0f060000000000000008121e2730373d414246464646464646433937332d261d140a00000006121f2b37434e58606d7984919e9f93887d6f665c51443b31261a0d04000000000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b989f9f9a8d8073675a5a6773808d9a9f9f988b7e7165584b3e3225180b000000000000050e18222a333c434b515860626a6f74787b7e80828485858686858483827f7d7a76716d66605c544e463f372e261d130a0000000000000000000000000000000000000000000000040d161d262d333c43474f54555c606366686a6b6c6c6c6c6b69686562605b54534e47423c332d261d150d030000000000000000000000000000000000000000000000000000000000050b1014191e2023282c2d2f3234353738383939393837373533312f2d2b2823201d19130f0a030000000000000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8283838383828074675a4e414d5a6673808283838383827a6e6154473b2e21140800000000000000000000000000000000000000000000000000000714212d3a4754606d7a86939facab9c9083766d605d5559585855544e463c32261b0f030000000000000000000000000000000000000e1a2734414d5a6774808d9a9f9fa29f9e9d9a9590887f726d63584e43372b20150a0000000000000000000000000000000000000000050a0f1213131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313120f0a05000000000000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a6875818e9b9a8e8174675f6a7683909d978a7d70646c7986929f968a7d7063574a3d3024170a000814202b37414b53595b60606060566875828e9b9285796c606060606060606060605b6576838f9c9285796c60606060606060606060585650483f34291d11050000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000030d1821323c444b4f5153535353535353534846423c332a1f1409010c18232d363f454a4b53535353535353534e4d4841392f1d140a0000000000000000000000000000000004101b25303942494d4f535353535353534c4a463f372d21180b020000000000050e1a24303942494d4f535353535353534f46443f382f261b11060000030f1b26313c45515d67707d8a939e9a9183786d60574d42362a1f160c010000000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000000020b17202a343c454d555d606a6f767c8084888b8d8f90929293929291908e8c8986827e79726d666058514940382e251c1108000000000000000000000000000000000000000000030c161f282f383f444e54596063676d707375777879797978787674726f6c66625f58534d443f382f271f150d0300000000000000000000000000000000000000000000000000000000000002080e1114171c1f20222527292a2b2c2c2c2c2b2b2a28262422201f1c1713110d080100000000000000000000000000000000000000000000000000000000000000000000000000000714202d3946525e686e767676767676746e64584c404b58636e737676767676766e685e5246392d20140700000000000000000000000000000000000000000000000000000713202c3945525d687784919dabab9f948b7f736d6766656565625f584e43372b1f13060000000000000000000000000000000000000e1a2734414d5a6774808d98989a9c9fa3aba7a09a938c7f726a6054473d32271b0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a6d7a86929f95897c6f635865727e8b989c8f8276696c7986929f968a7d7063574a3d3024170a000c1824303c48535d64686c6c6c6c6c6c727f8c9897887b6e6c6c6c6c6c6c6c6c6c6c6c6c73808d9998887b6f6c6c6c6c6c6c6c6c6c6c65625a50453a2e2115090000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000009141f2933444e565c5e606060606060606055534d453c31261a0e05111d29343f4851565860606060606060605b59534b412f261b11060000000000000000000000000000000915212c37424b53595c60606060606060595651493f332a1d140a00000000020d17202c36424b54595c606060606060605c53504941382d22170b0000000a15202935404b55616b75818e98a0958c7f72695f53463e31281e13080000000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000000a141d29333c464e575f676d747c82888d9196989a9c9d9e9f9f9f9f9e9d9b9999928f8a847f786f6a625b524a40372e231a0e0500000000000000000000000000000000000000000b151e283139424a50585f626b6f75797d7f828385858686858483817f7c79746f6a625f575049413931271f150b01000000000000000000000000000000000000000000000000000000000000000205060c10121316181a1c1d1e1f1f201f1f1e1d1c1a17151312100b0604010000000000000000000000000000000000000000000000000000000000000000000000000000000005111e2a36414c565e6169696969696967645c52473c47525c6366696969696969615e564c41362a1e1105000000000000000000000000000000000000000000000000000004111d2935414c566673808d99a3afa69f9388807a75737272726f6a5f54473b2e2215080000000000000000000000000000000000000e1a2734414d5a6774808b8b8c8d9092999ea5aca49f92877c6f62584e43372b1f130600000000000000000000000000000000000000000000000000000000000000000000000000000000060b0e101113131313131313110605030000000000000000000000000000000000000000000000000000000000000000000000000001040707131313131313131308070502000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a727f8b989d9184776b6054606d7a86929f93877b6e6c7986929f968a7d7063574a3d3024170a000e1a2734404d59646f74797979797979797d8996978a7e79797979797979797979797979797e8a97988b7e7979797979797979797979716c62564a3d3124170b0000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000020e1a26313b455660676b6c6c6c6c6c6c6c6c6c5f574d42372b1e120915222e3a45515b62656c6c6c6c6c6c6c6c68655d5341382d22170b0000000000000000000000000000000c1925313d49535d65686c6c6c6c6c6c6c65625b51453c2f261c110600000008141e29323e48545d65686c6c6c6c6c6c6c69605b53493f33271b0f030000040c18242f39434f59616e7b85929f9f92867b6e615a50433a2f24190c0200000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000006111b262f3b454e585f696e7981878f949a9ea1a8a7a9aaaaaaa9a9aaaba9a8aba39f9c97918c847c726d645c524940362c20170c0200000000000000000000000000000000000007121d273039434b545b606a6f767c8185898c8e90919292929291908e8b8985817c756e69605b534b433931271d12070000000000000000000000000000000000000000000000000000000000000000000000030607090b0e0f1112121313121211100f0d0b090706030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1925303b444c52545c5c5c5c5c5c5a58524a4136404a52585a5c5c5c5c5c5c54524c443b3025190d010000000000000000000000000000000000000000000000000000010d1924303b4854616e7b87929fa7afa49a938d8582807f7f7f7c6f6255493c2f221609000000000000000000000000000000000000091623303c4956636f7d7f7f7f8083868f939ea5afa3999083766a6054473b2e2215070000000000000000000000000000000000000000000000000000000000000000000000000000040b11171b1d1e202020202020201e13120f0b0600000000000000000000000000000000000000000000000000000000000000000002080d11131420202020202020201514120e090300000000000000000000000000000000000000000b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776a7783909d998c7f726559515d6774818e9a998c8073667986929f968a7d7063574a3d3024170a000e1b2835414e5b68748186868686868686898f999a908a86868686868686868686868686868a909a9b908b86868686868686868686867e7165584b3e3225180b0000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000005121e2a36424d57677277797979797979797976695f53463a2d21140b1724313d4a56626d727979797979797979756f6553493f33271b0f0300000000000000000000000000020e1b2834414d59656f7579797979797979726d62574d42382d22170b0200050e1925303b44505a656f7579797979797979766c655b5044372b1f120500000007121d27313e46525e69727f8b959f988f82756c61554c4135291e140a00000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000b17222d38414d575f6a6f7b848e939a9fa6abacaaaaa39f9e9d9c9c9d9ea1a9a7acaca9a19e9691877f746e645b52483e32291e13080000000000000000000000000000000000040d18232e39434b555d666c737c83898e9298999b9d9e9f9f9f9f9e9c9b9897918d88827b736c655d554b43392f24180e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141e29323b4146475050505050504e4c4741382f3840474b4d5050505050504746413b32291e1408000000000000000000000000000000000000000000000000000000000814212d3a46535e6974808d959fa7aca49f98928f8d8c8b8b7f7266594c3f3326190c0000000000000000000000000000000000000915222f3b4854606b6f72727273767b818e939ea9ab9f95897c6f6256493c2e23180c00000000000000000000000000000000000000000000000000000000000000000000000000050e161d22272a2b2d2d2d2d2d2d2d2b201f1b17110a02000000000000000000000000000000000000000000000000000000000000040c13191d20212d2d2d2d2d2d2d2d22211e1a140e06000000000000000000000000000000000000020b1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d9084776f7c88959f92867a6d61544b55626f7c89959e9184796d7986929f968a7d7063574a3d3024170a000e1b2835414e5b6874818e9393939393939699a1a29a979393939393939393939393939393979aa2a29b98939393939393939393938b7e7165584b3e3225180b0000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000714212d3a46535f69778486868686868686867b6e6155483b2e2215091825323f4b5865727f86868686868686868175655b5044372b1f120500000000000000000000000000020f1c2935424f5c687582868686868686867f72695f544a3f33281d140a020c17202a36414c56616c75818686868686868682796c605346392d201306000000010b151f2a36424d56606c788390999e948a7e71675d51453c30261c1106000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000030f1b27333f49535e696f7c8591969fa4acaca7a09d98989291908f90909197979b9fa2aaada8a099928c80746e635a50443a3025190d03000000000000000000000000000000010c161f2834404b555d676d78808790949b9fa2a9a29e9c9b9a9a9b9d9fa3a9a19e9a948f877f776d675d554b40352920170d02000000000000000000000000000000000000000000000000000000000000000000030607090b0d0f1111121313121211100f0d0a08070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d1720293036393b43434343434341403c362f262e353b3f404343434343433b3936302920170d020000000000000000000000000000000000000000000000000000000005121e2a36424d57606d798390959fa2aaaaa29f9b9998988c7f7266594c3f3326190c00000000000000000000000000000000000007131f2c38434f59606365656567696e78818e97a1ada79a8d807467554b4034281c10040000000000000000000000000000000000000000000000000000000000000000000000000e1720282e33363739393939393939382d2b27221b140b0200000000000000000000000000000000000000000000000000000000040e161e24292c3939393939393939392e2d2b261f180f0600000000000000000000000000010507070f0f1825323e4b5865717e8b98a296897c6f6356493c30231a2734414d5a6774808d9a9d90847774808d9a9b8e8275685e524754606a7783909d978a7d707986929f968a7d7063574a3d3024170a000e1b2835414e5b6874818e9b9f9f9f9f9f9fa0acafa6a49f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa0a3a8a6a49f9f9f9f9f9f9f9f9f988b7e7165584b3e3225180b0000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000000121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b88969393939393938b7e7165584b3e31261a121e2a36424d576875818e9393939393939285786c605346392d20130800000000000000000000000000000714212e3a4754616d7a85919393939392867b6e665b50443c2f261c1108131e29323a46525e68717e8a939393939392857a6e655b5044372b1f120500000000030d1925303b44505b666f7c87929f9e91847a6d60584e42382e23170b020000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000005121f2b3744505b656e7b849197a0a8afa7a09d95908b8885848383838485878a8e92989fa3ababa39f928c80736c61564c41362a1f140900000000000000000000000000000008131e28313a45515c676d79828d92999fa6a39f9a97928f8e8d8e8e9092989b9fa3a69e99928c82796d675d51453f32291e140800000000000000000000000000000000000000000000000000000000000104060b10121315171a1c1d1e1f1f201f1f1e1d1b19171514120e09060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e171e252a2d2e3636363636363433302b241d242a2f32333636363636362e2d2a251e170e050000000000000000000000000000000000000000000000000000000000020e1a25313b45515c676d7a838c92989b9d9e9fa39f9f998c7f7266594c3f3326190c000000000000000000000000000000000000030f1b27323d474f5456585859575e666d7a85929eabaa9d908377675c5145382c1f130600000000000000000000000000000000000000000000000000000000000000000000000711202932393f434446464646464646443937332d261d140a000000000000000000000000000000000000000000000000000000020c1620283035394646464646464646463b3a37312a21180e030000000000000000000002080d1113141c1c1c25323e4b5865717e8b98a296897c6f6356493c30231c2734414d5a6774808d9a9d9084777985929e96897d7063564c434e5865727e8b989c8f82767986929f968a7d7063574a3d3024170a000e1b2835414e5b6874818e93939393939393939fa3a59d9b939393939393939393939393939394979ea49d9a9393939393939393938b7e7165584b3e3225180b0000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d000000000000000000000000000000000000000000000000000000000000000000030d152c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a5465727e8b98a89f9f9f9f9b8e817568574d42372b1e14212d3a46535f697884919e9f9f9f9fa197887c6f6255493c2f24190d01000000000000000000000000000713202d3946525e68707d8a929da8a2989083786c60574d42382d22170e1925303a44505a616e7a85929ea5a89d938a7d70685e53493f33271b0f03000000000009141f28333f4a545f6a74808d96a1978d80746a60544a3f34281f14090000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000004101c2834404a54606c77828f96a1a9aea49d959189837f7c797777767677787a7d81868c9299a0a8afa49c928a7e70685e52463b31251a0e0000000000000000000000000000010d19242f3a43505a606d79828f949fa3a7a099928e898583818181828386898e92999fa7a39f948f82796d605b51443b3025190e02000000000000000000000000000000000000000000000000000001070d1113171c1f20222426292a2b2b2c2c2c2b2b2a28262422211e1a1312100c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d14191e20212929292929292726241f1a13191f23262729292929292921201e19140d050000000000000000000000000000000000000000000000000000000000000009141f2934404b555e686d7980858b8e909192999393938c7f7266594c3f3326190c000000000000000000000000000000000000000a16212b353d4348494c4c4c4d545d6873808c99abac9f9286796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000050f1923323b444b4f51535353535353535146443f382f261b1106000000000000000000000000000000000000000000000000000008131e28323a41455353535353535353534846423c332a1f1409000000000000000000040c13191d202128282828323e4b5865717e8b98a296897c6f6356493c3028282834414d5a6774808d9a9d9084777d8a979e9184786c6053463d4754606d7a86929f93877b7986929f968a7d7063574a3d3024170a000e1b2835414e5b68748186868686868686868692999d938e8686868686868686868686868686878c979d928d868686868686868686867e7165584b3e3225180b0000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000010b151f2935414c566c7885929fabada093867a6d6053473a2d20160c0200000000000000000000000000000000000000000000000000000000000000000006121f2c3844505c6675828f9ba8acabacab9e918578695f53473a2e2115222e3b4855616e7b8896a1adacaaaca9998c7f7366564c4135291d11040000000000000000000000000005111d2a36414c56616b74808d96a0aa9f948b7f72695f544a3f33281d16202a36414c56616c75818f97a1aba0968e81746c61564d41382d22170b000000000000020b17222d38424e58606d7984919e9f93877c6f665c50443b30251a0d0300000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000006121f2c3844515c66717e8b949fa9afa59d928d837d77726f6d666a69696a696e70747a80879196a0a8aea49e92857a6d61574d42362a1c11060000000000000000000000000004111d2935414c56616c74818e949ea6a69f959087817c79767474747577797d818790959ea5a69e948e81756d62564c41362a1e140800000000000000000000000000000000000000000000000003090e13181d2023282b2d2f3133353737383939393837373533312e2d2a26201f1c17110d08020000000000000000000000000000000000000000000000000000000000000000000000000000000002080d1114141d1d1d1d1d1d1b1a17140e080e1317191a1d1d1d1d1d1d1414110d08020000000000000000000000000000000000000000000000000000000000000000030c18232f39434c565e676d737a7e8184858686868686867f7266594c3f3326190c00000000000000000000000000000000000000040f19232b32383b3c3f3f3f424c56626f7c8899a3aea399877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000000000b16212b35444d565b5e606060606060605e53504941382d22170b00000000000000000000000000000000000000000000000000010d1924303a444c525f606060606060606055534d453c31261a0e0200000000000000040e161e24292d2e35353535353e4b5865717e8b98a296897c6f6356493c3535353535414d5a6774808d9a9d908477828e9b9a8c8073665b50443945515d6774818e9a998d807986929f968a7d7063574a3d3024170a000e1a2734404d59646f7479797979797979797987929b8e8179797979797979797979797979797a87969a8d8079797979797979797979716c62564a3d3124170b0000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d000000000000000000000000000000000000000000000000000000000000000007121d27313945525d687885929fabada093867a6d6053473e32281e13080000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7985929fa8a19ea1a8a197887b6e6255483b2f221825313e4b5864717e8b97a8a8a09ea0a89c908376685d5245392c20130700000000000000000000000000010d1925303a444f59606d79849199a3a69f92867b6e665b50443c2f261e28323a46525e68717e8a939ea9a3999184796d605a50443b2f261b11060000000000000006111c262f3c45515d67707d8a949e999083786d60574d42362a1f150b01000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000713202d3a4653606d7984919ea6b0a79d938d8079706b6562605c545c5d565e6164686d737c849196a0aaada2978e8174695e5346382e23170b000000000000000000000000000613202c3945525d68717e8a939da6a89f948f837c746f6c6668676768666d70757c838f939ea7a69e938b7f72685e52463b3025190d01000000000000000000000000000000000000000000040a0f151a1d24292c2e34383a3c3e404244444546464545444342403d3b3a36312d2c28231c19130d080200000000000000000000000000000000000000000000000000000000000000000000000000000000010507081010101010100e0d0b08030002070a0c0d10101010101008070501000000000000000000000000000000000000000000000000000000000000000000000007121d27313a444c555d60686d71747778797979797979726d63574b3e3225180c000000000000000000000000000000000000000007101921272c2f3032322f3a4653606d7986929facab95887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000000000000004101c27323d47565f676a6c6c6c6c6c6c6c6b605b53493f33271b0f0300000000000000000000000000000000000000000000000004111d2935414c565d6c6c6c6c6c6c6c6c6c6c5f574d42372b1e1205000000000000020c1620283035393a4242424242424b5865717e8b98a296897c6f635649424242424242414d5a6774808d9a9d90837a86929f93877b6e61544a3f35414c55626f7c89959e91847886929f968a7d7063574a3d3024170a000c1824303c48535d64686c6c6c6c6c6c6c677783909d918477686c6c6c6c6c6c6c6c6c6c6c687784919d908377676c6c6c6c6c6c6c6c65625a50453a2e2115090000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000030c18242f39434f59606d7a86929facaea194877b6e615a50443a3024190d030000000000000000000000000000000000000000000000000000000000000000091623303c4956636f7c8998a2a1969196a1a9988b7e7265584b3f31261e2a36424d576874818e9ba9a0969196a09f92867a6d6054473a2d21140a000000000000000000000000000008131e28323e45515d676f7c87929fa6a2989083786c60574d42382d25303a44505a616d7a85929ea5a69f92877c6f675d51483e32291d140a0000000000000000000a141d2935414b55616c75828f98a0958b7f72695e52463e31271d1207000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00030f1c28333f4a5464717d8a96a1acaca0958e81746d6760595553514a50504d5254565d606a6f7b849198a2aea99f92867b6e61544a3f34281c1003000000000000000000000004111d2935414c55606d7a85929ea5aca0968f82796e6a62605b545a5b545c60636a6e78818f959faba59f92857a6e61564c41362a1e11050000000000000000000000000000000000000000070c151b20262b2f35393a3f4446484a4d4f5051525253525251504e4c4a4846423d3a38342e29251e19140d05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151f29323a434b51565d6064686a6b6c6c6c6c6c6c66635b51463a2f22160a000000000000000000000000000000000000000000070f161b1f222325252c3844515c667784919daaa296897c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000000000713202c38444f5967717779797979797979776c655b5044372b1f14090000000000000000000000000000000000000000000000000713202c3945525d6876797979797979797976695f53463a2d21140700000000000008131e28323a4146474f4f4f4f4f4f4f5865717e8b98a296897c6f63564f4f4f4f4f4f4f484d5a6774808d9a9d90837e8b989c8f8276695e5342382f3a4754606a7783909d978a7d86929f968a7d7063574a3d3024170a000814202b37414b53595b606060606060556774818d9a96877a6d61606060606060606060566875818e9b9286796d6060606060606060585650483f34291d11050000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d000000000000000000000000000000000000000000000000000000000000000a151e2935404b55606b74818e98a3aeb5a89c8f82756c61564c4135291f150b0100000000000000000000000000000000000000000000000000000000000005111d2935414c566673808c99aa9e9184919eaa9b8e817568584e43372b202d3a46525e697784919ea1979184919ea3998a7d7164574a3e31261b0f0300000000000000000000000000020c16202935404b55606a737f8c949faa9f948b7f72695f544a3f332935414c56616c75818e97a1aa9f948c7f736a60554b40362c20170b02000000000000000000020b18242f3a43505a616e7b86929f9f92867b6e61594f43392f24180b020000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0006121f2b3844505b6675828f9ba8b1a89d9083786d605c554f4946444043434246474c52585f696e7b86929fa8afa3998d8073665c5044382b1f120600000000000000000000000613202c3945515d6773808d97a1ada69e91847a6d675f5853504a4e4e4b5153585f666d79839099a3ada2978d8174685e5246392d201409000000000000000000000000000000000000030b121820262b31373a4145474a50535557595c5d5e5e5f5f5f5e5e5d5b595755534d4946443f3835302a251e170e080200000000000000000000000000000000000000000000000000000000000000000000000000000000000002080c1012121313131313131313060400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d172029313940454c5254585b5d5e5f6060606060595751493f352a1e120600000000000000000000000000000000000000000000040a0f131516191c2834404a546a7683909da9a296897c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000000000916222f3b4854606b77838686868686868684776c6053463b30251a0e0000000000000000000000000000000000000000000000000714212d3a4754606d7a86868686868686867b6e6155483b2e2215080000000000010d1924303a444c52545b5b5b5b5b5b5b5b65717e8b98a296897c6f635b5b5b5b5b5b5b5b54535a6774808d9a9d918483909c978a7e7164574d422f2b37434e5865727f8b989b8e8187929f968a7d7063574a3d3024170a00030f1a252f3941484d4e5353535353535864717e8b97968a7d70635753535353535353535865727f8b9899897c6f63565353535353534b4a453f362d22180c010000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000006111c26303845515d67707d89939daab4b9aa9e948a7e71685d52463d31271d12070000000000000000000000000000000000000000000000000000000000000713202d3946525d687683909da8988c7f8c98a29e9185786a5f53473a2e212e3b4754616e7b8796a09e9285808c99ab9a8e817467584e43372b1f12060000000000000000000000000000050e18242f39434e58606d78839098a2a69f92867b6e665b50443c323a46525e68707e8a939ea9a2989083786d60584e43392f231a0e05000000000000000000000007131d28313e46535e69727f8c95a0988e81756b61554b4035291d140a0000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000613202d394653606c7985929fabaca095897d70665c514b433d3a38342e30363a3b41454e565e69727f8b96a0acab9e9185796d6053463a2d20130700000000000000000000000714212d3a4754606d7a85929fa9aa9e94897d70685d554e46443f41414045464e545c676f7c87929faca99f92867a6e6154473c31261a0e0200000000000000000000000000000000070c151d232831373c42474b5154545c60626466686a6a6b6c6c6c6b6a6a686664615f575653504a46413a3630292019130d0500000000000000000000000000000000000000000000000000000000000000000000000000000000060d13181c1e1f202020202020202013100c07010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e171f272f353a4145474b4e51525353535353534c4b463f372e23180d02000000000000000000000000000000000000000000000000030709090c18232e43505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000000000000000000000000000000000000000005111e2a36414c5663707d8995939393939396897d7063574d42362a1c110600000000000000000000000000000000000000000000000714202d3a4753606d7a86939393939393877b6e6154483b2e211508000000000005111d2935414c565d61686868686868686868717e8b98a296897c6f686868686868686868615e576774808d9a9f928690949e9285796d6053463b3127323d4754606d7a86929f928588939f968a7d7063574a3d3024170a000009131d272f373c404146464646464855626e7b8897998d807366544a3f46464646464956626f7c8998988c7f7265594c46464646463e3d3a342d241b1106000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000020b17232e38424e58606d7984919ea5afafacafa69e92857a6d61594f43392f24180c0300000000000000000000000000000000000000000000000000000000000714212e3a4754616d7a86939fa096877a85929fa197887b6e6255483b2d22313e4b5764717e8a97a89b8f827d8a96a89e9184786a5f53473a2e21150700000000000000000000000000000007121d27313c44505c666e7b86929fa5a2989083786c60574d423a44505a616d7a85919ea5a59f92867b6e665c50463d31281d1108000000000000000000000000010c161f2a36424d57606d788390999e938a7d70675d51453c2f261b110600000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000815222f3b4855626e7b8897a2adaa9d9184776b60544a4039312d2c2823252a2d30353c444d57606c7884919eaaada197897c6f6356493c302316090000000000000000000005111e2a36424d5765727f8b98a2aea99c8f82756b60564c433c38332d2e34383c424b555f6a74818e9ba8aea3988c7f7266574d42372b1e12050000000000000000000000000000000810191e272e343c43474d53555d6064666d6f7173757777787979787877767573706e696763605c54524c46413b322a251e170e0600000000000000000000000000000000000000000000000000000000000000000000000000000710181f24282b2c2d2d2d2d2d2d2d2d1f1c18120b030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d151d24293035393a3e4144454646464646463f3e3a352e251c12070000000000000000000000000000000000000000000000000000000000071d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000000000000000000000000000000000000000000000713202d3946525e6875818e9ba89f9f9fa89b8f8275695e5246382e23170b00000000000000000000000000000000000000000000000713202d3a4653606d79869aa49f9f9f94877a6e6154473b2e21140800000000000713202d3946525d686d757575757575757575757e8b98a296897c757575757575757575756e695e6774808d9aa29892989f9a8d8074665c51453829202c3945525d6874818e9b9892939aa4968a7d7063574a3d3024170a0000010b151d252b30343539393939394653606c7985929c8f8376665c5044383939393a4653606d7986929b8e827568574d423639393932312e29221b120900000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000a141d28343f4a54606a73808d96a0acaca49fa4aca1978e81746b60554b4035291e150a00000000000000000000000000000000000000000000000000000000000b1724313e4a5764717e8a99a49e918477828f9ca9988b7e726553493f332a36414c566774818d9aaa988b7f7a8796a0a196887c6f6255483c2f24180d010000000000000000000000000000010b151f28343f4a545f69717e8b939ea99f948b7f72695f544a414c56616c75818e97a1a89e938b7e71695f544a3f342b1f160c0000000000000000000000000000040d1a25313b44505c666f7c87939f9e9184796d60584e41382d22170b02000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000a1724303d4a5763707d8a96a9b3a69a8d807367594f42382f27201f1c18191e202429323b44505b65737f8c99a9a6a9998c807366594d4033261a0d000000000000000000000714202d3a46525e697683909daaada196897d7063594f433a312b282223282c3039434e58626f7c8895a0acaa9d908477695f53463a2d211407000000000000000000000000000009111a222a303940454e53575f62676d7175797b7d8082838485858685858483817f7d7b7874706d66615e56524c443e36302920180f0700000000000000000000000000000000000000000000000000000000000000000000000006101922293035383939393939393939392c29231d150d030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b12181e24292c2d3135373839393939393933322f2a231c130a000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000000000000000000000000000000000000000000030f1c28333f4a54616d7a86929facacacacac9f92877b6e61544a3f34281c10030000000000000000000000000000000000000000000006121f2c3844515c667986939facaca094877a6d6154473a2e21140700000000000714212e3a4754616d7a8182828282828282828183909da99c8f82828282828282828282817b6e616774808d9aaaa29fa29f95887b6f62544b4034281d2935414c56626f7c8995a09f9fa4ac968a7d7063574a3d3024170a000000030b131a202427282d2d2d2b3744505b6576828f9c9285796d6053463a2d2d2c3844515c667683909c918478695e52463a2d2d2d2524211d1811090000000000000000000000000714202d3a4753606d7a8693a0ada6998c807366594d4033261a0d0707040100000000000000000000000000000000000000000000000006111b262f3844505c666f7c87929fa8a69f9a939aa4a99d93897d70675d51453c30261c110600000000000000000000000000000000000000000000000000000006121f2b37434e586774818e9aab9b8e81757f8c99a99b8e8275655b5044372d3946525e687784919da298887c7784919ea9998c7f7266554b4035291d1104000000000000000000000000000000030d17232e38424d57626c75828f97a1a69f92867b6e665b5045525d68707d8a939ea9a1968e81756c62574d42382e22190d0400000000000000000000000000000009141f28343f4a54606a74808d97a1968d80736a5f53493f33271e1308000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000b1825323e4b5865717e8b98a4b1a4978a7e7164574b3e30261d1512100c0e1114192027333f4953616e7b88979a9998978f8276695c4f4336291c10030000000000000000000814212e3b4754616e7b87959fabab9e9184786c6053463d31281f1c17181c1f27313c47535f6a7784919daaaca095887b6e6155483b2e2215060000000000000000000000000009121b232c343c424b51585f62696e747a7d8185888a8c8f9091919292929191908e8c8a8884807d79736d68615e565046413a322a2119100700000000000000000000000000000000000000000000000000000000000000000000020d18222b343b414445464646464646464638342f271f150b01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c13191d202125282a2b2c2d2d2d2d2d2625221e18120a01000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000006121f2b3844505b66727f8c99a3aeaaa8aaafa3998c7f73665c5044382b1f14090000000000000000000000000000000000000000000004101c2834404a5f6c7986929facada093867a6d6053473a2d20140700000000000815212e3b4854616e7b878e8e8e8e8e8e8e8e8e90959fab9f948f8e8e8e8e8e8e8e8e8e887c6f626774808d9aa7aeacaa9d9083766a5f5342392e2319242f3a4754606a7783909daaacafa3968a7d7063574a3d3024170a0000000001090f14181a1b20201b27333f495366737f8c9998887c6f6255493c2f222834404a546773808d9a96877b6e6154473b2e212020201b1a17140e08010000000000000000060c1114202d3a4753606d7a8693a0ada6998c807366594d4033261a1a1413110d0801000000000000000000000000000000000000000000000b17222d38414d57606d78839099a3ab9f948f87939fa8a59e9184796d60584e42382e23170c0300000000000000000000000000000000000000000000000000000814212e3a47535f6a7884919eab988c7f727c8897a29e9285796c605346392e3a4754616d7a8795a09f92857974818e9ba79c8f8376675d5145392c2013060000000000000000000000000000000006111c26303b45505a616d7a85919ea4a2989083786c60574f59606d7a84919ea5a49a91847a6d615a50453b30261c100700000000000000000000000000000000030c17232e38424e58606d7a85919e9f92877c6f655b50443a3025190c030000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000c1925323f4c5865727f8b98a5afa396897c706356493d3023140b0604000205080e17222d3846535f6978858e8d8c8c8b8a85786b5e5245382b1f12050000000000000000000b1824313e4b5764717e8a97a7b1a79a8e8174665b5044382b1f160f0b0c10151f2b37434e586773808d9aa6b1a7988b7e7165584b3e2d22170b00000000000000000000000009121b242d353e464e545c606a6f757b81868a8e929797999b9d9d9e9f9f9f9e9d9d9b999796918d8985807a746e68615a524c443c332b2219100700000000000000000000000000000000000000000000000000000000000000000008131f29343d464c5152535353535353535345403931271d12070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d111314181b1e1f202020202020191816120d070000000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000000000000000000000000000000000000000613202d394653606c7884919eaba69e9c9ea6ab9e9184786d6053463b31261a0e00000000000000000000000000000000000000000000000c18232e46525f6c7985929facaca09386796d6053463a2d20130700000000000815212e3b4854616e7b87949b9b9b9b9b9b9b9b9d9fa79fa69f9c9b9b9b9b9b9b9b9b95887c6f626774808d9a9f9f9fa2988b7e7165584e4330271d131e2b38434e5865727f8b98a29f9f9f968a7d7063574a3d3024170a0000000000010911181e2225252d222d3d4a5663707d899a988b7f7265584c3f3025232e3e4a5764717d8a97978a7d7164574a3e2e232d2d2d2726241f1a130b020000000000000910171d21202d3a4753606d7a8693a0ada6998c807366594d403326262621201d19130c040000000000000000000000000000000000000000040f1b27333f49535f69727f8c95a0aba3998f82808c96a0aca0968d80736a5f544a3f34281f140900000000000000000000000000000000000000000000000000000815222f3b4855626e7b8896a1a399897c6f7985929fa197887b6f6255483c2d3e4a5764717d8a97a89c8f8276717e8b98a89f92867a6d6053473a2d20140900000000000000000000000000000000000a141e29333f46525e68707d8a929da89f948b7f72695f56616b74818e97a1a79f93887d70685d52483e33291e140a00000000000000000000000000000000000006111c26303d45525d68717e8a949f999083776c60564c41362a1e150b0000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000c1825323f4b5865727e8b98a5afa295897c6f6256493c2f23160600000000000006111b2a36424d576673808180807f7e7d7d706356493d3023160a000000000000000000010e1b2834414e5b6774818e9aa7b4aa978a7e7164544a3f3328190d040000040d1b26323d4a5764707d8a97aab4a79b8e81746853493f33271b0f030000000000000000000007101b242d363e474f585f666d737c82878e92989b9ea2a9a6a8aaa8a7a6a6a6a7a8a9a8a6a8a19e9a97928c86807a716c615e564d453c342b22190e0500000000000000000000000000000000000000000000000000000000000000000c1824303b464f575d5f606060606060605f514b43392f23180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010407070b0e11121313131313130c0c0a0602000000000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000000000000000000000000000000000000000005121e2a36424d5763707d8a96a0ab9e948f949eaaa1968a7d7064574d42362a1c120700000000000000000000000000000000000000000000071f2c3845525f6b7885929eabaea3998679665c5145382c1f130600000000000815212e3b4854616e7b8793939393939393939393939393939393939393939393939393887c6f626774808d939393939392857a6d6054473c3121150f1b27323d4754606d7a869293939393938a7d7063574a3d3024170a000000000009131b23292e31323939393a4754606d7a86939b8e817568564d42363939393b4854616e7b87969a8d807367544a3f34393939393433302b241d140b010000000009121b22282d30313a4753606d7a8693a0ada6998c807366594d40333333332d2c29241e160d04000000000000000000000000000000000000040e1a242b3744505b656e7b86929fa7a89f92867c7984919ea5a89f92877c6f665c50443c31261a0e0500000000000000000000000000000000000000000000000004101c2934404b5565727f8c98a89f9286796d75828f9ba9988b7f726553493f35414c566774808d9aaa998c7f726e7b8896a1a3998a7d7064574a3d31261a0e0200000000000000000000000000000000020c18212a36414c56616b74818d96a0a69f92867b6e665d68707d8a939ea9a0958d80736b60564c41362d21180c02000000000000000000000000000000000000000a151e2935414c56616c76828f989f948b7e71685e52463d30271d120700000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000b1724313e4a5764717d8a97a4b0a396897d7063564a3d2d22170b010000000000000e1a26313b4b58636e73757473727170706b6054483b2f22160900000000000000000005111e2a36414c566a7683909da9aea298887b6e6155483b2d221708000000000a15212e3b4854616e7b8798a2aeaa9d908377655b5044372b1f1205000000000000000000050e19222d363e485059616a6f7980878f93999fa3aaabaaaaa29f9d9b9a9a999a9a9b9d9fa2aaa9aba9a19e98928d857e756d685f574e463c342a20170c0300000000000000000000000000000000000000000000000000000000000003101c2835414c5761696c6c6c6c6c6c6c6c6c5c554b4034291c1004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000000000000000000000000000000000000000714202d3a46525e6975828f9ba8a3998f828f98a2a89c8f8276695f5346392e23180c00000000000000000000000000000000000000000005121f2b3845525e6b7885919eabac9f9286796c5f4b4034281c100400000000000815212e3b4854616e7b8686868686868686868686868686868686868686868686868686867c6f62677480868686868686868174675d5145392c20130a16202c3945525d687481868686868686867d7063574a3d3024170a0000000007111b252d343a3e3f4646464645525d687784919d918478695e5246464646464646525e697884919c908376665c50444646464646413f3c362f261d130800000006101b242c34393d3e404753606d7a8693a0ada6998c807366594d40404040403a39352f2820160c0100000000000000000000000000000000020c16202a36424d56606c77828f98a3aca0968c8073707d8a939eaaa3999083786d60574d42372b20170d02000000000000000000000000000000000000000000000006131f2c3845515c6776828f9ca99c90837667727f8b98a99b8f8275655b50443945525d687783909da298897c6f697884919eab9a8d817467574e42372b1e12060000000000000000000000000000000000060f1925303a444f59606d79849199a3a2989083786c606d7a84919ea5a3989083796d60594f443a30241b0f060000000000000000000000000000000000000000030c19242f3a43505a616e7b86929f9e92857a6d61594f42392e23180c03000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000a1623303d495663707c8996a8b1a4978b7e7164544a3f33281d120700000000000009141f2f3b47525c63666867666564646360594f44382c2013070000000000000000000713202d3946525e687885929fabac9f9285796c605346392d201306000000000714212d3a46535e697985929facac9f9285796c605346392d2013060000000000000000020d17202b343e48505a616b707c838c92999fa4abaca7a09d999892908f8d8d8d8d8d8f909298989c9fa4abaaa29f97928a827a6e6960584e463c32291e150b00000000000000000000000000000000000000000000000000000000000005121e2b3844515d6973787979797979797976675c5145382c1f1306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060809131313131313060400000000000000000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87929fac9f92877a85929fab9f93877b6e61544a4034281c1004000000000000000000000000000000000000000005121e2b3845515e6b7884919eabac9f9285796c5f52462e23180c0000000000000714202d3a46525e6976797979797979797979797979797979797979797979797979797979766a5f646e7479797979797979746f64554b4135291d1104111d2935414c56646f7479797979797979706b6155483c2f231609000000010d18232d373f464a4c53535353534c566774818e9a96877b6e6154535353535353534d576875828f9b9285796d60535353535353534e4c4741382f241a0e0300000c17222c363e45494b4d4d53606d7a8693a0ada6998c807366594d4d4d4d4d4d4745413a32281e13080000000000000000000000000000000008131e28323a46525e69717e8b949faaa59e9184796d6b75818e98a2aba0958c7f72695f53463f32291e140800000000000000000000000000000000000000000000000714202d3a4753606d7986929fab998d8073666f7b8897a19e9285796c6053463a4754606d7a86939f9f9286796d6875818e9ba89e9184786a5f53473a2e21140700000000000000000000000000000000000008131e28323e45515d676f7c87929fa79f948b7f726b74818e96a1a69f92867c6f675c51473d32281e12090000000000000000000000000000000000000000000008131e28313e46535f69727f8c95a0978e81746b60544b4034281f1409000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000814212e3b4754616e7a8795a0aca79a8e8174665b5044392f2318110a020000000003131f2a35404a52585a5b5a5959585756544f473d32271b10040000000000000000000714212e3a4754616d7a8798a2aeaa9d918477665b5044382b1f12060000000005121e2a36424d576a7784919daaaea298877a6e6154473b2e211408000000000000000009141f29323d46505a626c717d8690959fa3ababa49f9b95908c898584828180808081828385888b8f93999fa2aaa9a19e938f847b6f6a60584e443b30271d1207000000000000000000000000000000000000000000000000000000000006121f2c3945525f6c788586868686868686796d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0f12151520202020202013100c070100000000000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000000000000000000000000000000000006121f2c3844505c6673808c99a3ab9c8f8276818e9ba9a4998d8073665c5144382c1f1509000000000000000000000000000000000000000005111e2b3844515e6b7784919eaaab9f9285786c5f5245392c1f0700000000000005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c625f585c64676c6c6c6c6c6c6c67645d53433a2f24180d010d19242f3a43535d64686c6c6c6c6c6c6c6361594f44382c20140700000006121e29343f495156586060606060606065717e8b98978a7d71646060606060606060606065727f8c9898887c6f62606060606060605a58524a41362b1f14080005111d28343e48505557595959606d7a8693a0ada6998c8073665959595959595954524c443a2f24190d010000000000000000000000000000030d1924303a44505a616e7b85929fa6a99e93897d7067616e7b86929fa7a79f92867b6e615a50443b3025190d04000000000000000000000000000000000000000000000a1723303d4a5663707d8998a2a3998a7d70636a7885919ea297887c6f6255483d4a5763707d8a99a49c8f82766665717e8b98a8a196887b6e6255483b2f24180c000000000000000000000000000000000000020c16202935404b55606a737f8c959fa69f92867b707d89939da89f948b7f726a5f554b40352b20160c0000000000000000000000000000000000000000000000010c161f2a36424d57606d7883919a9e93897d70665c51453c31261a0d040000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000714202d3a46525e697784919dacab9e9184786c60554b403429221c140b05000000020e19242e3840474b4d4e4d4d4c4b4a4948443d352b21160b000000000000000000000915222f3c4855626f7b8895aab4a99c8f837669544a3f33281c0f0300000000020e1a2531434f5c6976828f9ca9b4aa95887b6f6255483c2f22150900000000000000030d1925303b444e58626c717e879298a0a7afa79f99938e88837f7c79777574737373747577797c7f83878d92989ea5ada59e9691857c6f6a5f564c42392e23180c030000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929393939393867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e151b1f21222d2d2d2d2d2d1f1c18120b03000000000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000000000000000000000000000000000000000713202d3a4653606d7984919eaba3998b7e717d8a97a2ab9e9285796d6053463c31261a0e010000000000000000000000000000000000000004111e2b3744515e6a7784919daaab9e9185786b5e5245382b1f12050000000000020e1a25303b454d525f60606060606060606060606060606060606060606060606060606055534e52585a606060606060605b59534b4131281d13070008131e2831414b53595b6060606060606057554f473e33281c10040000000916222e3a46515b62656c6c6c6c6c6c6c6c6f7b88989a8d80736c6c6c6c6c6c6c6c6c6c6c6c6f7c8999988b7e726c6c6c6c6c6c6c6c67645c52473c3024170b000815212d3945505a6164666666666d7a8693a0ada6998c80736666666666666666605d564c4135291d110400000000000000000000000000010b151f2935414c56616c75828f97a2ada2978e81756b605e69727f8c95a0aca2988f82766c62564c41362a1f160c01000000000000000000000000000000000000000005111e2a36414d566773808d9aaa9f92867a6d606875818e9ba9988b7f7265544a404b556773808d9aaa998c7f7366616e7b8896a1a8988b7f7265554b4035291d1004000000000000000000000000000000000000050e18242f39434e58606d78839098a2a29890827a84919ea5a2978f82776c60584e43392e23190e04000000000000000000000000000000000000000000000000040d1a26313b44515c666f7d88939f9d9184796d60574d42372b20160c0100000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0005111e2a36424d566774808d9aa4ada1968a7e71675c51453f332d261d170e0600000008121c262e353b3f404241403f3e3d3d3b38322b23190f04000000000000000000000a1723303d4a5663707d8996a3b0a89b8e8275685b4f422d22170b000000000000091c2835424f5b6875828e9ba8b0a396897d7063564a3d3023170a000000000000010b151f2a36424d56606a717e889299a2aaafa49c959087817c77726f6d6668676766676768666c6f72767b80868e939fa3aaa8a09792867c6f685e544b4034282015090000000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929f9f9f9f93867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101820262b2e2f3939393939392c29231d150d030000000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000000000000000000000000000000000005121e2a36424d5764707d8a96a1ac9f92867a6d7985929faba1978a7e7164574d42372b1d12070000000000000000000000000000000000000004111d2a3744505d6a7783909daaab9e9184786b5e5145382b1e120500000000000009141f29333b424648535353535353535353535353535353535353535353535353535353494743474c4d535353535353534e4c4841382f1f160c0100010c161f2f3941484d4e535353535353534a48443e352c21160b000000000b1825313e4a56626d727979797979797979797885929d908379797979797979797979797979797986929b8e81797979797979797979746e64584c3f33261a0d000a1724303d4955616c7173737373737a8693a0ada6998c807373737373737373736d685d5245392c2013070000000000000000000000000007121d27313945525d68717e8a939ea9a69f92857a6d615957606d7883909aa4aa9f948b7e71685e52463e31281e130800000000000000000000000000000000000000000714202d3946525e687784909daa9d908377675d65717e8b98a89b8f8275665b5045515d677683909da298897c6f635f697884919ea99c8f8276675d5145382c1f13060000000000000000000000000000000000000007121d27313d44505c666e7b86929fa69f9490849196a1a59e92857b6e655b50463c30271d1108000000000000000000000000000000000000000000000000000009141f2834404a54606b74818e97a0968c7f73695f53463e32281e130800000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00020e1925303b4855626e7b87939faaa99e9184796d605a50443f382f292017110a0300000a141c242a2f3233353433323131302f2c272119110700000000000000000000000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b060000000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a00000000000007121d27313946525e696f7c86929aa3ababa39f928d837c756f6a6662605c545a5a5a5a5a545b606265696e747b818a9298a2a9a9a19891847a6e665c51453c31261a0e0500000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabaca093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e18222a31373a3c46464646464638342f271f150b0100000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000000000000000000000000000000000714212d3a46535f6976828f9ca8ab9c8f82766874818e9ba9a99c8f8276695f5347392f23180c0000000000000000000000000000000000000004101d2a3743505d6a7683909da9aa9e9184776b5e5144382b1e1105000000000000020d17212930363a3b4646464646464646464646464646464646464646464646464646463c3b373c3f414646464646464641403c362f261d0d04000000040d1d272f373c4041464646464646463d3c38332c231a1005000000000c1925323f4c5865727f868686868686868686868a989f95908686868686868686868686868686868b999e938e8686868686868686868074675a4e4134271b0e000b1824313e4b5764717e8080808080808d99a6b3a99c90828080808080808080807a6d6054473a2d211407000000000000000000000000030c18242f39434f59606d7a85919ea5ab9f948b7e71685e52505c666f7c87939fa9a69f92857a6e61594f433a2f24190c03000000000000000000000000000000000000000814212e3b4754616e7a8795a0ac9a8d80736755616e7b8796a19f9285796c60534753606d7a86929f9f9285796d60576874818e9ba79f9286796d6053473a2d20140900000000000000000000000000000000000000010b151f28343f4a545f69717e8b939ea69f969196a0a89d938a7e71695e53493f342a1e150b000000000000000000000000000000000000000000000000000000030c18232e39424f59616d7a85929e9f92867b6e615a50443a2f24190c02000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000914212e3a47535f6a75828f98a3aca0968d80746c625a504a423b3228231c150c0500020a12191f2326272827262625242322201b160f070000000000000000000000000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b0a4978a7d7164574a3e3124170b0000000000000c18232f3943505a616e7b859198a3acaca399928b80786f6a625f585653504a4e4d4d4d4e4a505355575e61696e757e869297a2aaaaa1969082786d60574e42372b21170b00000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15202a343c43474853535353535345403931271d120700000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000000000000000000000000000000000004101c2834404b54616e7b87939faca3998b7e7165707d8a97a2ab9f94887b6e62554b4034291c100400000000000000000000000000000000000003101d2a3643505d697683909ca9aa9d9184776a5e5144372b1e110400000000000000050f171f252a2d2e3939393939393939393939393939393939393939393939393939392f2e2b303334393939393939393433302b251d140b00000000000b151d252b30343539393939393939302f2c28211a110800000000000c1925323f4c5865727f8b93939393939393939394a2a79f9d9393939393939393939393939393939fa3a59e9b93939393939393938d8174675a4e4134271b0e00101c2936434f5c6976828c8c8c8c8c8d929ca8b4ab9f94908c8c8c8c8c8c8c8c877b6e6154483b2e2115080000000000000000000000000a151e2935404b55606b74818e97a1ada3999083776c60564c4a54606b74818e97a1ada2978e81756c61554c4135291e150b000000000000000000000000000000000000030f1b27333f495364717e8b97a7a49a8a7d7064575e697884919ea297887c6f62554a5663707d8999a39c8f8276665c5864717e8b97a8a3988a7d7063574a3d31261a0e0200000000000000000000000000000000000000030d17232e38424d57626c75828f97a1a8a09ea0a8a0968e81746c61564d41382d22180c030000000000000000000000000000000000000000000000000000000007121c27303d46525d68717e8b949f988f82766c61564c4135291e140a000000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000006121f2b37434e58626f7c86929fa6a89d928b7e716c605b544d443d342e261e170e070000080e1317191a1b1a1a191817161613100b04000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8d8074675a4d4134271a0e0100000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b000000000004101c2934404b55616c76828f97a1aaafa49a92877e736d665f58534e4946443f41404040413f4446484d53565e616c717c859298a2aca89f948d80736a5f53473e33281c1004000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b26313c464e535560606060605f514b43392f23180c00000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000000000000000000000000000000000006131f2c3845515c6673808d9aa4ac9f92867a6d606d7985929faba69a8d8073675c5145382c1f150a00000000000000000000000000000000000003101d293643505c6976838f9ca9aa9d9084776a5d5144372a1e11040000000000000000050d141a1e20212d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d22211f2326272d2d2d2d2d2d2d282724201a130b020000000000030b131a202427282d2d2d2d2d2d2d2423201c1610080000000000000c1925323f4c5865727f8b989f9f9f9f9f9f9f9f9faaacaba99f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9faaacaaa89f9f9f9f9f9f9f9a8d8174675a4e4134271b0e00101c2936434f5c6976828f99999999999ca4aeb9b0a69f9c9999999999999994877b6e6154483b2e211508000000000000000000000006111c26303845515d67707d89939da9a89f92877c6f655b5044424f59616d7a85929ea6a99e938a7d70675d51453d30271d1207000000000000000000000000000000000005121f2b3744505b6575818e9ba89f93867a6d6154576774818e9aa9988b7f7265544b556673808c99aa998c7f72665454616e7b8796a1aa9a8d807467574d42362a1e1205000000000000000000000000000000000000000006111c26303c45505a616d7a85929eabacaaaca3999184796d605a50443b2f261b10060000000000000000000000000000000000000000000000000000000000000b151e2935414c56626c76828f989f948a7e71685d52453d30261c11060000000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000020f1a26313c47535f6a727f8c949fa7a49f93877e736c665e564f443f38302920191109000002070a0c0d0f0e0d0c0b0a0a0907040000000000000000000000000000000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b000000000006131f2c3845515c67707d8a949fa9b0a69f93887e716c605c544e47433c3a38342e3433342d3338393c42464d525a616a6f7c86929aa4afa69f92877b6e62594f44392d20150a000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2b37434e585f626c6c6c6c6c6c5c554b4034291c1004000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca9a396897d7063564a3d302317080806020000000000000000000000000000000000000000000000000713202d3a4653606d7985929eacaa9c8f8275685d6674818e9ba9ab9e9285796d6053473c31261b0f01000000000000000000000000000000000003101c2936434f5c6976828f9ca9a99d9083766a5d5043372a1d100400000000000000000002090e121415202020202020202020202020202020202020202020202020202020161513171a1a202020202020201b1a18140f08010000000000000001090f14181a1b20202020202020171614100b05000000000000000c1925323f4c5865727f8b939393939393939393939da0a7a09393939393939393939393939393939393a0a79f9d939393939393938d8174675a4e4134271b0e00101c2936434f5c6976828f9c9f9f9fa0a2a7afb9b6aea8a69f9f9f9f9f9f9f94877b6e6154483b2e21150800000000000000000000020b17232e38424e58606d7984919ea5aca1968d80736a5f53493f3d46525e68717e8b949faba59e91847a6d60594f43392e23180b02000000000000000000000000000000000613202d394653606c7885929eaa9d908477685d525764717e8a97a79b8f8275665b515c677683909ca298897c6f6356535e697884919eaa9d918477695f53463a2d2114070000000000000000000000000000000000000000000a141e2a333f46525e68707d8a99a3aeb7ac9f92877c6f675d51483e32291d140a00000000000000000000000000000000000000000000000000000000000000030c1924303a44505a626e7b86929f9e91857a6d60584e42382e23170b0300000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000a15202b37434e58606c78828f959fa6a499938b80786e686159504a423b322b231b1209000000000000020100000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b0e0100000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a0000000003101c28343f4a54606d7984919ea6b0aa9e948c7f736c625a504a423c37322d2c282327272722282b2d31363b42465058606a707e88939fa8aea3998f82766c6155493c31261b0f000000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000003060b0f15212e3a47535f6a76797979797976675c5145382c1f130e090603000000000000000000000000000000000000000000000000000003101c2936434f5c6976828f9ca9a4978a7d7164574a3e2f24191514120e090300000000000000000000000000000000000000000006121f2b37434e5864717e8a97a1ada3988b7e71645663707d8a97a1ada2978b7e7164584e43372b1d13070000000000000000000000000000000000020f1c2935424f5c6875828f9ba8a99c908376695d5043362a1d10030000000000000000000000020507081313131313131313131313131313131313131313131313131313130908060b0d0e131313131313130e0e0b0803000000000000000000000003080c0e0e131313131313130a0907040000000000000000000c1925323f4c5865727f86868686868686868686868995a0958986868686868686868686868686868689959f958986868686868686868074675a4e4134271b0e00101c2936434f5c6976828f9393939393969da7b2aea49c999393939393939393877b6e6154483b2e211508000000000000000000000a141d28343f4a54606a73808d96a0aca59e9184796d60584e413835414c56606c77829099a3ada1968d80746b60554b4034281d140a000000000000000000000000000000000916222f3c4955626f7c8897a1a79a8d817467564c54616e7a8795a09f9285796c6053606d7986929f9f9285796d60534d576874818e9ba7a096887b6e6155483b2e23180c00000000000000000000000000000000000000000008131e28323a45515c666e7b86929facb7ab9e91847a6d605a50443b2f261b1106000000000000000000000000000000000000000000000000000000000000000008131e28323e47535f6973808c96a0978d80746a60544a3f34281f140900000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000030f1a26313c44505b666d79838f949da5a49f928d827a706b605c544d443d352d241b12090000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8996a3b0a89b8e8175685b4e4235281b090000000000020f1b2835424e5b6875818e9ba8b0a3968a7d7063574a3d3024170a0000000006121f2b3844505c66727f8c96a0acaea2988f82776c605a50443f38302b26201f1c171a1a1a171c1f20252a30363e464e58616c73808d96a1acab9f948a7d7064584e43372b1d12070000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000060b1012171b1f222f3c4855626f7c8686868686796d6053473a2d201e1a15130f0a04000000000000000000000000000000000000000000000000020f1c2935424f5c6875828f9ba8a6998c7f7366554b4135292422211e1a150e0600000000000000000000000000000000000000000814212e3a47535f6a7683909ca9ac9f92867a6d6054606d7985929eaba99d9083766a5f53473a2f24180d0100000000000000000000000000000000020f1c2835424f5b6875828e9ba8a99c8f8376695c504336291d10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4a56626d72797979797979797979797983909d918479797979797979797979797979797983909d90837979797979797979746e64584c3f33261a0d00101c2936434f5c6976828686868686868b96a2aea89c928c8686868686868686867b6e6154483b2e21150800000000000000000006111b262f3844505c666f7c87929fa8aa9e938a7d70675d51463c2f303a44505b656f7c87929fa8a89f93887d6f675c51453c2f261c1106000000000000000000000000000004111d2935404b5566727f8c99a9a8978a7d7164574a525e687784919da297887c6f625663707c8998a39c8f8276665c514b5864717e8b97a8a8988b7e7265544b4034281c100400000000000000000000000000000000000000050f19242f3a444f59606d79839099a3acaaaca1968e81746c61564d41382d22170c0300000000000000000000000000000000000000000000000000000000000000020c16202b37424d57606d7984919e9f93877c6f665c50443b30251a0d04000000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000a152028333f4a545d676d79828e939fa3a49c948f857d736d665e564f473e362d241b110800000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8895aab4a99c8f8276695c4f4330251a0e0200000000030f1c2936424f5c6975828f9ca8b5ab95897c6f6256493c2f231609000000000713202d3a4653606d7884919ea8b2a99f92867b6e655b50483e342e261e1b1312100c060d060b0f12131a1f252a343d46505a606d7984919ea8b0a69c8f83766a5f5347392e23180c0000000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000001080d11171c1f22272b2d2f3c4855626f7b88939393867a6d6053473a2e2d2a25211f1b15100b0500000000000000000000000000000000000000000000010e1b2734414e5a6774818d9aa7a89b8f8275675d51453c352f2f2e2b2620180f0600000000000000000000000000000000000004101d2935404b55626e7b88949faba89b8e8175685d525c6674808d9aa7ab9f95887c6f62554b4035291d110400000000000000000000000000000000020f1b2835424e5b6875818e9ba8a99c8f8276695c4f4336291c100300000000000000060b0e10111313131313130f0e0c0904000000000000000000000003070b0d0e13131313131312110f0c0701000000000000000000000004080a0b1313131313131308070502000000000000000000000000000000000000000916222e3a46515b62656c6c6c6c6c6c6c6c6c6c74818d9a93867a6d6c6c6c6c6c6c6c6c6c6c6c6c74818e9a9286796d6c6c6c6c6c6c67645c52473c3024170b000f1c2835414e5a6670767979797979798693a0ada6998c8079797979797979797976695e53463a2d2114070000000000000000000b17222d38414d57606d78839099a3aea2988e81756b61554b40342a27333f49535f6a73808d96a1ada49a9184796d60584e42382d22170b03000000000000000000000000000613202c3945515d6776838f9ca9a096877a6e6154474c566774808d9aa9988b7f72655466737f8c99aa998c7f7266544a4854616e7b8796a0a89c8f8275665c5145382c1f1306000000000000000000000000000000000000020b17212935414c56606b73808d95a0a7a09da0a79d938a7e70685e53493f33271e150b0000000000000000000000000000000000000000000000000000000000000000040e1a26313c45515c67707d89939e999083786d60574d42362a1f160c010000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000030b17222d38424b555d676d78818b9298a0a69f97928880786e69605950483f362d231a0e04000000000000000000000000000000000000000000000000000000000814212e3b4754616e7b8798a3aeaa9d9084776a574d42362a1e12050000000005111d2935414c566a7783909daaafa399877b6e6154483b2e21150800000005111e2a36414c5664707d8a96a1adada1978c7f72695e53493f3628231c140c0a060300000000000306090e1419222b343e45515d67717e8a96a0acab9f94887c6f62544b4034281c100400000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000060b13191c23282b2d3337393b3e4855626f7b88959f93867a6d6053473e3b3a36312e2b26201c170e09030000000000000000000000000000000000000000000c1825323f4b5865727e8b98a6ac9f92857a6d60574d45413f3b3a37312a21180e03000000000000000000000000000000000006131f2c3945515d6774808d9aa6aca096897d7063564c54626f7b88959faba79a8d8174675d5145392c20150a00000000000000000000000000000000020e1b2835414e5b6874818e9ba7a89c8f8275695c4f4236291c0f030000000000040b12171b1d1e2020202020201c1b19150f09020000000000000001080e13171a1a2020202020201f1e1b18130c050000000000000000050c11141717202020202020201514120e0903000000000000000000000000000000000006121e29343f4951565860606060606060606064717e8b979a897d70636060606060606060606065717e8b9899897c6f6360606060605a58524a41362b1f1408000d1925323d49545e66696c6c6c6c6d7a8693a0ada6998c80736c6c6c6c6c6c6c6c6c5e574d42362a1e12050000000000000000040f1b27333f49535f69727f8c95a0aba79f92857b6e61594f43392f22222d38414e58606d7984919ea6aca0958c80736a5f544a3f33281f1409000000000000000000000000000714202d3a4753606d7a86929faa9d918477685e52464a5764707d8a99a49b8f8275655c6676828f9ca298897c6f62564946525e697784919eaa9f9285796d6053463a2d2013090000000000000000000000000000000000000a141d29333b45525d68707d87939fa69f959095a0a59e92857a6e655b50443c30271d120700000000000000000000000000000000000000000000000000000000000000000915202834404b55606b75818e97a0958c7f72695e52463e31281d12070000000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000006111c262f3a434b555d666d747f8691969ea5a19a938d827b706b615a50483f352b20160c020000000000000000000000000000000000000000000000000000000713202d3a4653606d7986929facab9f928578695e52463a2d201407000000000713202d3946525d687885929eabac9f9286796d6053463a2d2013070000000714202d3946525e6876828f9ca8b2ab9e9185796d60574d41382d2417110a02000000000000000000000002091019222935404b55606c7884919dabb0a69a8e8174665c5145382c1f130600000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000020a11171e24292e34383a3f4446484b4d55626f7b8895a093867a6d60534d4a4846423c3b37322d28221a150e0600000000000000000000000000000000000000000815222f3b4855626e7b88949faba2988b7f72695f57514c4c4847423c332a20150900000000000000000000000000000000000714202d3a4753606d7985929fabab9e9184786c605346535f6a7683909daaab9f92857a6d6053473d32271b0f01000000000000000000000000000000010e1b2834414e5b6774818e9aa7a89b8e8275685b4f4235281c0f0200000000050e161d23272a2b2d2d2d2d2d2d282825201b140c030000000000020b12191f2326272d2d2d2d2d2d2b2b28241e170f060000000000000810171c2123242d2d2d2d2d2d2d22211e1a140e0600000000000000000000000000000000010d18232d373f464a4c535353535353535355626e7b8897998c7f736659535353535353535355626f7b8898988c7f726559535353534e4c4741382f241a0e03000915212c38424c545a5c606060606d7a8693a0ada6998c807366606060606060605f534d453b31251a0e0200000000000000040e1a242b3744505b656e7b86929fa7ab9f958b7f72695e52473e31271d1b262f3c45515d67707d8a949eaaa89f92877c6f665b50443b31251a0e040000000000000000000000000a1724303d4a5763707d8a99a3a79a8e817467564c414754606d7a86939f9e9285796c606d7985929f9f9285796d605346424d576774818e9aa7a298897d706356493d30251a0e020000000000000000000000000000000006111c262f3b45505a606d7a849199a49f9490849096a1a1978f82776c60584e43392e23180e0400000000000000000000000000000000000000000000000000000000000000030c18232e39434f59616d7a85929f9f92867b6e61594f43392f24180b0200000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000000000a141d28313a434b545c606d727c848e939fa2a49f9490857d716c625a50473d32281e130800000000000000000000000000000000000000000000000000000006121f2b3844505c667784909daaaea298877b6e6154483b2e21150a000000000714212e3a4754616d7a8797a1adaa9e918477665c5145382c1f13060000000814212e3b4754616e7a87939facafa3998c7f72675d51453b2f261b1206000000000000000000000000000000071018242f3944505b66727e8b99a3aeac9f9285796d6053463a2d20130800000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000040b141b22272f35383f444649505355585a5c626f7b8895a093867a6d605b5a5754534d4947433c39332b261f180f09000000000000000000000000000000000000000814212e3a47535f697683909ca5aa9f92857b6e69605d555855534d453c31261a0e0200000000000000000000000000000006131f2b37434e5865717e8b97a2ada3998c7f72655b50444e5865717e8b98a2aea2988b7e7165584e43372b1e1308000000000000000000000000000000010e1a2734414d5a6774808d9aa7a89b8e8175685b4e4235281b0f02000000040e1720282e3336373939393939393534312c251e150c02000000010b141d242b3033343939393939393837342f2921180f050000000008121a22282d3031393939393939392e2d2b261f180f060000000000000000000000000000000007111b252d343a3e3f4646464646464647535f697885929c8f827569574d4246464646464653606c7985929b8e827568564d424646413f3c362f261d1308000005101b26303a42494e4f535353606d7a8693a0ada6998c807366595353535353534846423b33291f140900000000000000020c16202a36424d57606c77829098a3aea3999083786c60564d42352c1f15141d2935404b55616c75828f98a2aea3999083786c60574d42362a20160c020000000000000000000005121e2a36424d576774808d9aaba8978a7e7164574b3e45525d687783909da297887c6f626f7c8998a29c8f8276665c50443e4b5764717e8a97a8aa9a8d807367574d42362a1e1205000000000000000000000000000000030d17222d38424d57616c75818e96a1a39890827a84919ea59f948b7f726a5f554b40342820160c020000000000000000000000000000000000000000000000000000000000000007121d27303d46525e68717e8b949f988f82756c61554b4035291d140a00000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000020b161f28313a424a515b626a6f7a818b9298a0a69f9792877e716c62594f443a3025190d03000000000000000000000000000000000000000000000000000003101c28343f4a546875818e9ba8b3aa978a7d7064574a3d32271b0d04000001081623303d495663707c8996a9b3a89c8f827569544b4034281c10040000030f1b27333f495364717e8b9aa4afac9f92867a6e61554b4033291d140a000000000000000000000000000000000007121d28333f4a54616d7a86929facaea298897d706356493d2f24190d01000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000050d161d262d333a41454a5053535b60626467686a6f7b8895a093867a6d6a686664615e5755534e49443e37312a211a120a01000000000000000000000000000000000006121e2b37424d5763707d89939ea6a29891847b736d676665625f574d42372b1e12060000000000000000000000000000000815212e3b47535f6a7683909da9ac9f92867b6e6153493f4753606d7a85929facaa9d9083776a6054473a2f24190d010000000000000000000000000000010d1a2734404d5a6773808d9aa6a79b8e8174685b4e4135281b0e020000000b16202932393f434446464646464642413d3730271e140900000008121d262f363c3f414646464646464544403a332b21170c01000005101a242c33393c3e464646464646463b3a37312a21180e030000000000000000000000000000000009131b23292e313239393939393937424d576975828f9c928578695f53473a3939393844505b6676838f9c918478695e52463a393433302b241d140b010000000a141e2830383d4143464753606d7a8693aab4a6998d8073665a4d46464646463b3a36312921170d030000000000000008131e28323a46525e69727e8b949faaa89f92877c6f665b50443b30231a0d0b18242f3943505a616e7b86929fa8ab9f958b7f72695e53463e32281e1308000000000000000000000714212d3a46535e697784919eaaa196877b6e6154483b414c566673808d99a9988b7f7266727f8c99aa998c7f7266544a3f3b4754616e7b8796a0aa9d908477695e52463a2d2014060000000000000000000000000000010b151f28333f4a545e69717e8a939ea79f92867b707d89939ea69f92867c6f675c51453d32281e130800000000000000000000000000000000000000000000000000000000000000000b151e2a36414c56606c778390999e938a7d70675d51453c2f261b1106000000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000000000040d161f2830394044515860676d757e8691969fa7a19992887e716b60564c4135291f15090000000000000000000000000000000000000000000000000000000b17232e3f4b5865727e8b98a8b2a69a8d807367584e43372b1f15100c090e131e2a36414c5666727f8c99a5b3aa998c7f7366594c402e23180c00000005121f2b3744505b6575818e9bacb6a99c8f8276685e5243392f21170b020000000000000000000000000000000000010b17222d3846525d6875828f9ca8b4aa9a8d807367564c4135291d1104000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000050e171f282f383f444c51545c6063656c6e71747576787c8895a093867978777573716e6967625f58555047423c332c241c130a0000000000000000000000000000000000020e1a26313c4854606b74818e949da5a09691857f7a7673726e695f53473a2e211408000000000000000000000000000004111d2935414c55626f7c88959faba99b8f8275685e52413845515d6774818e9ba7aca095897c6f62564c4135291d11040000000000000000000000000000000d1a2733404d5a6673808d99a6a79a8e8174675b4e4134281b0e01000006121d28323b444b4f515353535353534f4d48423930251b0f0400030e19242f3840474c4d53535353535352504c453d33291e130700000c17222c363e45494a535353535353534846423c332a1f140900000000000000000000000000000000010911181e2225252d2d2d2d2d2631404c5966737f8c9997887b6e6255483b2f2d28333f4a546673808d9996877a6e6154473b2e2726241f1a130b0200000000020c161e262c3235363a4653606d798698a3aea79a8d81746753493f36393a3c3a38342f271f150b01000000000000030d1924303a44505a616e7b85929fa6ada1968d80746a5f544a3f32291f110807121d28313e46535f69737f8c95a0aca79f92867b6e615a50443a3025190d040000000000000000000815212e3b4854616e7b8796a0ab9e918478695e53463a3d4a5663707d8999a39b8e82756675828f9ca298897c6f6256493c3a46525e697784919daaa095877b6e6154483b2e23170c000000000000000000000000000007121d27313944505b666e7b85929fa5a0958c7f726b75818e97a1a3989083796d60594f443a3025190f0600000000000000000000000000000000000000000000000000000000000000030c1925303a44505b656f7c87929f9e9184796d60584e41382d22170b020000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000000000000040d161e272e343f464e555d606c717c8490959fa7a39a92877d70685e52463c31261a0e0000000000000000000000000000000000000000000000000000000615222f3c4855626f7b8896a0acaa9d9184776a6054473c31271f1c181b1a1e242d3946525e6876838f9ca9aea298897c706356493d302316070000000613202d394653606c7885929eabb3a9988b7f7265564c4131271d0f050000000000000000000000000000000000000006111c2935414c5665727f8b98aab4aa9d918477685d5245392c201306000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000040e172029313a414950555d60666d7075797b7e8082838486929fac9f9286858382807d7b77736f6a64615a534d453e362d251c120900000000000000000000000000000000000915202c38444f59606d79828e939c9fa097928c8683807f7b6e6255483b2f22150800000000000000000000000000000613202c3945515d6774818e9aa7ada1968a7d7063564d4135404b55636f7c8995a0aca79b8e8174685d5245392c20160a0000000000000000000000000000000d1a2633404d596673808c99a6a79a8d8074675a4d4134271a0e0100000b17232e39444d565b5e6060606060605b59534b42372c2015090007131f2b36404a52585a6060606060605e5c574f453a2f24180c0004111c28333e485055576060606060606055534d453c31261a0e020000000000000000000000000000000000070d12161819202020202023303d4a5663707d8999978b7e7164584b3e2f24222d3d4a5764707d8a97978a7d7064574a3d2e231717140e0801000000000000040c141b2125282c3845515c667986929faca89b8f8275655b5046424547484745403931271d12070000000000010b151f2935414c56616c75828f98a2aea69e9184796d60584e42382d20170d00010c161f2a36424d57606d7984919da5aea2988f82756c61564c4135291f160c010000000000000003101c28343f4a5465727e8b98a8a79b8e817468574d42363a4753606d7a86929f9e9285786c7985929f9f9285796d6053463a36424d566774818e9aa7a7988b7e7165544a3f34281c1003000000000000000000000000050e18242f39434e58606c78829097a2a3999083786d616d7a85929ea6a0958d80736b60564c41352921180c030000000000000000000000000000000000000000000000000000000000000008131e27333f49535f6a73808d96a0968d80736a5f53493f33271e14080000000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000040c151c2328343c434c515a626a6f7a839095a0a9a39992857a6d61574d42372b1b110600000000000000000000000000000000000000000000000000000815212e3a47535f6a7784919eabaca095887c6f62584e4339312c282327262b2f35414c56616d7a86929facab9f9285796d6053463a2d2013070000000815222e3b4855616e7b8897a1adada197887b6e6255483b3022150b0000000000000000000000000000000000000000000d1924303c4855626f7b8898a2aeaca095877a6d6054473a2d211407000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000020b162029323b434b535b60676d73797d8285888b8d8f90919298a3aea3989291908e8d8a8784807c76706c625f5750483f372d241b10060000000000000000000000000000000003101c27333d45515c676d7981898f939aa29f9992908d8b7f7265584c3f3225190c00000000000000000000000000000714212d3a4754606d7a85929facac9e9184796d6053463b303a4854606b7784919dabac9f92867a6d6054473d32271b0f0200000000000000000000000000000c1926333f4c5966727f8c99a5a69a8d8073675a4d4034271a0d0100020e1b27333f4b565f676a6c6c6c6c6c6c68655d53483d3125190c000b1723303c47525c64676c6c6c6c6c6c6b6861574c4034281b0f030814212d3945505a61646c6c6c6c6c6c6c6c5f574d42372b1e12050000000000000000000000000000000000000106090b0c1313131314212d3a4754606d7a86939a8d817467554b403529212e3a4754616d7a8796998d807366544a3f34281c100303000000000000000000020a1015191c2834404b546b7885929eabab9e9184786c6056534d51545553514b43392f23180c000000000007121d27313945525d68717e8a939eaaaa9e948a7d70675d51463c2f261c0e050000040d1a26313b45515c66707d89939ea9aa9e948a7e71685e52463d31281d12070000000000000006121f2c3844505c6675828f9ba8a9988b7e7165584b3e313945515d677683909ca197887b6f7b8897a29c8f8276665c504438303e4b5764717e8a97a8a89b8e8275665c5044382c1f12060000000000000000000000020c17202935404b555f6a727f8c949fa89f92877c6f665e68717e8a949ea79f93887d70685e52463f332a1e150a00000000000000000000000000000000000000000000000000000000000000020b17222d38414e58606d7984919e9f92877c6f655b50443b3025190c0300000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000000000000000030b1218222b313a414550585f686d79839097a1aba1978e8174695f5347382d22170b000000000000000000000000000000000000000000000000000006121f2b37434e586673808d99a3afa89b8e81756a5f554b433c38342e3431373a4145525d68737f8c99a3afa79b8e8175675c5145382c1f13060000000a1724303d4a5763707d8a96a9b3ab9e928578695f53473a2e2114030000000000000000000000000000000000000000000813202d394653606c7985929facb1a795897c6f6256493c2f231609000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000a141d28323b444d555d656c717a80858a8e9297979a9b9d9e9fa3aab4aaa39f9e9d9b999796918d88837d766e69615a51493f362d22180b02000000000000000000000000000000000b16212834404b555d676d747d82889297a2a39f9c988b7f7265584c3f3225190c0000000000000000000000000007131f2c38434f5965727e8b98a2aea49a8d8073665c5044382c38434f5965727f8c99a3aea2988b7f7265594f44382c1e130800000000000000000000000000000c1926323f4c5965727f8c98a5a6998d8073665a4d4033271a0d000004101d2a36434f5b677177797979797979756f65594d4134281b0e020d1a26333f4c58646e747979797979797873685c5044372b1e11050a1723303c4955616c717979797979797976695f53463a2d21140700000000000000000000000000000000000000000000000606060613202c3945515d677784909d908377675d5145382c202d3946525e687884919c908376665c5044382c1f120600000000000000000000000005090c18232e43505d6a7683909da9ada196897d7068615f575d6062605c554b4034291c1004000000030c18242f39434f59606d7a85919ea6aea2988f82756c61554b40342a1d140a0000000009141f2834404b54606b75818e97a2ada69e92857a6d61594f43392f24180c030000000000000713202d3a4653606d7985929faba197887b6e6155483b2e35404b556673808c99a9978b7e717e8b97a9998c7f7266544a3f342e3b4754616e7a8795a0ab9f9285796d6053463a2d201308000000000000000000000008131e29323a45515d676f7c87929fa6a0968d80736a5f56616c75828f98a2a49a91857a6d615a50453c30261c11060000000000000000000000000000000000000000000000000000000000000006111b262f3c45515d67707d8a939e999083776c60564c41362a1e150b00000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000000000000000000000710191f282f353f464e565d676e7a85929ea6a99f93877b6e6253493f33271b0f0300000000000000000000000000000000000000000000000000030f1a26313c4854616e7b87929faaac9f92877c6f675d554e46454041414142474c515b606d7a85929eabaca095897d7063554b4034281c10040000000c1926323f4c5965727f8c98a5b2a99c8f837669574d42372b1e120600000000000000000000000000000000000000000006121f2b3844505b667783909daab1a4978b7e7164584b3e3125180b000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000006111b262f3a444d565e676d777e858d91979b9ea2a9a7a8a5a4a4a6acb3aba5a3a4a5a7a6a8a09d9a95908a827b716c635b51483f342a1d140a0000000000000000000000000000000006111c262f3b444d575e666d72797e85929faba8a5988b7f7265584c3f3225190c000000000000000000000000000a15222f3b4854606b7783909daaac9f93877b6e61544a3f3428323d4754616d7a86929facaa9d9184776b6054483a3025190d00000000000000000000000000000c1925323f4c5865727f8b98a5a6998c807366594d4033261a0d000004111e2b3744515e6a77848686868686868175685b4f4235281c0f020e1a2734414d5a67748086868686868685786b5e5245382b1f12050b1724313e4a5764717e868686868686867b6e6155483b2e221508000000000000000000000000000000000000000000000000000004111d2935414c556774818e9a92867a6d6053473a2d202a36414c566875818e9b9285796d6053463a2d2013070000000000000000000000000000071a2734414d5a6774808d9aa9b2a89d91837a726e696c676d6f6d675c5145382c1f13060000000b151e2935404b55606b74818e97a1ada79f92867b6e615a50433a2f22190b0200000000030c18232e39424f59616e7a85929fa7ada1978e81746b60554b4035291e150a000000000000091623303c4956636f7c8997a2ab9e918578695f53463a2d2f3c4956636f7c8998a29a8e8174818d9aa298897c6f6256493c2e2d3946525e687784919daaa297897c6f6356493c3025190d01000000000000000000060f1925303a444f59606d79839199a3a49a9184796d6058505a616e7b86929fa7a1978f81756c62574d42382e23170d04000000000000000000000000000000000000000000000000000000000000000a141d2935404b55616b75818e989f958b7e72685e52463d30271d1207000000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000000000000000000000070d161e2429343c444c555e68707d8a949faba49a8d8174655b5044372b1f120500000000000000000000000000000000000000000000000000000a15212d3a46535e6975818e98a3aea3999083796d675f5853514b4e4e4e4d53555d606d74818e97a1ada69d9083776b605443392e23180c000000000e1b2834414e5b6774818e9aa7b3a79a8d8074675a4d4131261a0e02000000000000000000000000000000000000000000030f1c28333f4a546875818e9ba8b3a6998d8073665a4d4033271a0d000000000000000000000000000000000000000000000006121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000b17222d38414c565e696e79828b91979ea1a9aba8a19e9b9997989ba2aba1999697989b9ea0a8aaa79f9d948f867e726d635a50463c2f261b11060000000000000000000000000000000b17222d38424d565e696e787f858b9297a29f9c98958b7f7265584c3f3225190c00000000000000000000000006111b2935414c56636f7c8995a0aca99c8f8276695f5342382e232d3946525e6875828e9ba8aca095897c6f63564c41362a1b1106000000000000000000000000000c1825323f4b5865727e8b98a5a6998c7f7366594c403326190d000004111e2b3744515e6a778491939393938e8275685b4f4235281c0f020e1a2734414d5a6774808d939393939185786b5e5245382b1f12050b1724313e4a5764717d8a9393939393887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000010d19242f3e4b5865717e8b9899897c6f6356493c302325303f4c5865727f8b9898887c6f6255493c2f22160800000000000000000000000000000b1724313e4a5764717d8a97a1adaca09591847f7b7978797a7c796d6053473a2d201407000007121c27303945515d67707d89939da9aba0958c7f72695e53483e31281d100700000000000007121d27303d46525e68727f8b959faba99e93897d70675d51453d30261c11060000000005111d2935414c566673808c99a9a89b8e817568574d42372b2d3a4653606d7985929f9d90847783909d9f9285796d6053463a2d2a36414c566774818d9aa7a9998d807366564c41362a1e11050000000000000000030c18212a36414c56616b74808d95a0a89f93887d6f675c5146535e69727f8b959fa99e938b7e71695f544a3f34281f160c01000000000000000000000000000000000000000000000000000000000000020b18242f39434f59616e7b85929f9f92857a6e61594f43392e23180c030000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000000000000000000000000040c1319222a323a434d56616c7683909cabac9e9285786c605346392d201306000000000000000000000000000000000000000000000000000005121e2a36424d57616e7b86929fa6aba0958f82796f6a63605c555b5a5b575f62676d747f8c939ea9a99f948a7d7064594f4430271d120700000000101c2936434f5c6976828f9ca9b2a5998c7f7266594c3f3326190900000000000000000000000000000000000000000000000b17222d404d5a6773808d9aa6b3a89b8e8175685b4f4235281c0f000000000000000000000000000000000000000000000000121f2c3945525f6c7885929fabada093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000030f1b27333f49535d686e7b838f949ea1a9a9a19e9996918e8c8b8b909ba5998f898a8c8e9196999ea1a9a69f98928a7f726c62584e41382d22170b0000000000000000000000000000030f1c28333f4a545e696e7b838c92979f9f99938f8b88877f7265584c3f3225190c0000000000000000000000000b17222d3946525d6875818e9ba7ada1978a7e7164574d4230261c2a36414c5663707d8996a1ada79b8e8175685e5246382d22170b000000000000000000000000000b1825323e4b5865717e8b98a4a5988c7f7265594c3f3226190c000004111e2b3744515e6a7784919d9f9f9b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9a9f9f9e9185786b5e5245382b1f12050b1724313e4a5764717d8a979f9f9f94887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000815222f3b4855626e7b8897988c7f7265594c3f3025232f3c4956626f7c8998988b7e7265584b3f3024190d01000000000000000000000000000713202d3a4653606d7985929ea6b0a7a096918b8886858687877b6e6154483b2e21150800000c18232e39424e58606d7984919ea5afa4999083786d60574d42362c1f160c00000000000000000b151e2a36414c56606c78839099a4afa59e9184796d60584e42382e23170c000000000713202d3946525d687683909da9a9988b7e7265584b3f31262c3844515c6676828f9c9f93867a86929f9c8f8275665c5044382b25303e4a5764717d8a97a7aa9d908377685e5246392d20140600000000000000000b151e2a333c46525e68707d8a929da8a1968d80746b60554b424d57606c78839099a3a59f92867b6e665c50443d31281e13080000000000000000000000000000000000000000000000000000000000000007121d27313e46525e68727f8b959f978e81756b60554b4034281f15090000000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000010810182028313b44505a64717e8a99a3ada197887c6f6255493c2f2216090000000000000000000000000000000000000000000000000000020e1a25313b46535f69737f8c949fa7a79f948f837c75706d676867676869696e737a818c919ca5aaa1978f82766c6155473d331e150b0000000000101d2a3643505d697683909ca9b1a4978a7e7164574b3e3124180b0000000000000000000000000000000000000000000000061926323f4c5965727f8c98a5b2a89c8f8275695c4f4236291c0f0000000000000000000000000000000000000000000000030d152c3945525f6c7885929fabada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000010c161f2b3744505b656d7a8490959fa6aaa29f96918c8884817f7e7e8b98a396897d7d7f8184888c91979fa3aaa29f918b7e716a5f53493f33271b0f030000000000000000000000000006121f2b3844505b666e7b8490959ea19d948f87827e7c7a786c605346392d2013060000000000000000000000030f1b27333f4953616d7a86929facab9e9285796d6053463b31201925303a4653606c7884919eabac9f92867a6d6153493f33271b0f030000000000000000000000000b1824313e4b5764717e8a97a4a5988b7f7265584c3f3225190c000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aca194887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000613202d394653606c7985929b8e827568574d42362a202d3a4653606d7986929b8e817468564c4135291d11040000000000000000000000000006131f2c3845515c67737f8c949fa6ada8a19e989992929299877b6e6154483b2e2115080004101c2834404a54606a73808d96a09fa99f93877c6f665c50453b31241a0d040000000000000000030c1925303b44505b666f7c87939fa99fa1968d80736a60544a3f34281c10030000000714212e3a4754616d7a86939faca197887b6f6255483c2f222834404a5466727f8c99a4998c7f8c99a3998c7f7266544a3f3428212e3a4754616d7a8795a0ac9f93877a6e6154473b2d22170b0000000000000007121c27303c45515b616d7a85919ea4a59e9184796d60594f433b44505b666f7c86929fa7a2989083786d60594f433a2f24190f05000000000000000000000000000000000000000000000000000000000000010b151f2a36414d56606c788390999e93897d70675c51453c31261a0e0400000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000000000000000000000000000000060e161f29323e4753606d7a86929f9fa9988b7e7265584b3f3225180c00000000000000000000000000000000000000000000000000000009141f2a36424d57606d78828f959fa7a69f959087817d79777574747476787b80858e939ca3aaa29892857b6e615a5044352b210c030000000000111e2a3744515d6a7783909daab0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4b1a99c908376695d5043362a1d1000000000000000000000000000000000000000000000010b151f2935414c566c7885929fabada093867a6d6053473a2d20160c0200000000000000000000000000000000000000000000000008131e2935414c56606c77828f96a0a7a8a198928c84807b787572717b8895a0938679717274777b80848d9299a2aaa39f92867c6f655b5044372b1f130800000000000000000000000003101c28343f4a54606c788390969fa79d938e827b75726f6e6c665b5044382b1f1206000000000000000000000005121f2b3744505b65727f8c98a3aea79a8d8074675c5145382c1f131f2b3844505b6673808c99a4aea3988c7f72655b5044372b1f14080000000000000000000000000b1724313e4a5764717d8a97a4a5988b7e7265584b3f3225180c000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800000000000000000000000000000000000000000000000000000005121f2b3744505b6576828f9c918478695e52463a2d202c3845515c667683909d918477685d5245392c2013070000000000000000000000000004101c2834404b55606d78828f949ea1a8a9aaaba39f9f9f94877b6e6154483b2e2115080006121f2c3844515c666f7c879293939393978d80746a60544a3f33291f11080000000000000000000008141e28333f4a54606a74808d979393939392877c6f665c5044382c1f12060000000b1724313e4a5764717d8a99a4ab9e9285796c605346392d20232e3c4955626f7c8897a29e9184919ea298897c6f6256493c2e23202d3946525e687784909daaa49a8b7e7164544a3f33281c0f030000000000040d18232e39424d57626d75828f97a1a99e938a7d70675d51473d333f4a545f6a73808c95a0aa9f958c80736b60554c41352921170b02000000000000000000000000000000000000000000000000000000000000030d1925303b44505b666f7c87929f9e9184796d60574d42372b20160c02000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000000000040d17202c3945515d67778490939393938c807366594d4033261a0d000000000000000000000000000000000000000000000000000000030e1a26313b44505c666d7a8390959da5a7a099938e898683828181818385888c92979da5a7a09892867d70695e52483e3323190f000000000000111e2b3844515e6b7784919eaaafa396897c706356493d3023160a00000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1aa9d9083776a5d5044372a1d110000000000000000000000000000000000000000000007121d27313945525d687885929fabada093867a6d6053473e32281e13080000000000000000000000000000000000000000000000010d19242f3946525e68727f8c949ea8a8a19691867f79736e6968666f7b8895a093867a6d6568696e737980879298a2aea3999083786c6053463a2f24190d01000000000000000000000006121f2b3844505c66727f8b959fa89f958e81786e69656261605b544a3f33281c0f0300000000000000000000000613202d394653606c7884919daaab9f95887c6f62554b4034281c101c28333f4a54616e7b87939facaa9e9184786c6053463b3025190e0000000000000000000000000a1724313d4a5764707d8a97a3a4988b7e7165584b3e3225180b000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000030f1b27333f49536673808c9396877b6e6154483b2e212834404b546774808d9393867a6d6054473a2d21140700000000000000000000000000000c18232e3944505c666d7a828c91969a9c9e9f9f9f9f9e94877b6e6154483b2e211508000713202d3a4653606d798386868686868686857a6d60584e42382e21170d0000000000000000000000020b17222d38424e58606d7a858686868686868683796d6053463a2d201307000006121f2b37434e586774818e9aaba89b8f8275655b5044372b1f202d394653606c7985929fa1969196a19f9285796d6053463a2d201e2a36414c566774818d9aacac9b8e8175665b5044382b1f120600000000010c161f2834404a545f69727e8b949ea9a1978e81756b61554b41352d38424e58606d79839199a4a79f92877d6f675d51453e33291d140a0000000000000000000000000000000000000000000000000000000000000008141f28333f4a545f6a73808d96a0968c8073695f53473e32281e1308000000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000000000000000000000000000000000005111d2935404b556976828686868686868174675b4e4134281b0e0100000000000000000000000000000000000000000000000000000009141f28343f4a545e686d7a838e929d9fa7a49f9b9892908e8e8d8e8f9197999ea1a9a29e9590867d706b60574d42362c221108000000000000121f2b3845525e6b7885919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0aa9e9184776b5e5144382b1e11000000000000000000000000000000000000000000030c18242f39434f59606d7a86929facaea194877b6e615a50443a3024190d030000000000000000000000000000000000000000000004111d2935414c55616d7a86929fa6aba19691847c726d66615f57626f7b8895a093867a6d60575f61676d737d86929fa5ab9f958a7d7064554c4135291d110400000000000000000000000713202d3a4653606d7884919ea7a89d9083786d665f57555453504a42382d22170b000000000000000000000005111e2a36414c5663707d8996a0acaa9d9083766a5f5343392e23180c17222d3846535e6976828f9ca9aca096897d7063564d41362a1c110600000000000000000000000a1724303d4a5763707d8a96a3a4978b7e7164584b3e3125180b000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000b17222d3d4a5763707d868686867d7164574a3e3124232e3e4b5764717e868686867d7063564a3d3023170a000000000000000000000000000007121d28343f4a545e686d787f848a8d9091929292929190877b6e6154483b2e2115080006121f2c3844515c666d7779797979797979786d685d52463d30261c0f0500000000000000000000000006111c262f3c45525d686d7879797979797979776d665c5044382c1f120600000814212e3a47535f6a7884919eaba9988b7f726553493f33271b1f2b3844505b6675828f9ba8a19ea1a89c8f8275665c5044382b1f1925303e4a5764717d8a9aa4ab9e9285796c605346392d2013080000000008131e28313a44515c666e7b86929fa6a69e92857a6d61594f433a2f262f3c45515c666f7c87939fa8a39991847a6d605a50453b2f261c1106000000000000000000000000000000000000000000000000000000000000020b17222d38424e58606d7984919e9f92867b6e625a50443a3024190c030000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000000000000000000000000000000000010d18242f3a4e5a667076797979797979746f64584c4033271a0d01000000000000000000000000000000000000000000000000000000030b17232e38424c565e686d79818990959b9fa2aaa39f9d9b9a9a9b9c9ea1a9a49f9c97928c837b706b60594f453b30241a1000000000000000121f2b3845525e6b7884919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0aa9d9184776a5e5144372b1e110000000000000000000000000000000000000000000a151e2935404b55606b74818e98a3aeb5a89c8f82756c61564c4135291f150b010000000000000000000000000000000000000000000613202c3945515d6773808d98a2aea49991847b6e6a605c545355626f7b8895a093867a6d605353555d606b707d8a939ea9a79c8f8276675d5145392c20130600000000000000000000000a1623303d495663707c8996a1aca096897d70665c544d494746443f382f261c110600000000000000000000000714202d3946525e6875828e9ba8aea2988b7e7165584e4330271d1207111c2a36424d5764717e8a97a1ada89b8f8275685e5246382e23170b00000000000000000000000a1723303d4a5663707d8996a3a4978a7d7164574a3e3124170b000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000616232f3c4855616b7079797979716c6155493c302323303d4955616c7179797979706b6055483c2f2316090000000000000000000000000000000c17232e38424c565e666c72797d808384858686858483817a6d6054473a2d2114070004101c2834404a545c606a6c6c6c6c6c6c6c6b605d564c41342b1e150a00000000000000000000000000000a141d2935414c565d606b6c6c6c6c6c6c6c6a605c544a3f34281c100300000815222f3b4855626e7b8896a1ada297887c6f6255493c2d22171c28333f4a5465727f8b98a9acabaca9988c7f7265544a3f34281c14212e3a4754616d7a86939faca197897c6f6256493c3024190d010000010d19242f3a434f59606d78839098a2a99e948a7e71685e52473e31281d2834404b54606b74808d96a1aba0968e81746c61574d42382d22170b0000000000000000000000000000000000000000000000000000000000000006111c262f3c45515d67707d8a939e988f82766c61564c4135291e150a0000000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000000000000007131d323e49545e66696c6c6c6c6c6c67645c53483c3024180b000000000000000000000000000000000000000000000000000000000006111c26303a444c565e676d747c83898e9298999b9d9e9f9f9f9f9e9d9b999993908b857f786e6960594f473d33291f120800000000000000111e2b3844515e6b7784919eaab0a396897d7063564a3d3023170a00000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a99d9083766a5d5043372a1d10000000000000000000000000000000000000000006111c26303845515d67707d89939daab4b9aa9e948a7e71685d52463d31271d12070000000000000000000000000000000000000000000714212d3a4754606d7a85929faaab9f93877d6f695f58514b4855626f7b8895a093867a6d6053474b5159616b74818e9ba8ac9f92867a6d6054473a2d21140700000000000000000000000d192633404c5966737f8c99a8aa9d9184776b60544a423c3b3938332d261d140a0000000000000000000000030f1c28333f4a54616e7a86929facac9f92857a6d6053473c3120150b000e1a25313b4653606d7985929eabac9f92867b6e61544a3f34281c100300000000000000000000091623303c4956636f7c8996a2a3978a7d7064574a3d3124170a000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000714202c38444f5961636c6c6c6c64615a5044392d21212d3945505a61646c6c6c6c6360594f44382c20140700000000000000000000000000000006111c26303a444c545b60666d70737677787979787876746d685d5245392c20130700000c18232e39424a51535d606060606060605e54524c433a2f22190c030000000000000000000000000000020b19242f3a434c52545e606060606060605d53504a42382e23170c000004101c2834404b5565727f8b98a89f9f9285796c605346392d201317222d3b4855626e7b8897a19f9f9fa297887c6f6255493c2e231713202d3946525e687784909d9fa9998c7f7366564c4135291d1105000004111d2935414c55606b73808d959f9fa2978f82756c61564c41352c1f18232e39424f59606d7984919ea5a89e938a7e71695e544a3f33281c0f03000000000000000000000000000000000000000000000000000000000000000a141d2935404b55616c75828f989f948a7e71685d52453d30261c110600000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000000000000000000000000000000000000115212d38424c545a5c6060606060605b58534a41362b2014080000000000000000000000000000000000000000000000000000000000000a141e28323a444c555c606b6f777d8185898c8e90919292929291908f8d8a86837e79726d665f574f473d352b20170d0000000000000000111e2a3744515d6a7784909daab0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000c1825323f4b5865727e8b98a5b1a99c8f8276695c504336291d1000000000000000000000000000000000000000020b17232e38424e58606d7984919ea5afafacafa69e92857a6d61594f43392f24180c0300000000000000000000000000000000000000030f1b27333f495364717e8a98a2aca3998d80746b60574e45404855626f7b8895a093867a6d60534740454f59626f7c8896a0aca3998a7d7063574a3d3024170a00000000000000000000020f1b2835424e5b6875818e9ba8a79a8e817467594f4239302e2d2b28221c140b02000000000000000000000006121f2b3844505b66737f8c99a3aea79a8e8174675d5145392c2013030009141f2c3845515c6674808d9aa7afa3998c7f73665c5044382b1f1409000000000000000000000916232f3c4956626f7c8995a2a3968a7d7063574a3d3024170a000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000004101c28333e474f555760606060575550483e33281c1d28333e485055576060606056554f473d33271c1004000000000000000000000000000000000a151e29323a424a50545c606467696b6c6c6c6c6b6967605d564c4135291d1104000007121c2730394044465153535353535353524745413a31281e10070000000000000000000000000000000008131e28313a41454752535353535353535146443f3830261c1106000006131f2c3845515c6775828f939393938f8275665b5044382b1f1214212e3a47535f6a78859193939393939285796d6053463a2d2013111d2935414c566774808d93939393908376685d5246392d20130700000613202c3945515d676f7d87939393939392857b6e615a50443a30231a121d27303d45515d67707d8a939393939392857b6e665b5044382b1f120600000000000000000000000000000000000000000000000000000000000000020b18242f3a43505a616e7b86929f9e92857a6d60594f42382e23170c03000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000000000000000000000000000000000000a15202a343c4347495353535353535353534f4940372c21160a000000000000000000000000000000000000000000000000000000000000020c162029323a434b515960636b7075797c7f82838485868685858382807d7a76726d67605c544d453d352b23190e050000000000000000101d2a3643505d697683909ca9b1a5988b7e7265584b3f3225180700000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685c4f4235291c0f000000000000000000000000000000000000000a141d28343f4a54606a73808d96a0acaca49fa4aca1978e81746b60554b4035291e150a0000000000000000000000000000000000000005121f2b3744505b6574818e9b9ea09f92867b6e61594f453c3c4855626f7b8895a093867a6d6053473a3e47535f6a7784919eaaab988c7f7265594c3f3226190c00000000000000000000030f1c2936424f5c6975828f9ca8a4988b7e7165584b3e302721201f1c17110a020000000000000000000000000613202d394653606c7884919eabaca095897c6f62554b4035291d11040004101c2834404b54626f7c88959fabab9e9184786d6053463b31251a0e000000000000000000000916222f3c4955626f7c8895a2a396897d7063564a3d3023170a000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800000000000000000000000000000000000000000000000000000000000b16212c353e44484a535353534a49443e362c221717222c363e45494b535353534a48443d352c21160b0000000000000000000000000000000000030c1720292f383f444a5053575a5d5e5f5f5f5f5e5d5b54524c443a2f24190d010000000b151e272e34383a4446464646464646453a39352f281f160c0000000000000000000000000000000000010c161f282f35393a4546464646464646443a38342e261e150a0000000713202d3a4653606d79868686868686867f7266544a3f33281c0f121f2b37434e58687581868686868686868275665c5044382b1f120d1925303d4a5764707e868686868686877a6d6154473a2e21140700000714212d3a4754606d7a84868686868686867f71695e52483e32281e110b151e2935414b55616b75818686868686868682796c605346392d201306000000000000000000000000000000000000000000000000000000000000000007131d28313e46525e69727f8c95a0978e81746b60544a3f34281f1409000000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b00000000000000000000000000000000000000030f1b26323c464e535560606060606060605f5a52493e33271b0f02000000000000000000000000000000000000000000000000000000000000050e172029313940454f54596063676d70727576787879797878777573706d6865605d55504a423c332b231911070000000000000000000f1c2835424f5b6875818e9ba8b3a6998c807366594d402f23180c00000000000000000000000000000000000000000000010e1b2834414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e00000000000000000000000000000000000006111b262f3844505c666f7c87929fa8a69f9a939aa4a99d93897d70675d51453c30261c11060000000000000000000000000000000000000613202d394653606c78858b8e9196968f8275695e53473d333c4855626f7b8895a093867a6d6053473a37434e586976828f9ca9a69a8d8073675a4d4034271a0d0000000000000000000003101d293643505c6976838f9ca9a3978a7d7064574a3d31241513120f0b060000000000000000000000000005121e2a36424d5763707d8a96a1acaa9d9083776a6054433a2f24180d0100000c18232e3947535f6a7683909daaada1968a7d7063574d42362a1c12070000000000000000000915222f3c4855626f7b8895a2a396897c706356493d3023160a000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000005101a232c33383c3d464646463e3c39332c241a10101a242c33393d3e464646463d3c38332c231a0f05000000000000000000000000000000000000050e171d262d33383f44464a4d50515253535251504e4745413a32281e130800000000030c151c23282c2d3739393939393939382d2c29241e160d04000000000000000000000000000000000000040d161e24292c2d3839393939393939372d2c28231c150c0300000006131f2c3845515c676d79797979797979726d635742382d22170b0f1a26313c4d59656f7579797979797979757065544a3f34281c10081623303c4955616c707979797979797975685d5246392d20130700000613202c3945515d676d7879797979797979716d62574d42362c20160c030c18242f3a434f59656f7579797979797979766c665b5044382b1f12060000000000000000000000000000000000000000000000000000000000000000010c161f2a36424d57606d788390999f93887c6f665c50443b31251a0d040000000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b0000000000000000000000000000000000000006131f2b37434e585f626c6c6c6c6c6c6c6c6c645a4f43372b1e120500000000000000000000000000000000000000000000000000000000000000050e171f272f343d43484f54555c606366686a6b6c6c6c6c6b6a686664615e5653514b4c4841382f21191108000000000000000000000d1a2734404d5a6773808d9aa6b3a89b8e817568554b4034291c100400000000000000000000000000000000000000000005121e2a36424d576976838f9ca9b2a5988c7f7265594c3f3226190c0000000000000000000000000000000000000b17222d38414d57606d78839099a3ab9f948f87939fa8a59e9184796d60584e42382e23170c0300000000000000000000000000000000000613202d394653606c777c7e8184878a8b7e7165574d42352f3c4855626f7b8895a093867a6d6053473a32414e5b6874818e9ba7a79a8d8174675a4e4134271b0e0000000000000000000003101d293643505c6976838f9ca9a396897c706356493d3023160a06030000000000000000000000000000000714202d3a46525e6975828f9ca8aea3988b7f7265584e4331281d130700000007121d2b37434e5865717e8b98a2aea89c8f8275695e5346392e23180c0000000000000000000815222f3b4855626e7b8895a1a295897c6f6256493c2f231609000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800000000000000000000000000000000000000000000000000000000000008111a21282c2f303939393931302d28221a120808121a22282d303139393939302f2c27211a11080000000000000000000000000000000000000000050b141c22282e34383a3d404344454646454543413a39352f2820160c010000000000030b12181c1f202a2d2d2d2d2d2d2d2b21201d19130c040000000000000000000000000000000000000000040c13191d20212b2d2d2d2d2d2d2d2a201f1c17110a030000000004101c2834404b555c606c6c6c6c6c6c6c66635b51462f261c11060a1520313d48535d65686c6c6c6c6c6c6c69655d5442382e23170b0814202d3944505a61646c6c6c6c6c6c6c6b5d564c4135291d1105000004111d2935414c555d606b6c6c6c6c6c6c6c65625a50453b30241a0e040007131d28313e47535d65686c6c6c6c6c6c6c69605b544a3f33281c0f03000000000000000000000000000000000000000000000000000000000000000000040d1a25303b44505c666f7c87939f9a9083786d60574d42362a1f160c0100000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000000000000815212e3b47535f6a767979797979797979766c5f5346392d2013060000000000000000000000000000000000000000000000000000000000000000050d1925303b444c525f6060606060605d5d5e5f5f5f5f5e5d5c5a6060606060605a58534a41362b201408000000000000000000000c1925323f4c5865727f8b98abb5aa9d908477675c5145382c1f13060000000000000000000000000000000000000000000714212d3a46535f697885929fabb4aa968a7d7063574a3d3024170a0000000000000000000000000000000000040f1b27333f49535f69727f8c95a0aba3998f82808c96a0aca0968d80736a5f544a3f34281f1409000000000000000000000000000000000005121f2b3744505b656c6f7274777a7d807a6e6154473b312f3c4855626f7b8895a093867a6d6053473a35414b556875828e9ba8a69a8d8073675a4d4034271a0d0000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000000000003101c28343f4a54616e7b87929facac9f92867a6d6154473d3221160c01000000000f1b26313c4754606d7a85929facac9f93877b6e61544a4034281c100400000000000000000815212e3b4854616e7b87949f9f95887c6f6255493c2f221609000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000810161c2023242d2d2d2d2423211c17100800000810171d2123242d2d2d2d2323201c160f0800000000000000000000000000000000000000000000020a11171c23282c2d31343638393939393836342d2c29241e160d040000000000000000070c1012131e202020202020201f1413110d08010000000000000000000000000000000000000000000001080d1113141f202020202020201e1312100c06000000000000000c18232e39434b51535f606060606060595751493f351d140a000314202c37414b53595b606060606060605c5a544b4230261c110604101c28333e485055576060606060606054524c443a3024190d010000010d19242f3a434c51545e60606060606060585650483f33291f12080000010c161f2c35414b53595b606060606060605c53504a42382d22170b000000000000000000000000000000000000000000000000000000000000000000000009141f28343f4a54606a74808d97a0958c7f72695e53463e31281d130700000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000000000000916222f3c4955626f7c8686868686868686796c605346392d201306000000000000000000000000000000000000000000000000000000000000000005111e2a36414c565e6c6c6c6c6c6c6c6a675f555353524f5960636c6c6c6c6c6c67645c53483c3024180b00000000000000000000091623303c4956636f7c8999a4afac9f9286796d6053473a2d22170b0000000000000000000000000000000000000000000815222e3b4855616e7b8897a2adaea298887b6e6155483b2e22150800000000000000000000000000000000040e1a242b3744505b656e7b86929fa7a89f92867c7984919ea5a89f92877c6f665c50443c31261a0e0500000000000000000000000000000000030f1b27333f49535b60626568686d70736e685e524639292f3c4855626f7b8895a093867a6d6053473a3a45515d677683909da9a5998c7f7266594c3f3326190c0000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000000000006121f2c3844505c6673808c99a3afa89b8e8175685e5246392d20130400000000000a15202c3945515d6774818e9ba7afa4998d8073665c5144382c1f150900000000000000000814212e3b4754616e7a8793939393887b6f6255483c2f221509000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000000000000050b1014161720202020171614100b0500000000060c1114171820202020171614100b0500000000000000000000000000000000000000000000000000060b11171c1f2024272a2b2c2c2c2c2b2a2821201d19130c0400000000000000000000000406071113131313131313120706040100000000000000000000000000000000000000000000000000000104060712131313131313131107060300000000000000000007121d273039404546525353535353534c4a463f372d230b0200040f1a252f3941484d4e535353535353534f4d494239301e140a00000b17222c363e44494a535353535353534746413a32281e13080000000008131e28313a41454751535353535353534b4a453f362d20170d00000000040d1a232f3941484d4e535353535353535046443f382f261c11060000000000000000000000000000000000000000000000000000000000000000000000030b17232e38424e58606d7a84919e9f92867b6e615a50433a2f24180d01000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000000000000916222f3c4955626f7c8893939393939386796c605346392d20130600000000000000000000000000000000000000000000000000000000000000000714202d3946525e68767979797979797771675b4f464854606b70797979797979746e64584c4033271a0d010000000000000000000714202d3a4753606d7a86939facaea399897d706353493f33271b0f030000000000000000000000000000000000000004111d2935414c5565717e8b98a9b3ac9f9285786d6053463a2d201307000000000000000000000000000000020c16202a36424d56606c77828f98a3aca0968c8073707d8a939eaaa3999083786d60574d42372b20170d02000000000000000000000000000000000b17222d38414950535558565d616366615e564c41362a2f3c4855626f7b8895a093867a6d6053473e444d57606d7a86929faca9988b7e7165584b3e3225180b0000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000000000713202d3a4653606d7984919eabaca096897d7063564c4135291d1105000000000004111d2935414b55636f7c8995a0acab9e9185796d6053463c31261a0e00000000000000000714212e3a4754616d7a8686868686867b6e6255483b2f221508000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000407090a131313130b0a0804000000000000000005080a0b131313130a0907040000000000000000000000000000000000000000000000000000000000060c101213171a1d1e1f20201f1e1d1b1413110d080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151e272e34383a464646464646463f3e3a352d251c1100000009131d272f373d40424646464646464642413d3730271e0c02000005101a242c33393c3d464646464646463a3935302820160c0200000000010c161f282f35393a45464646464646463e3d3a342d241b0e05000000000008111d272f373d404246464646464646433938332d261d140a0000000000000000000000000000000000000000000000000000000000000000000000000006111c26303d45515d67717e8a949e988f82756c61554b4035291d1104000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000000000000916222f3c4955626f7c88959f9f9f9f9386796c605346392d20130600000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a86868686868683776a5d5144495663707d8686868686868074675a4e4134271b0e010000000000000000000613202c3945515d677784909daab4ab9a8d8073655b5044372b1f140a000000000000000000000000000000000000010c13202c3945515d6775828e9ba8b5a89c8f8275665c5044382b1f120600000000000000000000000000000008131e28323a46525e69717e8b949faaa59e9184796d6b75818e98a2aba0958c7f72695f53463f32291e14080000000000000000000000000000000006111b262f383f4446494b4c5254575954524c443b30252f3c4855626f7b8895a093867a6d605347464f565f69727f8b98a3ada197887c6f6255493c2f2216090000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000000000005121e2b37424d5764717d8a97a1adab9e9184786c6053463a3025190d010000000000010d18242f3a4854606b7784919dabada1978a7d7164574d42372b1d1207000000000000000713202d3946525e687679797979797976695f53473a2e211408000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306070a0d10111213131212100e0707040100000000000000000000000000000000000000000000000001040707131313131313130d0c0a0702000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151d23282c2d3939393939393933312e2a231c130a000000020b151d252c313435393939393939393634312c261e150c0000000008111a22282d3031393939393939392e2d29241e160e04000000000000040d161e24292c2d383939393939393932312e29221b1209000000000000000b151d252c31343539393939393939362d2b28221c140b0200000000000000000000000000000000000000000000000000000000000000000000000000000a141e2935414c55616c75828f9893948a7d70675d5145392c201306000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000000000000916222f3c4955626f7c8895a2acac9f9386796c605346392d20130600000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a87939393939084776a5d5144495663707c89939393938d8174675a4e4134271b0e0100000000000000000004101d2935404b556773808d9aa9b3ab9e9184786c6053463c2f261b1106000000000000000000000000000000000007131d28333f4a54606d7a86929facb1a7988b7f7265544a3f34281c10030000000000000000000000000000030d1924303a44505a616e7b85929fa6a99e93897d7067616e7b86929fa7a79f92867b6e615a50443b3025190d04000000000000000000000000000000000a141d262d3337393c3f4146474a4d4746413b3229222f3c4855626f7b8895a093867a6d605350535961686e7b85929eaaac9e9285786c605346392d2013060000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000000000714212d3a46535f6976828f9ca9afa3998c7f73655b504437281e13080000000000000007131d2c38434f5965727f8c99a3aea99c8f8276695f5347392e23180c0000000000000005111d2a36414c565e6c6c6c6c6c6c6c6c5f574d42372b1e1206000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000000000002080d10121313131313131313070704010000000000000000000000000000000000000000000000000002070b0d0d13131313131313130f0e0c090400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080d111314202020202020201a1916130d07000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b12181c1f202c2d2d2d2d2d2d2625221e18110a0100000000030b131a202527282d2d2d2d2d2d2d292825211b140c0300000000000810171c2023242d2d2d2d2d2d2d21201d19130c040000000000000000040c13191d20212b2d2d2d2d2d2d2d2524211d1811090000000000000000030b131a202527282d2d2d2d2d2d2d29201f1c17110a02000000000000000000000000000000000000000000000000000000000000000000000000000000020c19242f3a43505a616e7b8686868686847a6d6053473a2d201407000b1825323e4b5865717e8b98a4a69a8d8073675a5a6773808d9aa6a4988b7e7165584b3e3225180b000000000000000000000000000000000000000916222f3c4955626f7c8895a2acac9f9386796c605346392d20130600000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a87949f9f9d9084776a5d5144495663707c89969f9f9a8d8174675a4e4134271b0e01000000000000000000010d18242f3d495663707c8997a1adaca196897d7063584e41382d22170f06000000000000000000000000000000071118242f3844505b66717e8b98a2aeaca095887b6e6155483b2e23170b0000000000000000000000000000010b151f2935414c56616c75828f97a2ada2978e81756b605e69727f8c95a0aca2988f82766c62564c41362a1f160c01000000000000000000000000000000020b141b22272b2d2f3035393a3d403b3936302920232f3c4855626f7b8895a093867a6d60545c60636b707a839197a1ada49a8e8175655b5044372b1f12050000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000004101c2834404b55616e7b87939facac9f92867b6e6153493f3327160c0200000000000000010f1b27323d4754616d7a86929facac9f93877b6e61554b4034281c1004000000000000010d1925303a444c525f60606060606055534d453c31261a0e02000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800000000060d14191c1f1f202020202020201413110d080100000000000000000000000000000000000000000001080e1317191a20202020202020201c1b191510090200000000000000000000000000000000000000000000000000010507070b0e101212131312110f0d0a07060400000000000000000000000000000000000000000000000000040c13191d202d2d2d2d2d2d2d2d2625231e19120a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c1013131f202020202020191816120d070000000000000002090f14181b1b202020202020201c1b191510090200000000000000050b10141617202020202020201413110d08020000000000000000000001080d1113141e20202020202020181715110c060000000000000000000002090f14181b1b202020202020201d13120f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000008131e28313e46535f696e7979797979786d675d5145392c201306000b1825323e4b5865717e8b989f9f9a8d8073675a5a6773808d9a9f9f988b7e7165584b3e3225180b000000000000000000000000000000000000000916222f3c4955626f7c88959f9f9f9f9386796c605346392d20130600000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8794a1aa9d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e01000000000000000000000713202d3a4653606d7985929eacb2a89c8f82756a5f53493f332721180f0802000000000000000000000003091119232935404b55606c7884919daab3a99d908477695f53463a2d1c1106000000000000000000000000000007121d27313945525d68717e8a939ea9a69f92857a6d615957606d7883909aa4aa9f948b7e71685e52463e31281e130800000000000000000000000000000000020a11171b1f202224292d2e30332e2d2a25292c2e343c4855626f7b8895a093867a6d6063666d70767d859195a0a9a89f93877c6f6253493f33271b0f030000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000006131f2c3845515c6773808d9aa4afa99c8f8275695e5241382d2217040000000000000000000a16202d3946525e6875828e9ba8afa49a8d8073675c5145382c1f150a0000000000000008131e28323a4146535353535353534847423c332b23190f04000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e2215080000000810181f25292b2c2d2d2d2d2d2d2d2d201d19130c0400000000000000000000000000000000000000020a12191f2326272d2d2d2d2d2d2d2d292825211b140c030000000000000000000000000000000000000000000003080d111314181b1d1e1f20201f1e1c1a171413100c0701000000000000000000000000000000000000000000040d161e24292c393939393939393933322f2a241c130a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040607131313131313130c0c0906010000000000000000000004080c0e0f131313131313130f0f0c0904000000000000000000000004080a0a131313131313130707050100000000000000000000000000000104060712131313131313130b0b0905010000000000000000000000000004080c0e0f13131313131313100606030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c161f2a36424d575f616c6c6c6c6c6b605d554b4035291d1104000b1825323e4b5865717e8b939393938d8073675a5a6773808d939393938b7e7165584b3e3225180b000000000000000000000000000000000000000916222f3c4955626f7c8893939393939386796c605346392d20130600000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8794a1a99d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e010000000000000000000006121f2c3844505c6673808d9aa4afaa9e94887c6f655b50443d332a2219140e09060400000100000406090e141a232b353d45515d67717e8a95a0acada2978b7e7265574d42362a1e0a0000000000000000000000000000030c18242f39434f59606d7a85919ea5ab9f948b7e71685e52505c666f7c87939fa9a69f92857a6e61594f433a2f24190c030000000000000000000000000000000000060b0f121316191d2021242621272c2f35393a3f444855626f7b8895a093867a6d6d7074797d828a9297a0a7aaa1968e81756a5f5341382d22170b000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000000000713202d3a4653606d7985929eacada1978a7d7064564d422f261b110600000000000000000005111d2a36414c5663707d8a96a1adac9e9285796d6053463c31261b0f01000000000007131e29333d454c5052535353535353534948443d352b21160b000004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000006101a222a3035383939393939393939392c29241e160d040000000000000000000000000000000000000a141c242b2f333439393939393939393534312c261e150c0200000000000000000000000000000000000000060b0f13191d20212427292b2c2c2c2c2b292724201f1d18120f0a04000000000000000000000000000000000000010c1620282f35394646464646464646403f3b352e251c1207000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d1a26313b454d53555f606060605e53514b433a2f24180d01000b1825323e4b5865717e8686868686868073675a5a6773808686868686867e7165584b3e3225180b000000000000000000000000000000000000000916222f3c4955626f7c8686868686868686796c605346392d20130600000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a87949c9c9c9084776a5d5144495663707c89969c9c9a8d8174675a4e4134271b0e010000000000000000000003101c28343f4a54616e7b87939fabb0a69c9083776c60584e453c342a251e1a1312100c070e070c1013131a1f262a353d47505a606d7984919ea7b1a99f9285796d6053473b31261a0e00000000000000000000000000000a151e2935404b55606b74818e97a1ada3999083776c60564c4a54606b74818e97a1ada2978e81756c61554c4135291e150b00000000000000000000000000000000000000030506080d11131821272c33383a4145474a505356626f7b8895a093867976797d81858a8f949ea1a9a9a29891847a6e61584e432f261b1106000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000006121f2b37434e5864717e8a97a1adac9e9184796d6053463b3020140a00000000000000000000010d1925303a4653606c7884919eacada1978a7e7164584e43372b1d120700000000000c18242f3a454f575c5e6060606060606056544f473d32271b10040004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800020d18222c343b414446464646464646464639352f2820160c010000000000000000000000000000000006101c262e363b3f40464646464646464642413d3730271e14090000000000000000000000000000000000020a11171b1f252a2d2e3134363839393938383633302d2c29241d1b150e09030000000000000000000000000000000008131e28323a414553535353535353534d4b4740372e24190d0200000000000000000000000000000000000000000000000000000000000000000000000000000002080d10121313131313131313131313131313131313131313131313121211100e0b090706040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306131313131313131308070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f29333b4246485253535353514745403a31281d130700000b1724313d4a56626c71797979797979736e645858646e73797979797979716c62564a3d3124170b000000000000000000000000000000000000000815212e3b47535f6a767979797979797979766c5f5346392d20130600000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a878f8f8f8f8f84776a5d5144495663707c898f8f8f8f8d8174675a4e4134271b0e0100000000000000000000000c17232e3846535f6975828e99a3afab9f948b7f726a60574e463e36302a25201f1c181b1a1b181c1f20262b31363f474f59616c74808d96a1adada2978d8073675d5145392a1f14090000000000000000000000000006111c26303845515d67707d89939da9a89f92877c6f655b5044424f59616d7a85929ea6a99e938a7d70675d51453d30271d1207000000000000000000000000000000000000000000050d161d242932383d44484c5154545c6063666f7b8895a2998c7f8285898d91979c9fa6aca69f9792867c6f685e52463c311d140a00000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c30231609000000000000000000000000000815212e3a47535f6a7683909ca9afa49a8d8073665c5044382c1f1202000000000000000000000008131f2b3844505b6673808c9aa4afa99c9083766a5f5347392f24180d01000000030f1b2834404c5761686b6c6c6c6c6c6c6c6360594f44382c2013070004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e2215080008141f2a343e464d5152535353535353535345413a32281e1308000000000000000000000000000000020b18222e3840474c4d53535353535353534f4d49423930261b1004000000000000000000000000000000060b141b22272b3036393a3e414345454646454442403d3a38352f2b27201a140d050000000000000000000000000000010d19242f3a444c525f606060606060605957524940352a1e13070000000000000000000000000000000000000000000000000000000000000000000000000000060d14191c1f1f202020202020202020202020202020202020202020201f1e1e1c1a18161413100c070501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c101220202020202020201514120e0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d17212931363a3b4646464646453a39352f281f160c0100000915212e3a45505a62656c6c6c6c6c6c67645c52525c64676c6c6c6c6c6c65625a50453a2e2115090000000000000000000000000000000000000006131f2b37434e585f626c6c6c6c6c6c6c6c6c645a4f43372b1e120500000000000000000000000000000000000000000000000000000000000000000714212d3a4754606d7a8283838383838174675b4e414855626f7c8283838383827f7265584c3f3225190c00000000000000000000000006111c2a36424d57626e7b87929fa8b0a69f92877c6f695f585046413b36312d2c282327272723282c2d31373b42465159606b717e8a929da8b1a79f92857a6d61554b4035291d1004000000000000000000000000020b17232e38424e58606d7984919ea5aca1968d80736a5f53493f3d46525e68717e8b949faba59e91847a6d60594f43392e23180b0200000000000000000000000000000000000000050f171f282f353d43484f54555d6064666d6f73767c8895a29c918c8f92989a9ea1a9aca8a09d948f857d6f6a60564c41342a200b0200000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c3023160900000000000000000000000004101d2935404b55626f7c88949fabac9f93877b6e61544a3f34281c10030000000000000000000000030f1c28333f4a54616e7b87939facab9f94887c6f62554b4035291d100400000005111e2b3744505c68737879797979797979706b6054483b2f2216090004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f12050b1724313e4a5764717d8a97a4aea194887b6e6155483b2e221508000d1925303b4650585d5f606060606060605f524c443a2f24190d0100000000000000000000000000000a141d2a34404a52585a60606060606060605c59544b42372c21150900000000000000000000000000020a11171d262d33373a4146474b4e505152535352514f4d4a4745403937322a251f170f080000000000000000000000000004111d2935414c565d6c6c6c6c6c6c6c6c66635b52473b2f23160a000000000000000000000000000000000000000000000000000000000000000000000000000810181f25292b2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2b2a29272523201f1c1813110d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11171c1f2d2d2d2d2d2d2d2d21211e1a140d05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f171f262a2d2e3939393939382d2c29241d160d0400000005111d29343f485056586060606060605a58524a4a52585a606060606060585650483f34291d110500000000000000000000000000000000000000030f1b26323c464e535560606060606060605f5a52493e33271b0f0200000000000000000000000000000000000000000000000000000000000000000713202c3945525d686d767676767676746f64584c4047535f6a6f767676767676726d62564a3e3125180b000000000000000000000000000e1a26313b47535f6974808d96a0abaea39991857b6e6a615a524c46423c3a38342e3434342e34383a3c42474d535b626b707d86929fa4aeaaa0958b7f72685e5243392f24180d010000000000000000000000000a141d28343f4a54606a73808d96a0aca59e9184796d60584e413835414c56606c77829099a3ada1968d80746b60554b4034281d140a000000000000000000000000000000000000050e172129313940454f54596063676d7175797c808387929faca39c999c9fa2aaabaca49f9c96918a827b6f6b60584e443b3022180e0000000000000000000000000003101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000613202c3945515d6774808d9aa6b0a99c8f8276695f5342382e23170c000000000000000000000000000b17222d3846535e6976828f9ca9b0a69a8d8074675d5145392c20150a00000005121f2b3845525e6b7885868686868686867d706356493d3023160a0004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e5245382b1f07000b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800101c2935414d5862696c6c6c6c6c6c6c6c6c5d564c4135291d11040000000000000000000000000006111c262f3c46525c64676c6c6c6c6c6c6c6c68655d54493d3125190c000000000000000000000000030b141b22272f383f44464c5254575a5c5e5f5f5f5f5e5c5a5753514b47433d363129211a120a0100000000000000000000000713202c3945525d687679797979797979736d63574b3f3225190c00000000000000000000000000000000000000000000000000000000000000000000000006101a222a30353839393939393939393939393939393939393939393939393838373634322f2d2c2923201d19130f0a030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151c23282c39393939393939392e2d2a251f170f05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d141a1e21222c2d2d2d2d2b20201d18130c0400000000010c18222d363f454a4b5353535353534d4c474040474c4d5353535353534b4a453f362d22180c0100000000000000000000000000000000000000000a15202a343c4347495353535353535353534f4940372c21160a00000000000000000000000000000000000000000000000000000000000000000004111d2935414c565d6069696969696967645c53483c434e585f6269696969696965625b51463a2e2216090000000000000000000000000009141f2b37424d57606d79849199a4afaba19791847c706c615e56534d494644404141414141404546494d53575f616d727d869298a2aeaca2989083786c60564c4131281d120700000000000000000000000006111b262f3844505c666f7c87929fa8aa9e938a7d70675d51463c2f303a44505b656f7c87929fa8a89f93887d6f675c51453c2f261c110600000000000000000000000000000000030c172029333b434b515960636b70757a7e8285898c909299a3afada7a5a9aaaba39f9c9a93908a847e766e6960594f463c32291e10060000000000000000000003070909101d293643505c6976838f9ca9a296897c6f6356493c302316090000000000000000000000000714202d3a4753606d7985929fabada2978a7e7164574d4230261c11060000000000000000000000000006111c2a36424d5764717e8a97a1adab9f9285796d6053473c32271b0f01000005121f2b3845525e6b7885919393939393897c706356493d3023160a0004111e2b3744515e6a7784919daaa89b8e8275685b4f4235281c0f020e1a2734414d5a6774808d9aa7ab9e9185786b5e52452f24180c000b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800121f2b3844515d6974797979797979797976685d5245392c201307000000000000000000000000000b17222d38424e58646e737979797979797979756f65594d4134281b0e0200000000000000000000030c151d262d333d41495053565e616467696b6c6c6c6b6b696663605d55544e46423b332c241c130a01000000000000000000000714212d3a4754606d7a86868686868686807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000000020d18222c343b4144464646464646464646464646464646464646464646464645454443413e3c3a38342f2d29241e1a150f0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151e262e343846464646464646463b3a36312921170d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214151f202020201e1413110d070100000000000006111b242d343a3d3e464646464646403f3b36363b3f404646464646463e3d3a342d241b1106000000000000000000000000000000000000000000040e18222a32373b3c464646464646464646433e372e251b1005000000000000000000000000000000000000000000000000000000000000000000010d1924303a444c52545c5c5c5c5c5c5b58534a41363c464e53555c5c5c5c5c5c585651493f34291e120600000000000000000000000000030e1a26313c45515d676f7d87939fa4aea9a19691867e756e68615e575653514a4e4e4d4e4e4b515356575f62696e767f879298a2aaafa49a92867c6f665b50443a301f160c010000000000000000000000000b17222d38414d57606d78839099a3aea2988e81756b61554b40342a27333f49535f6a73808d96a1ada49a9184796d60584e42382d22170b030000000000000000000000000000000b151e29333b454d555d606b6f767d81868a8e9298999d9fa3abb5aca6a8a09e9a9992908c87837e78716c615e574f473d342b20170d000000000000000000040a0f131516191c28333f4a546a7683909da9a296897c6f6356493c30231609000000000000000000000006131f2b37434e5865717e8b97a2adab9f9285796d6053473b3120150a0000000000000000000000000000000e1a25313b4653606d7985929eabaea2988b7e7165584e43372b1e1308000005121f2b3845525e6b7885919e9f9f9f96897c706356493d3023160a0004111e2b3744515e6a7784919daaa89b8f8275685c4f4235291c08000e1a2734414d5a6774808d9aa7ab9e9285786b554b4035291d10040b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800131f2c3946525f6c7986868686868686867a6d6054473a2d211407000000000000000000000000030f1c28333f4a545f6a738086868686868686868275685c4f4235291c0f02000000000000000000020c151e272f383f444e535b6063686d7174767878797978777573706d67626058534d453e362e251c130a000000000000000000000714212d3a4754606d7a8793939393938c807366594d4033261a0d000000000000000000000000000000000000000000000000000000000000000000000008141f2a343e464d5152535353535353535353535353535353535353535353535251514f4d4b494745403a3935302b26201b150c070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c2630383f4453535353535353534846423b33291f14090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507081313131313120706040100000000000000000009121b22292e313239393939393934332f2b2b2f333439393939393932312e29221b1209000000000000000000000000000000000000000000000006101820262b2e2f39393939393939393937332c251c1309000000000000000000000000000000000000000000000000000000000000000000000008131e28323a4145475050505050504e4c4841382f343c4347485050505050504c4a463f372d23180d01000000000000000000000000000009151f2935404b55606b727f8b929da4ada9a198928a817a746e696562605c545b5a5a5a5b545c606266696e747b828b9299a2aaaea39f93887e706a5f544a3f32291e0d04000000000000000000000000040f1b27333f49535f69727f8c95a0aba79f92857b6e61594f43392f22222d38414e58606d7984919ea6aca0958c80736a5f544a3f33281f1409000000000000000000000000000007121c27303b454d575e676d747c83898e92989b9fa2aaa9a8aab0aca29a9796918e8a86837f7b76716d66615a524d453d352b22190e050000000000000000070f161b1f222325252b3844505b667784909daaa296897c6f6356493c3023160900000000000000000000000815222e3b4754606a7783909da9b1a79a8d8074675c5145382c1f130300000000000000000000000000000009141f2c3845515c6774808d9aa7b1aa9d9083776a6054473a2f24190d010005121f2b3845525e6b7885919eabaca396897c706356493d3023160a0004111e2b3744515e6a7784919daaa99c8f8376695c50433025190e020e1a2734414d5a6774808d9aa7ac9f928679675d5145392c1f13060b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800131f2c3946525f6c7985929393939393877a6d6054473a2d2114070000000000000000000000030d1a232b3844505b666f7c8792939393939392857b6e6154473b2e211408000000000000000000000a141e2730394149505860656c70767a7e818384858686858482807d79746f6a615e57504840372e251c12090000000000000000000714212d3a4754606d7a87939f9f9f998c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000000000d1925303b4650585d5f6060606060606060606060606060606060606060605f5f5e5d5c5a585653514b4746413a37312b262018120b0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17232e38424a505f606060606060605f534d453b31251a0e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000911181d2124252d2d2d2d2d2d2726231f1f2326272d2d2d2d2d2d2524211d18110900000000000000000000000000000000000000000000000000060e151b1f21222d2d2d2d2d2d2d2d2d2b27211b130a010000000000000000000000000000000000000000000000000000000000000000000000020c1620283035393a43434343434341403c362f262a32373b3c4343434343433f3e3a342d251b1107000000000000000000000000000000030d18242f3a434f59626d74808d929ca3adaaa29f938e86807b76726f6d6669686767676869666d6f72777b81868f949fa3ababa39f918c7f726c61584e42382d20170d000000000000000000000000040e1a242b3744505b656e7b86929fa7ab9f958b7f72695e52473e31271d1b262f3c45515d67707d8a949eaaa89f92877c6f665b50443b31251a0e04000000000000000000000000000c18232e39424d575e696e79818990959b9fa3aaaaa8a19e9c9ea6a69a908a8784817d7a76726e6964605c545046423b332b23191007000000000000000007101921272c2f30323230394653606c7985929faca295887c6f6255493c2f2216090000000000000000000004111d2935414c56626f7c88959fabab9f95887c6f62554b4034291c100400000000000000000000000000000004101c2834404b55626f7c88959fabab9f95887c6f62564c4135291d11040005121f2b3845525e6b7885919eabaca396897c706356493d3023160a0004111e2b3744515e6a7784919daaaa9d9083776a564c41362a1e11050e1a2734414d5a6774808d9aa7afa399867a6d6053473a2d2014070b1724313e4a5764717d8a97a4aea194887b6e6155483b2e22150800131f2c3946525f6c7985929f9f9f9f93877a6d6054473a2d21140700000000000000000000010b151f2a36414c56606c78839099a39faa9e948b7e71685e5246392d20140700000000000000000006111c263039424a535b606a6f787d82868a8d8f9192929292918f8d8a86817c756e69615a524a40372e241b0f0600000000000000000714212d3a4754606d7a8793a0aca6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000000101c2935414d5862696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6b6a69676562605c5554524c47433c373228231d150c0700000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a545c6c6c6c6c6c6c6c6c6c5e574d42362a1e12050000000000000000000000000001070b0f111213131313131313080705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c111517182020202020201a1917131317191a202020202020181715110c06000000000000000000000000000000000000000000000000000000040a0f1315162020202020202020201e1b1610090100000000000000000000000000000000000000000000000000000000000000000000000000040e161e24292c2d3636363636363433302b251d20262b2e2f36363636363632312e29231b1309000000000000000000000000000000000007131d28313d47515b606c77808c919ea1a9aea59e98928d87837f7c79777674747474747677797c7f83888e92999fa6aea8a199928b7f736d635a50463c2f261c0e050000000000000000000000020c16202a36424d57606c77829098a3aea3999083786c60564d42352c1f15141d2935404b55616c75828f98a2aea3999083786c60574d42362a20160c02000000000000000000000004101c2834404a545e696e7b838e939d9fa7aca7a09d9996918f949ea4978a7e7b7774716d6865615e5753504a423e363029211911070000000000000000040f19232b32383b3c3f3f3f424b55626e7b8898a2aea894877b6e6154483b2e211508000000000000000000000613202c3945525d6874818e9aa79faa9d9083766a5f5343392f23180c00000000000000000000000000000000000c18232e3947535f6a7683909daa9fa79a8e8174685d5245392c2013060005121f2b3845525e6b7885919e9f9f9f96897c706356493d3023160a0004111e2b3744515e6a7784919daaab9e918578685e5246392d2014070e1b2834414e5b6774818e9aa7b5ab94887b6e6155483b2e2215090b1825313e4b5864717e8b97a4aea194887b6e6155483b2e22150800131f2c3946525f6c7985929facaca093877a6d6054473a2d2114070000000000000000000007121d27313946525e68727f8b959fabaea2988f82766c62564d41362a1e11050000000000000000030d17232e38424a545c656c737c838a8f93999a9c9e9f9f9f9e9e9c9998928e89827b716c635c524940362d22180b02000000000000000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000000121f2b3844515d697479797979797979797979797979797979797979797979797878777674716f6d6764615d56534e47433c342e271e191008000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2c3844505c66767979797979797976695e53463a2d211407000000000000000000000000050c12171b1d1e202020202020201514120e0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105090b0b1313131313130d0d0b07070b0d0d1313131313130b0b09050100000000000000000000000000000000000000000000000000000000000003060809131313131313131313120f0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000040c13191d2021292929292929282724201a13151b1f21222929292929292525221e181109010000000000000000000000000000000000010c161f2b353f44505b656c747f8a92979ea6acaaa29f9a93908c898684828181808181828486898c90959a9fa3ababa49f9691877e736d635b51473e342a1d140a00000000000000000000000008131e28323a46525e69727e8b949faaa89f92877c6f665b50443b30231a0d0b18242f3943505a616e7b86929fa8ab9f958b7f72695e53463e32281e1308000000000000000000000006121f2c3844515c666e7b8490959da5aba49f9b95908c8884828f9ca09386796e696764605d5654534d46443f38302a251f170f070000000000000000000a16212b353d4348494c4c4c4d525d67727f8c99aaaca096867a6d6053473a2d201407000000000000000000000714212d3a4754606d7a869293939393988b7e7165584e4331271d1207000000000000000000000000000000000007121d2b37434e5865717e8b989393939392867a6d6054473a2d2114070005121f2b3845525e6b7885919393939393897c706356493d3023160a0004111e2b3744515e6a7784919daaada197877a6e6154473b2e23180b0f1b2835424e5b6875818e9ba8b0a3978a7d7064574a3d31261a0d0c1825323f4b5865727e8b98a5aea194887b6e6155483b2e22150800131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000020b18242f39434f59616e7a85929fa7b0a69f92867b6e615a50443b3025190e0200000000000000010b151f28343f4a545c666d77808890959c9fa4aba8a5a3a2a2a3a5a8aaa39f9b938f867e736e635b52483e342a1d140a000000000000000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c79868686868686868686868686868686868686868686868685848482807e7c7975716d68625f58534e454039302a221a1109000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d78868686868686867b6e6154483b2e2115080000000000000000000000060f161d23272a2b2d2d2d2d2d2d2d22211e1a140e060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d1113141d1d1d1d1d1d1b1a18140f080a0f1215151d1d1d1d1d1d191816120d070000000000000000000000000000000000000000040d192327333f49535b606d737d858f949da0a7acaca49f9c989892918f8e8d8d8d8e8f919298999d9fa7acaca69f99938d847d716c635b51493f352c22180b020000000000000000000000030d1924303a44505a616e7b85929fa6ada1968d80746a5f544a3f32291f110807121d28313e46535f69737f8c95a0aca79f92867b6e615a50443a3025190d0400000000000000000005111e2a36414c56606d78829096a0a7a8a099938e88837f7b787c8895a093867a6d60565754524c4846423b38342e261e1a140d05020000000000000000030f1b27323d474f5456585859575e616d7984919eabaa9e918477675d5145392c201306000000000000000000000c1925323f4c5865727f8686868686868686796d6054473c3121150b010000000000000000000000000000000000000f1b26313c4754606d7986868686868686867f7265584b3f3225180c0005121f2b3845525e6b7885868686868686867d706356493d3023160a0004111e2b3744515e6a7784919daab3a9968a7d7063554b4034281d14111c2935424f5c6875828f9ba8b3a6998c807366584e43372b1f16111926323f4c5965727f8c98a5b5ab94877a6e6154473b2e21140800131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000a141d2935404b55606b75818e97a2adaa9f948b7e72695e52483e32291f1408000000000000000007121d27313944505c666d78818c939a9fa7a9a29f9b9896959596989b9fa2aaa59e98928a80736e635a50463c2f261b11060000000000000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7985929393939393939393939393939393939393939399929291908f8d8b8985827e7a756f6a625f58514b433c342c231b12090000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d79869393939393877b6e6154483b2e21150800000000000000000000050f1820282f333738393939393939392e2d2b261f180f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020608080b0e1011121313121211100d0b0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000010406070a0e10111213131212100e0b080806020000000000000000000000000000000000000000000000000000000000000000000000010407071010101010100e0d0b08030000030608091010101010100c0b09060100000000000000000000000000000000000000000000071017222d384149505b636b707b828990959c9fa4acaca9aaa39f9d9c9b9a9a9a9b9c9d9fa3aaaaababa39f9b948f878079706b625a514940372e231a10060000000000000000000000010b151f2935414c56616c75828f98a2aea69e9184796d60584e42382d20170d00010c161f2a36424d57606d7984919da5aea2988f82756c61564c4135291f160c0100000000000000000713202d3946525e6873808d949fa8a7a0969187817c77726e6f7b8895a093867a6d60534a4745413b3a36312b2823201f1b1714110e090200000000000007131f2c38434f59606365656667696e75808d96a1aca89b8e817568554b4035291d1104000000000000000000000b1824313e4a56626d7279797979797979796d675d5145392c201303000000000000000000000000000000000000000a15202c3945515d676d7979797979797979726d62564a3d3124180b0005111e2b3744505c68737879797979797979706b6054483b2f2216090004111e2b3744515e6a7784919daab4a79a8d8074675c51453a2f26201d1e2b37424d576a7783909daab6a99d9083766a5f53473c3128201e1d27333f49536774808d9aa7aea399877a6d6054473a2d21140700131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000006111b262f3845515d67707d89939ea9aea2988f82776c60574d42362d20170d0200000000000000000c18232f39434f59606d78818e939fa4aaa29f97928e8b898888898b8e92989fa3aaa29f928c80736c61584e41382d22170b0000000000000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0604020000000000000000000000000000020506060503000000000000000000000000131f2c3946525f6c7985929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9e9e9d9c9a9898928f8b86817c756f6a605c554e463e352d241b120900000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7986939f9f9f94877b6e6154483b2e211508000000000000000000010c16202a323a3f4345464646464646463b3a37312a21180e0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205090e121415181b1d1e1f20201f1f1e1c1a181514120e090502000000000000000000000000000000000000000000000000000000000000000000000001080d111314171a1c1e1f20201f1e1d1b181514120e09040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111b262f383f44515961696e757d83898f939a9c9fa2aaa7a8aaa9a7a7a7a7a7a9a9a8a6a9a29e9b99928e88827c746d676059504840372e251c110800000000000000000000000007121d27313945525d68717e8a939eaaaa9e948a7d70675d51463c2f261c0e050000040d1a26313b45515c66707d89939ea9aa9e948a7e71685e52463d31281d120700000000000000000714212e3a4754616d7a86929fa6aaa09590847c756f6a66626f7b8895a093867a6d6053473a3935302d2e3633312e2d2b2722201e19140d0500000000000915222f3b4854606b6f72727273767b818d929da8aca1968a7d7064574a3d2f24180d01000000000000000000000915222e3a46515b62656c6c6c6c6c6c6c6c605d554b4135291d11040000000000000000000000000000000000000004111d2935414b555d606c6c6c6c6c6c6c6c65625b51463a2e22150900030f1b2834404c5761686b6c6c6c6c6c6c6c6360594f44382c2013070004111e2b3744515e6a7784919daab7ab9f9285796d60564c42382f2c292a2d3a47535f697885929fabb8ab9f95887b6e62584e4339312d2a2a2d3744505b6576828f9ca9ac9f928679685d5245392c20130600131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000000000b17222d38414e58606d7984919ea5afa79f92867b6e655b50453b30241b0e05000000000000000004101c2934404b55606b73808d939ea5a7a098928c85817e7c7c7c7d7f82868d9299a1a8a49c928b7e716a5f53493f33271c110600000000000714212d3a4754606d7a8793a0ada6998c807366594d4033261a1312110f0b0706040100000000000306070b0f11131312100d0a09070400000000000000131f2c3946525f6c7985929facacacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a6a7aaa9a7aaa29f9b99928e87827c736d675f584f473f362d241b1007000000000000000000000000000000000000000606060606060606060606060606060606060713202d3a4653606d798693a0aca194877b6e6154483b2e21150800000000000000000007121d28323c444b5051535353535353534846423c332a1f140900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e11151a1e21222528292b2c2c2c2c2b2b29272522211e1a14120e090200000000000000000000000000000000000000000000000000000000000000050b1013191d20212427292b2c2c2c2c2b2a282522211e1a15110d070100000000000000000000000000000000000000000000000000000000000000000000000406070a0d0f11121313131212100e0c09060603000000000000000000000000000000000000000000000000000000000000000a141d262d3340474f575e616b70777d82878b8f9298989a9b9d9e9e9f9f9f9e9d9d9b999797928e8a86817c766f6a605d554f473e362e251c130a000000000000000000000000030c18242f39434f59606d7a85919ea6aea2988f82756c61554b40342a1d140a0000000009141f2834404b54606b75818e97a2ada69e92857a6d61594f43392f24180c0300000000000004111d2935414c566673808c98a2aea29890837a6f6a625f58626f7b8895a093867a6d6053473a2d30363a3b43403e3b3937332d2d2a251f170e0500000000091623303c4956636f7d7f7f7f8083868e939da4aea59e9184786d6053463a2d201307000000000000000000000006121e29343f49515658606060606060605f54514b433a2f24180d0100000000000000000000000000000000000000010d18242f3a434b51545f60606060606060585651493f34291d120600000c18242f3a454f575c5e6060606060606056544f473d32271b10040004111e2b3744515e6a7784919daab7ada2978b7e71685e544a423c3935363a3f4a54616e7b8898a2aeb5afa79a8d80746a5f554b433d393636393d4653606c7985919eabaa9e9184776b564c4135291d110400131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000000030f1b27333f49535f6a73808d96a0acaa9f958c7f72695f53493f33291f120900000000000000000006131f2c3845515c67707d88939fa5a7a09590857f797572706f6f7072757a80869196a1a9a49f92867c6e655b5044382e23170c00000000000714212d3a4754606d7a8793a0ada6998c807366594d4033261f201f1e1b181413110d080100060b101213171c1e1f201e1d1a171613100b050000000000131f2c3946525f6c7985929facb8ada39c9898989898989898989898989898999a9b9d9fa3aaaaacaba39f9a938f8780796f6a615950483f362d22190f050000000000000000000000000000000306071313131313131313131313131313131313131313202d3a4653606d798693a0aca194877b6e6154483b2e2115080906010000000000000b17232f3a444e565c5e6060606060606055534d453c31261a0e0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d14191e20262b2e2f323436383939393938373634322e2d2b26201e1a140e0902000000000000000000000000000000000000000000000000000000040a0f161c1e24292c2d3134363839393939383634322e2d2b26201d18130c060000000000000000000000000000000000000000000000000000000000000001070c10131416191c1d1f1f20201f1e1d1b191613120f0b060000000000000000000000000000000000000000000000000000000000020b141b2227353e454d525960636b70757b7e8285888b8d8f9091929292929191908e8c8a8885817e7a746f6a626058514b433d352d241c130a010000000000000000000000000b151e2935404b55606b74818e97a1ada79f92867b6e615a50433a2f22190b0200000000030c18232e39424f59616e7a85929fa7ada1978e81746b60554b4035291e150a0000000000000713202c3945525d687783909daaab9f92857b6e6860585355626f7b8895a093867a6d6053473a333b4246474f4d4a4846443f3b3a36302920170d020000000e1a2734414d5a6774808b8b8c8d8f92999ea5aca59e938a7e71665c5044382b1f12060000000000000000000000010d18232d373f464a4c53535353535353524745413a31281d130700000000000000000000000000000000000000000007131d28313a41454752535353535353534b4a463f372d23180d01000007131e29333d454c5052535353535353534948443d352b21160b000004111e2b3744515e6a7784919daab1a7a09d92857a6d665b544e474541424648505b66727f8c98aab4aba49f9d92877c6f675d554f4746414146474e58626f7c8997a1ada99c8f8276695c4f432f24190d0100131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000030c19232b3744505b656e7c87929fa8aea3989083786c60574d41382d21170d00000000000000000004111d2935414c55606d7984919aa4a9a09590837b726d67656362626365686d737c849197a1aba2989083786c60544a3f34281c1003000000000714212d3a4754606d7a8793a0ada6998c807366594d40332b2c2c2c2b282521201d19130d0a11171c1f2024282b2c2c2b2a272322201c160f0800000000131f2c3946525f6c7985929facb8a79c918c8b8b8b8b8b8b8b8b8b8b8b8b8b8c8d8e909298999da0a7aaaca49f99928d837c706b625a50483e342b21170d03000000000000000000000000060b1012132020202020202020202020202020202020202020202d3a4653606d798693a0aca194877b6e6154483b2e21191815120d0600000000000f1b27333f4b5660686b6c6c6c6c6c6c6c6c5f574d42372b1e12050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c13191f252a2d31373a3b3e41434445464645454443403e3b3a37312d2a251f1a140d0500000000000000000000000000000000000000000000000000060b151b21272c2f35393a3d414344454646454543413e3b3a37312c29241d17110a03000000000000000000000000000000000000000000000000000000040a0f12181c1f202326282a2b2c2c2c2c2b2a282523201f1c17110f0a03000000000000000000000000000000000000000000000000000000020a1117232c333b42464f54596063696e7276797c7e808283848585868585848382807d7b7975716d68625f58544e45403a312b231b120a0100000000000000000000000007121c27303945515d67707d89939da9aba0958c7f72695e53483e31281d100700060000000007121d27303d46525e68727f8b959faba99e93897d70675d51453d30261c110600000000000714212d3a4754606d7a86939facaa998c8073695e564e4855626f7b8895a093867a6d6053473a3b454d52545c5a57555350494746423b32291f14090000000e1a2734414d5a6774808d98999a9c9fa3aba8a19e938e81756c61544a3f34281c100300000000000000000000000006111b252d343a3e3f46464646464646463a39352f281f160c01000000000000000000000000000000000000000000010c161f282f35393a46464646464646463f3d3a342d251b1106000000010c17212b333a404445464646464646463d3b38322b23190f04000004111e2b3744515e6a7784919daaaca09590958e81786c665f5854524c4d53555a606c7883909daaafa4999390959083796d67605954524c4c525458606a74818e9aa9b3aa998d8073665a4d4033271a080000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000b151e2a36414c56606c77829099a3aea79f92867b6e665b50453b2f261b0f050000000000000000000613202c3945515d67737f8c96a1aca29790837a6e69605d5556555556565d606a6f7b859199a3aa9f948b7e71665c5044382c1f1509000000000714212d3a4754606d7a8793a0ada6998c807366594d4036383939393735322d2c29241e19141c23282b2d3135383939383633302f2c2721191108000000131f2c3946525f6c7985929facb2a5988c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80818386888c91959c9ea6acaba39f9591867d716c625a50463d33291f140900000000000000000000020a11171c1f202c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2d3a4653606d798693a0aca194877b6e6154483b2e2c2524221e18110901000000111d2a3743505c6872787979797979797976695f53463a2d21140700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080e161e25293036393c4247484b4e50515253535252514f4d4b4846423c3a36302a251f170f0800000000000000000000000000000000000000000000020a111720262b33383a4145474a4d4f515253535251504e4b4847423c39352f28231c150c05000000000000000000000000000000000000000000000000040a0f161b1d23292c2d303335373839393939383635322f2d2b28221c1b150e090300000000000000000000000000000000000000000000000000000006111a202930363d44484f54565e6165666d6f7174757778787979787877767573716f6d6664605d56534e47433d352f281f19110900000000000000000000000000000c18232e39424e58606d7984919ea5afa4999083786d60574d42362c1f160c1313130c060603000b151e2a36414c56606c78839099a4afa59e9184796d60584e42382e23170c00000000000916232f3c4956626f7c8999a4aea298887b6e62574d444855626f7b8895a093867a6d6053473a424d575e6169666461605b5354524d443b3025190e0200000e1a2734414d5a6774808d9a9f9fa29f9e9d9a96918b81786d605a5042382e23170b000000000000000000000000000009131b23292e313239393939393939392d2c29241d160d040000000000000000000000000000000000000000000000040d161d24292c2d393939393939393932312e29231b13090000000000050f1821292f34373839393939393939302f2c272119110700000004111e2b3744515e6a7784919daaaa9d908490938e81786e6a64605d56575f61646c727f8b95a0acac9f93878390958f82796f6b64615e56565e61646a6f7c87929facaea298897d7063564a3d3023170a0000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000007121d27303946525e68717e8b949fababa0958c7f726a5f544a3f332a1d140a000000000000000000000714212d3a4754606d7a85929fa8a89f92857b6e685e57514b4949494a4c52585f696f7d87929faaa69e9184786d6053463c31261a0e020000000714212d3a4754606d7a8793a0ada6998c807366594d40434445464544423e3a39352f2a251e262e34383a3e424446464543403d3c38332b23190f050000131f2c3946525f6c7985929facada093877a7272727272727272727272727273737477797c8084898f949da0a7afa7a09892877e716c61584e453b30251a0d040000000000000000020c141c23282b2d393939393939393939393939393939393939393939393a4653606d798693a0aca194877b6e6154483b393932312e29231b1309000000121e2b3845515e6b7884868686868686867b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a121a202830353b4146474e5355585b5c5e5f5f5f5f5e5e5c5a5855534d4846423b363029211a120a0200000000000000000000000000000000000000030b141b222732373d44484c5254575a5c5e5f5f5f5f5e5d5b5855534d4745413a342e261e170f0700000000000000000000000000000000000000000000060b151b21272c2f34383a3d40424445464646454543413f3c3938332d2b26201a150b06000000000000000000000000000000000000000000000000000000080e171f252a33384851595e6060605c60626567686a6b6b6c6c6c6b6a6a68666462605c6060605f5c574f453a29241d160d07000000000000000000000000000004101c2834404a54606a73808d96a09fa99f93877c6f665c50453b31241a20202020201913120f0b060c1925303b44505b666f7c87939fa99fa1968d80736a60544a3f34281c1003000000000a1724303d4a5763707d8a96abab9f9285796c6053463c4855626f7b8895a093867a6d6053473a46525e696e7673716e6c6567615e564d42362a1e110500000e1a2734414d5a6774808d939393989291908d8a847e746d665c51483e30261c11060000000000000000000000000000010911181e2224252d2d2d2d2d2d2d2c21201d18130c0400000000000000000000000000000000000000000000000000040c13181d20212c2d2d2d2d2d2d2d2524221d18110901000000000000060f171e24282b2b2d2d2d2d2d2d2d2322201b160f070000000005111e2b3844515e6b7784919eaaa4978b7e8491938e827c75716d686b6b696e71767e87929fa7b1a79c8f827b8692948f837c75716e686b6b686d70757c859299a3afaa9f9285796d6053463a2d2013070000131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000c18232e39424f59616d7a85929ea6aea3999083786d60574e42382d21180b0200000000000000000007131f2c38434f5965727f8c98a2aca0968b7f72695f564d45403d3c3c3d41454e57606b74808d98a2aca1968a7e7164574d42372b1e12060000000714212d3a4754606d7a8793a0ada6998c807366594d4c5051525352514e4b4745413a36302a30383f44464a4f51525351504d4a48443d352b21160b0000131f2c3946525f6c7985929facada093877a6d656565656565656565656565666768666d6f73777c828990959fa4acaaa299928b7e716a60574d42362a1f160c01000000000000000a141e262e34383a46464646464646464646464646464646464646464646464653606d798693a0aca194877b6e6154484646463f3e3a342d251b11060000121e2b3845515e6b7884919393939393887b6e6155483b2e22150800000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c242c323a41464d5254575f626567696b6c6c6c6c6b6a696765615f5754524d46423b332c241c140a020000000000000000000000000000000000030c151d262d333c43474f54565d606467696b6c6c6c6c6b696765615f5754514b443f3830292119100700000000000000000000000000000000000000020a111720262b323839404547494c4f50525253535251504e4c4946443f3837312b262017110a020000000000000000000000000000000000000000000000000000050d141a2136424e59636b6c6c6c6c6b64615a5c5d5e5f5f5f5f5e5e5d5b535b60656c6c6c6c6b6861574c403428130c0400000000000000000000000000000006121f2c3844515c666f7c879293939393978d80746a60544a3f33291f202c2d2d2d2c26201f1c17110a141e28333f4a54606a74808d979393939392877c6f665c5044382c1f1206000000000b1824313e4b5764717e8a97a4aa9e918477655b50443c4855626f7b8895a093867a6d6053473b4754616e7b82807d7b7976746e695e52463a2d20140700000e1a2734414d5a6774808686868686858483807d79716c605c544a40362c1e140a0000000000000000000000000000000000060d12151819202020202020201f1413110d070100000000000000000000000000000000000000000000000000000001070d1113141f20202020202020181815120d06000000000000000000050c13181b1e1f20202020202020161613100b04000000000005111e2b3844515e6b7784919eaaa3978a7d7d8992948f86817d7a797778797b7e838b9299a3afaba0958a7e737f8c94959087827e7a797878797a7d82889297a1abaea3988d8074665c5145382c1f13060000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000004101c2834404b54606b74818e97a1ada79f92877c6f665c50453c2f261c0f06000000000000000000000915222f3b4854606b7784919eaaab9e9184786d60574d443b352f2f2f30353c454f59616d7a86929faca89d908376695f53473a2d2114080000000714212d3a4754606d7a8793a0ada6998c8073665956595c5e5f5f5f5e5b5854524c46413a333c424a5053575b5e5f5f5e5d5a56544f473d33271c100400131f2c3946525f6c7985929facada093877a6d605858585858585858585858595a545c6062666b6f767c838d939aa3ababa39f92867c6f695e52463e31281d130700000000000006111c2630383f444653535353535353535353535353535353535353535353535353606d798693a0aca194877b6e6154535353534c4a463f372d23180d0100121e2b3845515e6b7884919e9f9f9f94887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b141d262e363e444c52565e61666a6e717476777879797878777673716e6966615e57524d453e362e261c140a00000000000000000000000000000000030c151e272f383f444e54596063686d7074767778797978787674716e6965605d55504a423b332b221910070000000000000000000000000000000000040b141c222832373d43484b515356595b5d5e5f5f5f5f5e5d5b585653504a47433c373127221b140b03000000000000000000000000000000000000000000000000000002091f2c3945525e6b757979797978706c615f57514b525352524b51575f656c71787979797873685c5044372b1e11000000000000000000000000000000000713202d3a4653606d798386868686868686857a6d60584e42382e282b383939393939332d2b28221c140b17222d38424e58606d7a858686868686868683796d6053463a2d201307000000000b1824313e4b5764717e8a97a4ab9e918578665c50443c4855626f7b8895a093867a6d605347424e5865717e8b8d8a888583807b6e6154473b2e21140800000d1a26333f4c58646e74797979797979787774706d66625a514a42392e241a0c020000000000000000000000000000000000000106090b0c131313131313131307060401000000000000000000000000000000000000000000000000000000000000000104060713131313131313130c0b090601000000000000000000000001070c0f1112131313131313130a0907040000000000000005121e2b3845515e6b7884919eaba3968a7d73808d9499928e8a8785848585888b90959fa3abaea3999183786d78828f959a938f8b8786848485878a8e939aa1a9afa59f92867b6e61544b4034281c10040000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000040e1a242c3845515c66707d89939ea9aba0958c80736a5f544a3f332a1d140a0000000000000000000000091623303c4956636f7c8996a0aca3998b7f72665c50453b32292422222429333d46525d6874808d9aa8ab9f95887b6e6155483b3025190d0100000714212d3a4754606d7a8793a0ada6998c807366606366696b6c6c6c6a6865605d56524c443e454d545c6064686b6c6c6b69666360594f44382c20130700131f2c3946525f6c7985929facada093877a6d60544c4c4c4c4c4c4c4c4c4c4c4d4a5053555960636a6f7980889299a3abaea39891857b6e615a50433a2f24180d0000000000000b17232e38424a50535f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f606d798693a0aca194877b6e615f5f5f5f5f585651493f34291e120600121e2b3845515e6b7884919eabaca194887b6e6155483b2e22150800000000000000000000000000000000000000000000000000000000000000000000000000000000000009131d262f38404850565e61686e73777b7e81838485868685858482807e7b77736e69615e57504840382e261c13090000000000000000000000000000000a151e273039414950585f626b70757a7d808284858686858483817e7b77726d67605c544d453d342b22190f05000000000000000000000000000000040d161d262d333c43474f54555c606366686a6b6c6c6c6c6b69686562605b54534e47423c332d261d150d03000000000000000000000000000000000000000000000000000613202d394653606c7987868686847d756e69605c554f46454f545c60696e777e8586868685786b5f5245382c1f120500000000000000000000000000000006121f2c3844515c666d7779797979797979786d685d52463d302e34384546464646463f3938332d261d18111c262f3c45525d686d7879797979797979776d665c5044382c1f1206000000000a1723303d4a5663707d8996a9ac9f9286796d6053463e4855626f7b8895a093867a6d6053474b54606a76838f9997989290857a6d6053473a2d20140700000b1723303c47525c64676c6c6c6c6c6c6b6a6764605c545044403930271c1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005121f2b3845525e6b7885919eaba396897c7078828f949f9b97989291919298979d9fa7aeaaa29f92877d70666d7a8390959f9c97999291919298979b9fa4acaca49f938c7f72695e5342392e23180c000000131f2c3946525f6c7985929facada093877a6d6054473a2d21140b0b0b0b0c16202b37424d57606d7984919da5afa3999083796d60584e42382e21180b020000000000000000000005121e2a36424d576774808d9aa8ac9f92867a6d61544a3f33292018161619212935414c56626f7c8895a0aca7998c807366564c4135291d110500000714212d3a4754606d7a8793a0ada6998c8073656c6f7376777879787775716d68615e5650484d575f666d7175777979787673706b6054483c2f22160900131f2c3946525f6c7985929facada093877a6d6054473f3f3f3f3f3f3f3f3f40403f4446494f545860676d737e879299a3aeaaa1978f82766c61554b4135291d12070000000003101c28343f4a545c6a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d798693a0aca194877b6e6c6c6c6c6c6c65625b51463a2e22150900121e2b3845515e6b7884919eabaea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000000000007101b252f38404a525a61686d747b8084888b8e8f919292929291918f8d8b8884807b746e69615a524a40382e251b0f060000000000000000000000000006111c263039424a535b606a6f767d82868a8d8f919292929291908e8b88847f7a726d665e574e463d342b21170b0200000000000000000000000000030c161f282f383f444e54596063676d707375777879797978787674726f6c66625f58534d443f382f271f150d03000000000000000000000000000000000000000000000000000b1825313e4b5864717e889396918a827b736d67615953525960666d737b828b929792877e7064574a3d3124170a0000000000000000000000000000000004101c2834404a545c606a6c6c6c6c6c6c6c6b605d564c413430383f445253535353534c46443f382f2a2119141d2935414c565d606b6c6c6c6c6c6c6c6a605c544a3f34281c1003000000000815222e3b4855616e7b8897a1ada399897d70635a50474855626f7b8895a093867a6d60534c535c666f7c89949faaa29b8e8175675d5145382c1f1306000007131f2b36404a52585a60606060605f5e5d5a5753514b423f342e271e150b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507080a0d0e10111212131313131211100f0d0b090706040000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101d2935404b556c7885929f9f9f95887c6f6d79828d939a9fa29f9e9e9fa3aaa9a9aba39f98928a7f726b60686d7a838d939a9fa39f9e9e9fa2aaa8a9aba49f9a938c81776c60574d4230271d1207000000131f2c3946525f6c7985929facada093877a6d6054473a2d211818181818181e28323a47535f69737f8c96a0aca89f92877c6f665c51463c30261c0f0600000000000000000000000714212d3a46535e697784919eaaa99c8f8276685e5242382e21170d07080f1924303a47535f6a7784919daaaa9d908377685e5246392d20130700000714212d3a4754606d7a8793a0ada6998c807370787c7f838485868584817e7a746d68615a51575f696e787e828485868483807d7063564a3d3023170a00131f2c3946525f6c7985929facada093877a6d6054473a3232323232323232332e34383a3d43484e555c606c717e87929fa5afa99f948a7e71675d5145392e23180c0000000006121f2b3844505c6674797979797979797979797979797979797979797979797979797979788693a0aca194877b79797979797979726d62564a3e3124180b00121e2b3845515e6b7884919eabaea194887b6e6155483b2e22150800000000000000000000000000000000000000000000000000000000000000000000000000000000030c19222d37404a525c636c717a81868c9196989a9c9e9f9f9f9f9e9d9c9a9895918d86817b716c645c524a40372d21180e030000000000000000000000040e17232e38424a545c656c727c82898f92999a9c9e9f9f9f9f9e9c9a9895908b857f786e6960584e463d33291d140a000000000000000000000000000b151e283139424a50585f626b6f75797d7f828385858686858483817f7c79746f6a625f575049413931271f150b010000000000000000000000000000000000000000000000000a1724303d4956626c717f8b919e948f868079706b615f5d606b6f797f868f949f93887e716c6155493c3023160a00000000000000000000000000000000000c18232e39424a51535d606060606060605e54524c433a2f38424a505e5f6060605f5953504a423b332a251f19242f3a434c52545e606060606060605d53504a42382e23170c00000000000613202d394653606c7985929eabab9b8f82756c615a544e55626f7b8895a093867a6d6053565d656d7983909da6aca0958a7d7064554b4035291d10040000030e19242f3840474c4d53535353535251504d4a464540393028231c150c03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000406090e12141517191b1d1e1f1f2020201f1f1e1d1c1a18161312100c0705020000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3945515d6779869293939393887b6e676d7880878f93999b9d9e9f9f9f9e9c9a99928e867e726d62595e686d7980878e92999a9c9e9f9f9f9e9d9a99938e877f746c655b50453b311e150b00000000131f2c3946525f6c7985929facada093877a6d6054473a2d2424242424242424303a44505a616e7b86929fa8aca0968d80736a60544b40342a1e150a0000000000000000000000000815212e3b4854616e7b8796a0acab988c7f7265564c4130261c0f06000008131e2b37434e586774808d9aa7ac9f93867a6d6154473a2e21140700000714212d3a4754606d7a8793a0ada6998c80747d83898c8f91929292918e8b86807a706c635b5e696e7b838a8e91929291908d86796c5f5346392c201300131f2c3946525f6c7985929facada093877a6d6054473a2d252525252525252623282c2d32383d434b515a616c727f8b939ea9b0a69e91847a6d60544b4034281c10040000000713202d3a4653606d78868686868686868686868686868686868686868686868686868686868a95a1b9ac9f9286868686868686867f7265584c3f3225190c00121e2b3845515e6b7884919eabaea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000000000a151e2b343f49525c646e737e858d92999da0a8a9a29f9d9c9b9c9d9fa2aaa7a09d99928e857e736e645c52493f332a1f140900000000000000000000020c162028343f4a545c666d777f8790949b9fa3aba7a3a2a1a1a2a4a8a7a7a09d97928b837b6f6a60584e453b2f261b1106000000000000000000000007121d273039434b545b606a6f767c8185898c8e90919292929291908e8b8985817c756e69605b534b433931271d12070000000000000000000000000000000000000000000000000815212d3945505a626d727f8b919c98928c847d756e69686d747c838c92989c918b7f726c625a5044392d201408000000000000000000000000000000000007121c2730394044465153535353535353524745413a31343f4a545c6a6c6c6c6c6c66605b544d453f363029201e28313a41454752535353535353535146443f3830261c1106000000000005121f2b3744505b6574818e9ba6aa9e938a7e716c62605857626f7b8895a093867a6d605c60686d77818e95a0aca79d9184786c605346392f24180c0000000008121d262f363c3f414646464646464544413d3a38342e271e18120b03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c1013141a1e2121242628292a2b2c2c2d2c2c2c2b2a29272522201f1c1814120e0903000000000000000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d79868686868686867a6d61666d737c82878b8e909192929291908d8a86817b716c625b51565e676d737c81868a8d909192929291908e8a87817c736d605b53493f33291f0c0300000000131f2c3946525f6c7985929facada093877a6d6054473a31313131313131313135414c56616c76828f98a3aea49a9184796d60584e42392e22180c030000000000000000000000000b1825313e4b5864717e8b97a8aea399887c6f6255493c3022140a000000020f1b26323d4a5763707d8a96a8afa4998a7d7064574a3d3124170700000714212d3a4754606d7a8793a0ada6998c80808a9095999c9e9f9f9f9d9b98928d857e736d63616e7b8590959b9e9f9f9e9c9286796c5f5346392c201300131f2c3946525f6c7985929facada093877a6d6054473a2d2119191919191919171c1f20272c30394045505a626d74818e97a1adada1968c7f73665c5145382c1f14090000000713202d3a4653606d798692929292929292929292929292929292929292929292929292929298a3aebaaea399929292929292928b7f7265584c3f3225190c00121e2b3845515e6b7884919eabaea194887b6e6155483b2e22150800000000000000000000000000000000000000000000000000000000000000000000000000000006111c26303d46515b646e74808a92979fa3a9a19e999792908f8f8f909298989d9fa7a39f97928a80736e635b51453b31261a0e0400000000000000000008131e28323a44505c666d78818c92999fa6a9a19e9a9795949596979b9fa2a9a9a29f9590857c6f6a60574d41382d22170b01000000000000000000040d18232e39434b555d666c737c83898e9298999b9d9e9f9f9f9f9e9c9b9897918d88827b736c655d554b43392f24180e05000000000000000000000000000000000000000000000005111d29343e48505a626d727f8c929c9f96918a827b73717a818891959f9d928c7f736d625a50483e33281c10040000000000000000000000000000000000000b151e272e34383a4446464646464646453a39352f2b3844505c66757979797979726c665f575146423b3229251f282f35393a4546464646464646443a38342e261e150a000000000000030f1b27333f4953626f7c89949ea9a59f92877e756f6a6764626f7b8895a093867a6d65676d717a818e939da7a99f958a7e71665b5044382b1d120700000000010b141d242b303334393939393939383734312d2c28231d150c07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e12181d1f20252a2d2e31333536373839393939393838373534322f2d2c2823211e1a140f0b0600000000000000000000000000000000000000000000000000000000000000000000000613202c3945515d67767979797979797976685e5c606a6f757a7e8183858586858483817e7a746e69615a51494c555c606a6f757a7e8183848586858483817e7b756f6a635b504941382d21170d0000000000131f2c3946525f6c7985929facada093877a6d6054473e3e3e3e3e3e3e3e3e3e3e45525d68717e8a949faaa89f93887d6f675d51463d30271d1006000000000000000000000000010e1a2734414d5a6774808d9aa7ac9f9286796d6053463a2d201307000000000a14212e3b4754616e7a8796a1adab998d8073665a4d402f24180c00000714212d3a4754606d7a8793a0adab9f92858d929da0a7aaa39f9e9e9fa2a39f97928a7f736d6975828e97a0a7aaacaaa29f9286796c5f5346392c201300131f2c3946525f6c7985929facada093877a6d6054473a2d21140c0c0c0c0c060c1012131b1e272e343e47515b606d7985919ea7b1a99e9185796d6053463b31251a0e0200000713202d3a4653606d7986939f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa3aab4bfb4aba39f9f9f9f9f9f988b7f7265584c3f3225190c00121e2b3845515e6b7884919eabaea194887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000000000000000000000000000c17232e38424f59626d74808d929ea1a9a39f97918c8885838282838385888b90959ea1a8a29f928d80736d62574d42362a20160a0000000000000000010d1924303a44505a606d78818e939fa3a9a29f97918d8a888788898b8e92979fa2aaa79f9792867c6f695e53493f33271d12070000000000000000010c161f2834404b555d676d78808790949b9fa2a9a29e9c9b9a9a9b9d9fa3a9a19e9a948f877f776d675d554b40352920170d0200000000000000000000000000000000000000000000000c17222d363f48515b636d737f8c929ca09e948f867f7d848d939aa09d938d80736d635b51483e362c22170b00000000000000000000000000000000000000030c151c23282c2d3739393939393939382d2c29242d3a4653606d7987868686867f786e69625b524d443e3530282024292c2d3839393939393939372d2c28231c150c03000000000000000b17222d384854606a75828f97a2aaa399928b827c7773716e6f7b8895a093867a6f7175797e848e939da5aba2979083786c60544a3f33281c0b010000000000020b12191f2326272d2d2d2d2d2c2b2a2724201f1c18120b030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e151a1d24292c2d31363a3b3d4041434445454646464645444342403e3c3a38342e2d2a261f1b17110a0200000000000000000000000000000000000000000000000000000000000000000004101d2935404b555d6c6c6c6c6c6c6c6c6c5e5651586062686d71747678797978787674716d67615e5750483f434b51585f62686d71747678787978777674716e69625f5851443f382f261b0f050000000000131f2c3946525f6c7985929facada093877a6d60544b4b4b4b4b4b4b4b4b4b4b4b4f59606d7a85929ea6aca1968d80746b60554b40342b1e150b0000000000000000000000000004111d2935414c55697683909ca9aa9d908377665c5144382c1f1206000000000714202d3946525e687884919eaba99c8f827669554b4035291d1004000714212d3a4754606d7a8793a0adada29792979da49f9c97989291919298969a9f9f918c7f726e7b87939fa9b1a7a09d98929286796c5f5346392c201300131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000003060a0c151d2328353f45515d67717e8b95a0acada1978b7e7164574d42362a1e120500000713202d3a4653606d798693a0acacacaca49f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa0a1a6aeb8b1a9a3a19f9f9f9f9f988b7f7265584c3f3225190c00121e2b3845515e6b7884919eabaea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54606b727f8c929ca4aaa299928c84807b787675757677797b7f838a91969fa6a49c928b7f72695f53463d32271b0f030000000000000005111d2935414c56616c74808d939ea5a7a097928b85807d7b7b7b7c7e81858c9298a0a7a9a29891857b6e655b5044392f24180c000000000000000008131e28313a45515c676d79828d92999fa6a39f9a97928f8e8d8e8e9092989b9fa3a69e99928c82796d675d51453f32291e1408000000000000000000000000000000000000000000000006101b242d363f49515b636d73808d929da49e98928c8a91969fa49e938e81746e645b51493f362d241a10050000000000000000000000000000000000000000030b12181c1f202a2d2d2d2d2d2d2d2b21201d1f2b3844505c66717e879399928c827b726d615e565046413a3229241d20212b2d2d2d2d2d2d2d2a201f1c17110a03000000000000000006111b2c38434e58616e7b859298a2a9a39f948f8984807e7b7a7c8895a194877a7c7e82858b91969ea5aaa29992857b6e665b5042382d22170b0000000000000001080e13171a1a20202020201f1e1d1a171313100c070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d14191f262b2f35383a3e4246484a4c4e50515252535353525251504f4d4b494644403b3a36312b27221b140b070100000000000000000000000000000000000000000000000000000000000000010d18242f39434b515f606060606060605f524c454e54565e6165686a6b6c6c6c6b696764605d55534d453e363940454e53565d606467696b6c6c6c6b6a6764615e57534e4640332d261d140a000000000000131f2c3946525f6c7985929facada093877a6d605757575757575757575757575754606b74818e97a1ada59e9184796d60594f43392f22190c04000000000000000000000000000613202c3945515d677885929eaba89b8e827568544a4034281c10040000000005111e2a36414c566976838f9ca9ab9e918578675d5145382c1f1306000714212d3a4754606d7a8793a0adb3a9a29fa2a19e948f8b8786858485878a8d92979f93887e727e8b99a4afaba0959088858686796c5f5346392c201300131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000030b1218232935414b55606c7883909da9b3a99d908377695e53463a2d21140600000713202d3a4653606d798693a5afaca29a979393939393939393939393939393939393939393959ca6b1a99f97949393939393938b7f7265584c3f3225190c00121e2b3845515e6b7884919eabaea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000006121f2c3844505c666f7c87929fa4aba29892878079736f6a6a696869656c6e72777d848f949fa6a49f92867b6e61584e43382b1f1306000000000000000713202d3946525d68717e8a929da5a79f9590857f7974706f6e6e6f7175797f869195a0a7aaa1978f82776c60554b4035291d1004000000000000010d19242f3a43505a606d79828f949fa3a7a099928e898583818181828386898e92999fa7a39f948f82796d605b51443b3025190e02000000000000000000000000000000000000000000000009121b242d373f49525b636e74808d929da5a39f99979ea1a69e948e81786c605c524940372d241b11080000000000000000000000000000000000000000000000070c1012131e202020202020201f1413111c28343f4a54616c717e87939a9490867f766e69615a524c443e352f281f191f202020202020201e1312100c0600000000000000000000000f1b27323d46525e69707d8692979ea5a69e9c95918d8a888786929fac978d87898b8e92979ea1a8a8a09892877e70695f544a3f2f261c110600000000000000000003070b0d0e13131313131312110e0a070604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e171e252a3137394045474a4d535457595b5c5d5e5f5f605f5f5f5e5d5c5a585553514a4846423b37332d261d18120c040000000000000000000000000000000000000000000000000000000000000007121d283139404553535353535353535346413c43474c5254585b5d5e5f5f5f5e5d5a5754514c46423b332c2e343c43474c5254575a5d5e5f5f5f5e5d5b5754524d47433c3427221b140b02000000000000131f2c3946525f6c7985929facada093877a6d646464646464646464646464646464666f7c88939fa9a89d93897d70675d51473d3129241e160e060000000000000000000000000714212d3a4754606d7a8797a2ada6998c807366594d402e23180c0000000000010d192530414e5a6774818d9aa7ada197867a6d6053473a2d201407000714212d3a4754606d7a8793a0adbcb3ada9a1979289827e7b797878797a7d81858d929992857b818e9babafa49990837c79797b6e6255483b2f22150800131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000071118242f3a44505b65717e8b97a2adab9f95877b6e6154483b2e23170c00000713202d3a4653606d7986939ea8a69a908a86868686868686868686868686868686868686868a95a1ada3978d87868686868686867f7265584c3f3225190c00121e2b3845515e6b7884919eabaea194887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54606d78839099a3afa39992867d736d67625f585c5c535b6061656c707a828f949fa9a2988f82766a6054473b2e22150800000000000005121e2a36424d57616d7a85929ea4a99f9590837b726d66646261626364676d727b839095a0aaa99f948b7e71675d5145382c1f140900000000000004111d2935414c56616c74818e949ea6a69f959087817c79767474747577797d818790959ea5a69e948e81756d62564c41362a1e140800000000000000000000000000000000000000000000000009121b252d374049525c646e74808d939da59f9f9f9fa79f948f82786d665b504a40372e251b1209000000000000000000000000000000000000000000000000000004060711131313131313131207060b17232e3842505a616c717e88939a98928b827b716c615e564f45413a312b22190f13131313131311070603000000000000000000000000000a16212a36424d57606b707d858e939d9fa7a7a09d9a9795989298a3ae9f979495989b9fa2a9aaa29f9691867d706c61574d42382d1d140a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a1117202930363c42474b515357575e61646668696a6b6c6c6c6c6c6b6b6a68676562605c5455534d46443f382f29241d160d05000000000000000000000000000000000000000000000000000000000000010c161f282f3539464646464646464646393632373a4146474b4e505252535251504e4b4745413a36312921232831373a4145474b4e505152535251504e4b4746423b37312a2217110a0200000000000000131f2c3946525f6c7985929facada093877a71717171717171717171717171717171717883909aa4ada1968e81746b60554e48443d35302820180f0600000000000000000000000915222f3c4855626f7c8895a9b3a4988b7e7165584b3e32251807000000000000081926333f4c5966727f8c99a5b2a995887b6e6255483b2f221508000714212d3a4754606d7a8793a0adbab9ada19792857d76716e696b6b676d70747a808792978e81828f9ca9ac9f93877b6f6a6c6e695f53473a2e21140800131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000000000000000007131d27333f4953606d7985929fabb1a7988b7e7265544a3f34281c10030006121f2b3844505c6675818e96a1a4978a7e79797979797979797979797979797979797979788693a0aca194877b79797979797979726d62564a3e3125180b00121e2b3845515e6b7884919eabaea194887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000000000000000000000006121f2c3844505c66727f8b95a0aba89f92877d706b605d55534e4f4f495053555a61686d79829097a1a49f94897c6f6256493c2f2316090000000000000714212d3a46535e6974818d97a1ada19790837a6e69605c5455545556555c60696e7a839098a2aea69e9184796d6053473b31261a0e0200000000000613202c3945525d68717e8a939da6a89f948f837c746f6c6668676768666d70757c838f939ea7a69e938b7f72685e52463b3025190d0100000000000000000000000000000000000000000000000009131c252e37404a525c606c77818e93939393939393959082796d665c544a3f382e251c1309000000000000000000000000000000000000000000000000000000000000040606060606060605000006111c26303e48505a626c717f88939f9f948f857e756d686159514b433d342b21160a00060606060400000000000000000000000000000000040e1a25303b454f59606b707b818a90959a9ea1a8a6a4aaa39fa3aab4a8a3a1a2a4a8aba49f9c98928c847c706b615a50453b2f261c0b0200000000000000000000000306080909090909090909090909090909090909090909090909090909090909090909090909090909090909090806030000000000000000000000000000020b141c2228323b41464d53555d606468696e70737476777878797979797877767573716f6d6665615f57535049413d352f281f170f06000000000000000000000000000000000000000000000000000000000000040d161d24292c39393939393939392e2d2a272b3036393a3e4143454646454543413e3a39352f2a251f171820262b2f35393a3e4143454546454443413e3b3a36302b2620181006000000000000000000131f2c3946525f6c7985929facb1a4988b7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e808d95a0acab9e91847a6d67625f58544f45413a322a21181006000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000b1825313e4b5864717e8b97a4b0a3968a7d7063574a3d3024170a000714212d3a4754606d7a8793a0adbcb1a79e92857c706b64615e57555d6063686d747e8692938e86929faca99d908376695f60625f574d42372b1e120600131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000000000010b17222d3845515d6774818e9aabb5a89c8f8275665c5044382c1f12060003101c28343f4a54606d7a84919ea59f92867b6e666c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d798693a0aca194877b6e6c6c6c6c6c6c65625b51463a2e22160900121e2b3845515e6b7884919eabaea194887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7984919ea7ada1968d80736b6059514b474342423f44464850565d676d7a85929b9993908c8275685c4f4235291c0f020000000004101d2935404b55616e7b86929fa9a69e92857a6e685e57514b484848494b51575e686e7b86929fa9ada1968b7e7165574d42362a1e12050000000004111d2935414c55606d7a85929ea5aca0968f82796e6a62605b545a5b545c60636a6e78818f959faba59f92857a6e61564c41362a1e1105000000000000000000000000000000000000000000000000010a131c252e384044505b656c7881868686868686868683796d675d544a42382d261c130a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141e2c363e48505a626d727f8b919b9e97928a817a706b605d554e463d32271b0f030000000000000000000000000000000000000000000009141f29333d474f5960696e757d83888d9196979a9b9d9e9fa3aab4aaa29f9e9c9b9999938f8b857f796f6a615950483e33291d140a00000000000000000000040a0f121515161616161616161616161616161616161616161616161616161616161616161616161616161616161515120f0a030000000000000000000000020b141d262d333e444c52575f62676d7174787b7d7f81838485858686868585848382807e7c7976726e6964605b534f454039312921170f06000000000000000000000000000000000000000000000000000000000000040c12181d202d2d2d2d2d2d2d2d21201d1b1e252a2d2e32353738393939383634312d2c29241e1a140d0c151a1e24292c2d31343638393939383734312e2d2a251f1b150e0600000000000000000000131f2c3946525f6c7985929facb8a69b908b8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8d929da7b1a79a8e817b77746f6a636059524c443c332a22180f050000000000000000000b1825313e4b5864717e8b97a4afa295897c6f6256493c2f2316090000000000000a1723303d4a5663707d8996a3b0a4978b7e7164584b3e3125180b000714212d3a4754606d7a8793a0adb8ab9f958a7e716a605954524d4b5154565d616c707d8793989298a3aea79a8d817467575355534d453c31261a0e0200131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000006111b2935404b5564717d8a99a3afac9f9285796d6053463a2d20130700000b17232e3845525d68707d89939da2989083796d6059606060606060606060606060606d798693a0aca194877b6e616060606060585651493f34291e120600121e2b3845515e6b7884919eabaea194887b6e6155483b2e22150802020202020202020202020202020202020202020202020000000000000000000000000004101d2935404b5564717d8a96a1acaa9e9184796d60594f45403937312d3337393e444c555e68717e8b8e8a86837f7c6f6255483c2f221509000000000006131f2c3945515d6774818d99a3ab9f948a7e71685e564d45403c3b3b3c40454d565f69727f8b97a1ada99d908377695f53463a2d211407000000000613202c3945515d6773808d97a1ada69e91847a6d675f5853504a4e4e4b5153585f666d79839099a3ada2978d8174685e5246392d20140900000000000000000000000000000000000000000000000000010a131c2627333f49535b666c757979797979797979776d675d554b42392f261c140a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c1a242d363f48505a626d727f8b919ba29f938e857d746d6760584e43382c1f130700000000000000000000000000000000000000000000030d17212b353d474f575e616b70767c8084878a8d8f90919298a3aea2989291908e8c8986837e79726d6660584f473e362c21170b02000000000000000000060e151b1f21222323232323232323232323232323232323232323232323232323232323232323232323232323232322211f1a150e06000000000000000000000a141d262f383f4450565e61696e74797d8184878a8c8e8f909192929392929291908f8d8b8886837f7b76706c656059514b433b332921170d0400000000000000000000000000000000000000000000000000000000000001070d101320202020202020201413110f13191e202125282a2b2c2c2c2b2a272421201d19130e0903030a0f13191d202124272a2b2c2c2c2b2a282421201e1a140f0a030000000000000000000000131f2c3946525f6c7985929facb8aca29b9897979797979797979797979797979797979a9da4aeb5a99d938e8784817c76706b605d564e463c342a21170b0200000000000000000c1926323f4c5965727f8c98a5aea195887b6e6255483b2f2215080000000000000916232f3c4956626f7c8995a2afa5988b7f7265584c3f3225190c000714212d3a4754606d7a8793a0adb6aa9d9083776c61584f4846424145474c525a616b73808d969fa3aab4a5998c7f7266594c4847423c332a2015090000131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000000000000000000000c18242f3a4754606d7a86929facaea298887b6e6255483b2f221508000006111c2935414c56606b74818e96a1a0958d80746b60564c53535353535353535353606d798693a0aca194877b6e6154535353534c4a463f372d23180d0100121e2b3845515e6b7884919eabaea194887b6e6155483b2e22150f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0b0a08040000000000000000000613202c3945515d6775828f9ba8aea3988b7e71675d51473d352f2b2622272b2d323a434c56606d7883817e7a76736f6a5f53473b2e21150800000000000714202d3a4753606d7985929faba89c8f82766c61564c433b342e2e2f2f343b444d57606d7985919eababa095887b6e6155483b2e221508000000000714212d3a4754606d7a85929fa9aa9e94897d70685d554e46443f41414045464e545c676f7c87929faca99f92867a6e6154473c31261a0e0200000000000000000000000000000000000000000000000000010a1417222d38414a545b60686c6c6c6c6c6c6c6c6a605d554c433930271d140a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242d363f48515b626d727f8c919ca39e97918a81796f6a6054483b2e2215090000000000000000000000000000000000000000000000050f19232b353d454d525961636a6f74787b7d8082838486929fac9f92868483827f7c7a76716d67605c544e463e352c231a0f0600000000000000000006101820262b2e2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2e2b2620181006000000000000000006111b262f38424a505a61686e747b81858a8e919697999b9c9d9e9f9f9f9f9f9e9e9d9b9a9898928f8c87827d78706b605d554d453b33291f160c0100000000000000000000000000000000000000000000000000000000000000010406131313131313131307070502080d111314181b1d1f1f201f1e1d1b181413110d08010000000001080d111314181b1d1e1f201f1e1d1b181414110e090200000000000000000000000000131f2c3946525f6c7985929facb8b4aca6a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a7a9aeaeafafa59d9a96918d88837d746d685f584e463c33291d140a00000000000000000d1a2733404d5a6673808d99a6ada194877a6e6154473b2e2114080000000000000815222f3b4855626e7b8895a1aea6998c807366594d4033261a0d000714212d3a4754606d7a8793a0adb3a9988b7f72655a50463d3a3635393a41465059606d7984919eabb4b2a5988b7f7265584c3f3a37312a21180e030000131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000000000000000000000713202c3945525d687783909daab4aa978a7d7064574a3d3124170a0000000d19242f3a444f59606d7984919aa49f93887d70685d5245464646464646464653606d798693a0aca194877b6e6154484646463f3e3a342d251b11070000121e2b3845515e6b7884919eabaea194887b6e6155483b2e221b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b171714110c05000000000000000714202d3a4753606d7a86929facac9f92867a6d60554b403529241d1a171b1f2028313a44515c666d7775716d6866625f584e43372b1f12060000000004101c2834404b5564717e8b98a2aca096897d70635a50443b31282321222329323c44515c6673808c99aab1a7988b7e7265584b3f3225180800000005111e2a36424d5765727f8b98a2aea99c8f82756b60564c433c38332d2e34383c424b555f6a74818e9ba8aea3988c7f7266574d42372b1e120500000000000000000000000000000000000000000000000000000006111b262f38424a50535b60606060606060605d54514c433a31271e150b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d363f49515b626d727f8c9193939393938e847c6f6256493c2f231609000000000000000000000000000000000000000000000000071119232b333b42464f55585f6267696e71737576787c8895a093867977767572706d6764605d55514b423d342c231a1108000000000000000000040e18222a31373a3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3a37312a22180e03000000000000040d17222d38414a545b606c717a81878d92989b9ea1a8a6a7a8a7a5a4a3a3a3a3a4a5a6a8a6aaa39f9c9a938f8a837d746d675e574d453b31281d13070000000000000000000000000000000000000000000000000000000000000000000006060606060606060000000000010507070b0e101213131212100e0b070604010000000000000000010406070b0e101212131211100e0b08070502000000000000000000000000000000131f2c3946525f6c7985929facb8b0a8a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa0a1a2a5a7aba8a09e9a949089817a6e6a5f584e453b2f261c1106000000000000000e1a2734414d5a6774808d9aa7ada093877a6d6054473a2d2114070000000000000815212e3b4854616e7b8794a1aea69a8d8073675a4d4034271a0d000714212d3a4754606d7a8793a0adada197877a6e6154473e342d2a292c30353e45515c67727f8c99a3aeb2a5988b7f7265584c3f322b2620180f06000000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000000000000004111d2935414c566875818e9ba8b2a5998c7f7266594c3f3326190c00000008131e28323d45515d67707d88939fa49a91847a6d60594f443a303939393a4653606d798693a0aca194877b6e6154483b393932312e29231b1309000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e28282828282828282828282828282828282828282828282828282423211c1710080000000000000a1723303d4a5663707d8998a3aea89b8e8275675d51433a2f23181d1d1d1d1d161f2834404a545c606a6864615e5655534e463c32261b0f030000000006131f2c3845515c6775828f9caaaa9d9184776b6054483e32291f18151518202834404a54626f7b8898a2aea89b8e8175685b4e423025190d0100000714202d3a46525e697683909daaada196897d7063594f433a312b282223282c3039434e58626f7c8895a0acaa9d908477695f53463a2d211407000000000000000000000000000000000000000000000000000000000a141d262f383f44464e5353535353535353504745413a31281f150c030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d373f49515b636d737f86868686868686868174675a4e4134271b0e01000000000000000000000000000000000000000000000000071119202930363e44484e5355575e616467686a6f7b8895a093867a6d69686663605d5553514b454039302b221a1108000000000000000000000a15202a343c434748494949494949494949494949494949494949494949494949494949494949494949494949494949494847433c342a20150a0000000000010c161f27333f49535b666c747e858e92999fa2aaaba9a8a19e9c9a9897979696979798999c9e9fa4acaca49f9c95908981796e695f574d433a2f24180d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000131f2c3946525f6c7985929facb8a89e969393939393939393939393939393939393939393939495989b9ea1a9aaa69f9c938e847c6f6a5f574d42382d22170b000000000000000e1b2734414e5a6774818d9aa7ada093867a6d6053473a2d2014070000000000000814212e3b4754616e7a8794a1ada79a8d8174675a4e4134271b0e000714212d3a4754606d7a8793a0adab9e918578685e5246392c221e1d20242934404b55616e7a86929facb2a5988b7f7265584c3f32251a150e0600000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000010d19242f404d596673808c99a6b3a79b8e8174685b4e4135281b0e000000010c16202935404b55606b74808d96a0a1968e81746b61564c4135292d2d3a4653606d798693a0aca194877b6e6154483b2e2d2525221e18110901000000121e2b3845515e6b7884919eabaea194887b6e6155483b35353535353535353535353535353535353535353535353535353531302d28221a120800000000000d1a2733404d5a6673808d99aab4aa978b7e7164554c4131282a2a2a2a2a2a2a2a2a232e39424a51535d5b5754524c4847433c342a20150a00000000000713202d3a4653606d7985929facab998c7f7366594f44362c20170d07070e18232e394653606c7985929fabaa9d9184776a564c41362a1d110500000814212e3b4754616e7b87959fabab9e9184786c6053463d31281f1c17181c1f27313c47535f6a7784919daaaca095887b6e6155483b2e22150600000000000000000000000000000000000000000000000000000000020b141d262d333839424646464646464646443a39352f281f160d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b252d373f49515b636d737979797979797979746e64584c4033271a0d0100000000000000000000000000000000000000000000000000070e171f252a33383c4347484d5254575a5c626f7b8895a093867a6d605b595653514b47454039342e271e19100800000000000000000000030f1b26313c464e53555656565656565656565656565656565656565656565656565656565656565656565656565656565655534e463c31261a0f030000000007131d28313a44505b656c78808a92979fa3abaaa69f9c9896918f8d8b8a8a89898a8a8b8d8f91939a9c9fa4aca7a09d938e837b6e695f554b41352921160a000000000000000000050a0d0f101313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313100f0d0a050000000000000000000000000104060712131313130908060300000000000000000000000000131f2c3946525f6c7985929facb8a2968c87868686868686868686868686868686868686868787898b8e92979da0a7aba59d9691857c6f695e544a3f33281d12070000000000000e1b2834414e5b6774818e9aa7aca09386796d6053463a2d2013070000000000000714212e3a4754616d7a8794a0ada79a8e8174675b4e4134281b0e000714212d3a4754606d7a8793a0ada99c8f827669564d41362a1a12111319232f3946525e687683909da9b2a5988b7f7265584c3f32251909030000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000000000000000081824313e4b5764717e8a97a4b1a89c8f8275695c4f4236291c0f00000000040d18242f3a434f59606d79849199a39d938a7d70685e52463e32292d3a4653606d798693a0aca194877b6e6154483b2e21191816120d070000000000121e2b3845515e6b7884919eabaea194887b6e615548424242424242424242424242424242424242424242424242424242423e3c39332c241a100500000004101c2834404b546976828f9ca9aea398887b6f6255483c2f3737373737373737373737373039404446514e4b4746413c3b37322a261f180f06000000000a1723303d4a5663707d8998a2aea399897c706356493d32231a0e05000007121f2b3844505b6676838f9ca9ac9f928579685e5246392d20130700000b1824313e4b5764717e8a97a7b1a79a8e8174665b5044382b1f160f0b0c10151f2b37434e586773808d9aa6b1a7988b7e7165584b3e2d22170b0000000000000000000000000000000000000000000000000000000000020b141c22282b2d353939393939393939372d2c29241e160d04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131b252d373f49515b63666c6c6c6c6c6c6c6c67645c53483c3024180b000000000000000000000000000000000000000000000000000000050d141a21282c31373a3c4246484a4d55626f7b88959f93867a6d60534c494745403a39352f28231d150c07000000000000000000000006121f2b37434e585f6262626262626262626262626262626262626262626262626262626262626262626262626262626262625f584e43372b1f1206000000010d18242f3a434f59606c77818d929fa2a9ada59e9b948f8b888482807f7e7d7d7d7d7e7e808284878b8f939a9ea6aca59d9590847b6e675d51453d32271b0f03000000000000030a1016191c1d20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201d1c1916100a03000000000000000001070d1113141f202020201515120f0a040000000000000000000000131f2c3946525f6c7985929facada093877a797979797979797979797979797979797979797a7b7c7e81858a90959fa3aba8a19792857b6e665b5044392e23180c0000000000000e1b2835414e5b6874818e9ba7aca09386796d6053463a2d2013070000000000000714212d3a4754606d7a8793a0ada79b8e8174685b4e4135281b0e000714212d3a4754606d7a8793a0ada89b8e8175685b4e423025190f0408121d2a36414c566774818d9aa7b2a5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000000a1724303d4a5763707d8a96a3b0a99c908276695d5043362a1d10000000000007131d28313d45515d676f7c87929fa59e91857a6d615a50443b302d3a4653606d798693a0aca194877b6e6154483b2e211508090601000000000000121e2b3845515e6b7884919eabaea194887b6e61554e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4a49453e362c22170c00000006131f2c3845515c667884919eabac9f9286796d6053464444444444444444444444444444444444444444444444444444443b3a36312a21180e030000000d192633404c5966737f8c99aaac9f92867a6d6053473a2d201407000000030f1c28333f4a546874818e9ba7aea298877a6d6154473a2e21140700010e1b2834414e5b6774818e9aa7b4aa978a7e7164544a3f3328190d040000040d1b26323d4a5764707d8a97aab4a79b8e81746853493f33271b0f030000000000000000000000000000000000000000000000000000000000020a11171c1f20282d2d2d2d2d2d2d2d2a21201d19130c040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000109131b252e37404951575960606060606060605a58534a41362b2014080000000000000000000000000000000000000000000000000000000002090e161c20262b2e30363a3b3e4855626f7b88939393867a6d6053473d3a39352f2c29241d18120b030000000000000000000000000815212e3a47535f6a6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6a5f53473a2e21150800000004111d2935414b55616b73808d939da4ada9a29f938e88827e7b78757472717070707071727375777b7e82878f939fa2aaa7a0969183796d60594f43382c1f14090000000000040d151c212629292d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d292926211c150d04000000000000040c13181d20202b2d2d2d2d22211f1b150e0600000000000000000000131f2c3946525f6c7985929facada093877a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c666c6d6e6f7274797e838c9299a3aba9a1978f82786c60554b4034281c100400000000000e1b2834414e5b6774818e9aa7aca09386796d6053463a2d2013070000000000000714212e3a4754616d7a8794a0ada79a8e8174675b4e4134281b0e000714212d3a4754606d7a8793a0ada79a8d8174675a4e4134271b0801010d1925303e4b5864717e8b97a4b1a5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000000a1623303d495663707c8996a3afaa9d9083776a5d5044372a1d110000000000010c161f2935404b55606a73808d95a0a1978e81756c61564c41362d3a4653606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e615b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b575550483e33281c110400000713202d3a4653606d7986939facaa9d908477665c50505050505050505050505050505050505050505050505050505050504846423b332a1f1409000004101d2935404b556975828f9ca8aa9d918477675d5145392c201306000000000b17222d414d5a6774808d9aa7b4aa94887b6e6155483b2e2215080005111e2a36414c566a7683909da9aea298887b6e6155483b2d221708000000000a15212e3b4854616e7b8798a2aeaa9d908377655b5044372b1f120500000000000000000000000000000000000000000000000000000000000000060b0f12131b20202020202020201d1413110d08010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e3740464b4c53535353535353534e4c4841382f251a0f03000000000000000000000000000000000000000000000000000000000000050b10151b1f21252a2d2f3c4855626f7c8686868686796d6053473a2d2c2924201d18120c0700000000000000000000000000000915222f3c4855626f7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c6f6255483c2f2215090000000613202c3945515d67707d8a929ca5aea9a197928a817c76726e69696765646463636464656669696e72767c828a9298a2aaa8a0958e81746b6054483c31261a0e02000000030d161f262d32353639393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393635322d261f160d0300000000040d161d24292c2d38393939392f2e2b2620181006000000000000000000131f2c3946525f6c7985929facada093877a6d606060606060606060606060606060605b6060616265666d71787f879299a3afa99f948b7f72675c5145382c1f130700000000000e1b2734414e5a6774818d9aa7ada093867a6d6053473a2d2014070000000000000814212e3b4754616e7a8794a1ada79a8d8174675a4e4134271b0e000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d0100081724303d4a5763707d8a96a3b0a5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000000916222f3c4955626f7c8895a2afaa9e9184776b5e5144382b1e11000000000000040d18242f39434e58606d79839099a39e938a7e71685e52463e333a4653606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6868686868686868686868686868686868686868686868686868686868686864615a5045392d21140800000815212e3b4854616e7b879aa4afa99c90837669545d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d55534d453b31261a0e020006131f2c3845515d677884919eaba99d9083766a554b4035291d110400000000061a2633404d596673808c99a6aea295887b6f6255483c2f221509000713202d3946525e687885929fabac9f9285796c605346392d201306000000000714212d3a46535e697985929facac9f9285796c605346392d2013060000000000000000000000000000000000000000000000000000000000000000000306060f131313131313131311070604010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e353b3e40464646464646464641403c362f261d1308000000000000000000000000000000000000000000000000000000000000000000040a0f12151a1e212e3a47535f6a76797979797976675c5145382c201d1813100d0701000000000000000000000000000000111e2a3744515d6a77848989898989898989898989898989898989898989898989898989898989898989898989898989898983766a5d5043372a1d10000004101d2935404b55606d7984919ea4aeaaa19791857e756f6a65615f575a58575756565757585a565e61656a6f757e869298a2aea89e93897c6f63574d42372b1e12050000000a151f2831383e4243464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464643423e3831281f150a000000010c161f282f35393a45464646463c3b37322a22180e040000000000000000131f2c3946525f6c7985929facada093877a6d6054535353535353535353535353534a5053545456545c60666d737e87929fa7b0a69e9185796d6053463a2f24180d01000000000e1a2734414d5a6774808d9aa7ada093877a6d6054473a2d2114070000000000000815212e3b4854616e7b8794a1aea79a8d8074675a4d4134271a0e000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d0100091623303c4956636f7c8996a2afa5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000000916222f3c4955626f7c8895a2afab9e9184786b5e5145382b1e120000000000000007121d27313d45515c666f7c87929fa59e92857a6e615a50453b3a4653606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b7575757575757575757575757575757575757575757575757575757575757575716c6155493c3023170a00000916232f3c4956626f7c8995acb6a89c8f82756a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a615f574d42362a1e1205000714202d3a4753606d7a86939faca89c8f8275695c4f422f24180d01000000000d1a2733404d5a6673808d99a6afa295887c6f6255493c2f221609000714212e3a4754616d7a8798a2aeaa9d918477665b5044382b1f12060000000005121e2a36424d576a7784919daaaea298877a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c232a2f323339393939393939393433302b251d140b0100000000000000000000000000000000000000000000000000000000000000000000000306090e121f2b37434e585f626c6c6c6c6c6c5c554b4034291c110d0704010000000000000000000000000000000000111e2a3744515d6a77849095959595959595959595959595959595959595959595959595959595959595959595959595959083766a5d5043372a1d10000006131f2c3945515d67737f8c96a1adaea29891857b716c625f5855534d4d4c4b4a4a4a4a4b4b4d4d5254585f626c707c86929fa7afa59c8f8276695f53463a2d211407000005101c26313a42494e505353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353504e49423a31261c1005000007131d28313a40454752535353534847433c342a20150a0000000000000000131f2c3946525f6c7985929facada093877a6d6054474646464646464646464646463f44464748494b51545c606c727e8b959fabada1978b7e7165554b4135291d1104000000000d1a2733404d5a6673808d99a6ada194877a6e6154473b2e2114080000000000000815222f3b4855626e7b8895a1aea6998d8073665a4d4033271a0d000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222f3b4855626e7b8895a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000000916232f3c4956626f7c8995a2afaa9d9183776a5e5144372b1e1100000000000000010b151f2834404b545f6a737f8c959fa1978f82756c62574d423a4653606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabb5a89b8f8281818181818181818181818181818181818181818181818181818181818181817e7164574a3e3124170b00000a1623303d495663707c8996a3afa89b8e8177777777777777777777777777777777777777777777777777777777777777776e695f53463a2d211407000915222f3c4855626f7b889aa4afa89b8e8275685b4f422d22170b00000000000e1b2834414e5b6774818e9aa7b4ab95887b6e6255483b2f221508000915222f3c4855626f7b8895aab4a99c8f837669544a3f33281c0f0300000000020e1a2531434f5c6976828f9ca9b4aa95887b6f6255483c2f2215090000000000000000000000000000000000000000000000000000000000030607090b0d0f1111121313121211100f0d0a080705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d272724201a130b02000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b26313c464e535560606060605f514b43392f23180c010000000000000000000000000000000000000000111e2a3744515d6a7784909da2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29d9083766a5d5043372a1d1000000714202d3a4753606d7985929ea8b1a79f92867c6f69615a534e484642413f3e3d3d3d3d3e3f404246474e535a616a717e8b959fabac9f93877b6e6155483b2e22150800000a16212d38424c545a5c60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605c5a544c42382d21160a00010d18242f3a434b51535e6060606055534e463c32261b0f0400000000000000131f2c3946525f6c7985929facada093877a6d6054473a393939393939393939392d3338393a3b3c40454a505a606c7883909da9b3a99d908376675d5145392c201306000000000c1926333f4c5966727f8c99a5aea195887b6e6255483b2f2215080000000000000916222f3c4955626f7c8895a2afa5988c7f7265594c3f3226190c000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000000a1623303d495663707c8996a3afaa9d9083776a5d5044372a1d110000000000000000030d18232e39424e58606d78839098a39e948b7e71695e52463f4653606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabb7aa9e938f8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8c807366594d4033261a0d00000a1724303d4a5763707d8a96a3b0ab9e928583838383838383838383838383838383838383838383838383838383838383837b6e6155483b2e221508000a1724303d4a5763707d8a96acb6a89c8f827569544a3f33281c0f0300000004111d2935414c566875828e9ba8aea399877a6e6154473b2e211408000a1723303d4a5663707d8996a3b0a89b8e8275685b4f422d22170b000000000000091c2835424f5b6875828e9ba8b0a396897d7063564a3d3023170a000000000000000000000000000000000000000000000000000104060b10121315171a1c1d1e1f1f201f1f1e1d1b19171514120e09060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d1216191920202020202020201b1a18140f080100000000000000000000000000000000000000000000000000000000000000000000000000000000000a15202a343c43474853535353535345403931271d1207000000000000000000000000000000000000000000111e2a3744515d6a7784909d9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9d9083766a5d5043372a1d100004101c2834404b5464717e8a97a2acaca0958b7e726a5f575047433c3a3631323131303031313230363a3c43475058616c7683909da9afa49a8c7f7265594c3f3226190700000d1926323e49545e66696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c69665e54493e3226190d0004111d2935404b555d606b6c6c6c6c625f584e43372b20150a00000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2d2d2d2d2d2d2d2d2d22282b2d2d2e2e34383f44505b65707d8997a2adac9f92867a6d6054473a2d211407000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090000000000000a1623303d495663707c8996a3afa4988b7e7165584b3e3225180b000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000000b1824313e4b5764717e8a97a4b1a99c8f8276695c504336291d1000000000000000000007121d27303c44505c666f7c86929fa69f92857b6e615b51454653606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabb7afa59e9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b998c807366594d4033261a0d00000a1724313d4a5764707d8a97a3b0ada1979290909090909090909090909090909090909090909090909090909090909090887b6e6255483b2f221508000b1825313e4b5864717e8b97a4b1a99d908376665b5044382b1f130a0603060a13202c3945525d687784919daaac9f9286796c605346392d201306000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b060000000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000000000000001070d1113171c1f20222426292a2b2b2c2c2c2b2b2a28262422211e1a1312100c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002060a0c0d13131313131313130e0d0b080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000030e18222a31373a3c46464646464638342f271f150b01000000000000000000000000000000000000000000111e2a3744515d6a77839093939393939393939393939393939393939393939393939393939393939393939393939393939083766a5d5043372a1d100006131f2c3845515c6675828f9a9c9fa29d9083786d60584e453e37322d2a262524242323242425252a2d32373e46505a64717e8b97aab3ac9c8f8275695c4f422f24180c00000f1c2935424e5a66707679797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797670665a4e4235291c0f000613202c3945515d676d78797979796f6a5f53473d32271b0f00000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d212020202020202020171c1f20212123282e343f4953606d7985929eabafa3998a7d7063574a3d3024170a000000000b1724313e4a5764717d8a97a4b0a3968a7d7063574a3d3024170a0000000000000b1724313e4a5764717d8a97a4b0a3978a7d7064574a3d3124170a000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000000000c1926333f4c5966727f8c99a5b2a79b8e8174685b4e4135281b0e000000000000000000000b151e28343f4a545f6a727f8c949fa2978f82766d62574d4653606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabb7b8afaaa8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a6998c807366594d4033261a0d00000a1724313d4a5764707d8a97a3b0b3a9a19e9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d94887b6e6155483b2e221508000c1926323f4c5965727f8c98a5b2ab9e9285796c6053463a30241b14121012141c26303a4754606d7a86939facaa9d918477655b5044372b1f1205000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b0a4978a7d7164574a3e3124170b00000000000000000000000000000000000000000003090e13181d2023282b2d2f3133353737383939393837373533312e2d2a26201f1c17110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006101820262b2e2f3939393939392c29231d150d0300000000000000000000000000000000000000000000111e2a3744515d6a77838686868686868686868686868686868686868686868686868686868686868686868686868686868683766a5d5043372a1d10000713202d3a4653606d79868b8d909298988a7e71665c50463c332b26211e1a1918171717171818191e20262b343e4754616e7b8798a2aeaa9e9184776b554b4035291d100400101d293643505c69768386868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868276695c504336291d10000714202d3a4753606d7a85868686877c6f62584e43372b1d1207000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114131313131313130b0f12131415181c232d3844505c6675828e9ba8b5ab998c7f7266594c3f3326190c000000000916232f3c4956626f7c8995aab4a4978b7e7164584b3e3125180b0000000000000c1925323f4c5865727f8b98a5b4aa95887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000000000000004101c2934404b556774818e9aa7b3a6998c807366594d4033261a0d00000000000000000000030c17232e38424e58606c78839098a29f948b7f72695f544a53606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabb7b1a9a3a19f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f998c807366594d4033261a0d00000a1723303d4a5663707d8996a3b0b8b0aba99f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa9aaaaaaaaaa94877a6e6154473b2e211408000d1a2733404d5a6673808d99a6b3ada297887c6f62564c41352d26201f1c1f20262e38424e5864707d8a9aa4afa89b8e81756853493f33271b0f03000b1825313e4b5864717e8b97a4b1a79a8d8074675a4d4134271a0e0100000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b00000000000000000000000000000000000000040a0f151a1d24292c2e34383a3c3e404244444546464545444342403d3b3a36312d2c28231c19130d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000040607090c0e1011121313131211100f0d0b0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e151b1f21222d2d2d2d2d2d1f1c18120b030000000000000000000000000000000000000000000000101d2936424f5b677177797979797979797979797979797979797979797979797979797979797979797979797979797979797671665b4e4236291c10000613202d394653606c777c7e808385888b867a6d60544a3f342a211b15120e090b0a0a0a0a0b090e11151b222d3a46525e697885929fabac9f928679675d5145392c1f130600101d293643505c6976838f9393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393938f8276695c504336291d10000613202c3945515d67717e8b959a8f82756a605447392e23180c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070606060606000003060607070c111b28343f4a546673808d99a6b3a69a8d8073675a4d4034271a0d010000000814212e3b4754616e7a8798a3aea6998c7f7366594c40332619090000000000000d1a2733404d5a6673808d99a6aea298877a6d6154473a2e211407000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000000000000006131f2c3845515c677783909daab4aa988b7e7165584b3e3225180b000000000000000000000006111c26303c44505b666e7b86929fa69f92867b6e665b5053606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabb7a99f9894939393939393939393939393939393939393939393939393939393939393938c807366594d4033261a0d0000091623303c4956636f7c8996a2afb0a69f9c9393939393939393939393939393939393939393939393939c9ea6b0aea398877a6d6054473a2d211407000e1a2734414d5a6774808d9aa7b3b3a9998c8073685d52463f382f2d2b282b2d30383f4a545f6a76828f9cacb0a6988b7e7265584b3f2d22170b00000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b000000000000000000000000000000000000070c151b20262b2f35393a3f4446484a4d4f5051525253525251504e4c4a4846423d3a38342e29251e19140d050000000000000000000000000000000000000000000000000000000000000000000000000004070c10121316191b1d1e1f1f201f1f1e1d1b19171414110e0806030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a0f12151520202020202013100c07010000000000000000000000000000000000000000000000000e1a27333f4a555f676a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a665f554a3e32261a0d0005121f2b3744505b656c6f717476797b7e7e71675d5142382e22180f0a0502000000000000000002050b111e2a36424d566b7884919eabafa399867a6d6053473a2d20140700101d293643505c6976838f918b86868686868686868686868686868686868686868686868686868686868686868686868686868686868686868b918f8376695c504336291d100004111d2935404b55606d7883909d94897c6f62544b4034281c10040000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000000000000b17232e3f4c5965727f8c98a5b2a79a8e8174675b4e4134281b0e010000000613202d394653606c7985929faca79b8e8174685b4e4131261a0e020000000003101c28343f4a546875828e9ba8ac9f928579685e5246392d201307000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000000000000000000000714202d3a4753606d7986929facaea298887c6f6255493c2f2216090000000000000000000000000a151e28333f4a545f69727f8b949fa2989082786c605753606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabb7a3988d888686868686868686868686868686868686868686868686868686868686868686807366594d4033261a0d00000815222f3b4855626e7b8895a9b3ab9f948f8686868686868686868686868686868686868686868686868f949eaaac9f928579675d5145392c201306000e1b2734414e5a6774818d9aa7b4b8ab9f92857a6d615b5049413c393834383a3d424a505c666e7c87939facab9f94877b6e6154483b2e21150600000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b0e0100000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a00000000000000000000000000000000030b121820262b31373a4145474a50535557595c5d5e5e5f5f5f5e5e5d5b595755534d4946443f3835302a251e170e0802000000000000000000000000000000000000000000000000000000000000000001070c1013181c1f20232527292b2b2c2d2c2c2b2a28262421201e1915120f0a0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306080913131313131306040000000000000000000000000000000000000000000000000000000a16222e39434d555b5d606060606060606060606060606060606060606060606060606060606060606060606060606060605d5b554d43382d22160a00030f1b27333f49535b60626467666c6e71716c62554b4030261c100600000000000000010507090e12161c222c3845515c677885919eabaea399877a6d6054473a2d21140700101d293643505c6976838f8b7f79797979797979797979797979797979797979797979797979797979797979797979797979797979797979797f8b8f8376695c504336291d1000010d18242f3a44505c66717e8a979a8e8174665c5145382c1f13060000000000131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000000000000000104091925323f4c5865727f8b98a5b2a89b8e8175685b4e4235281b0f0200000005121f2b3744505b657783909daaa99c90837669574d42362a1e12050000000006121f2c3844505c667783909daaa99d9083766a564c4135291d1105000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000007101d2935404b5563707d8a99a3aeac9f9285796d6053463a2d201307000000000000000000000000030c17222d38424d57606c77828f98a29f948c7f726a5f54606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b7979797979797979797979797979797979797979797979797979797979797979736e63574b3f3226190c00000714212d3a4754606d7a8797a2ada99c8f82797979797979797979797979797979797979797979797979828f9ca9ab9e9184786b554b4135291d1104000e1b2834414e5b6774818e9aa7b4b3ada2988d81746d605b534e4846443f4446484e545c606d7883909aa4afa79c8f8376695e52463a2d20140700000a1723303d4a5663707d8996a3b0a89b8e8175685b4e4235281b090000000000020f1b2835424e5b6875818e9ba8b0a3968a7d7063574a3d3024170a000000000000000000000000000000070c151d232831373c42474b5154545c60626466686a6a6b6c6c6c6b6a6a686664615f575653504a46413a3630292019130d05000000000000000000000000000000000000000000000000000000000003090e12181d1f23282c2d3032343638383939393838373533312e2d2a25211f1b150f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c27313b434a4f5153535353535353535353535353535353535353535353535353535353535353535353535353535353504e4a433a31271c110500000b17222d38414950535558545b60626465625a50433a2f1e140a00000000020507080d1113141a1e21272c343c4653606d7986929facac9f928679675d5145392c20130600101d293643505c6976838f8b7f726c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c727f8b8f8376695c504336291d10000007131d28343f4a54606d7985929e9285796d6053463a2d2013070000000000131f2c3946525f6c7985929facada093877a6d6054473a2d21140c0c0c0c0c0c0c0c0c0c0c070d10151c28333f4a546673808c99a6b3a79a8e8174675b4e4134281b0e01000000030f1b27333f49536874818e9ba7ab9f928578695f53463a2d211407000000000713202d3a4653606d7986929faca79a8e8174675b4e413025190d01000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000000000050e19222c3945515d6774818e9aabb4a99c908376665c5044382c1f12060000000000000000000000000006111c262f3c44505b656e7b86929fa69f92867b6e665c606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c66635c52473b2f23170a00000613202c3945515d677885929eabaa9d9184776c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c667784919eaaa99c8f8376695c50432f24180d01000e1b2834414e5b6774818e9aa7b3a9a19e9e928b7f726c655f585553504a5053555860666d74808d959facaba0958a7d7164574d42362a1e120500000916222f3c4955626f7c8895aab4a99c8f8276695c4f4330251a0e0200000000030f1c2936424f5c6975828f9ca8b5ab95897c6f6256493c2f23160900000000000000000000000000000810191e272e343c43474d53555d6064666d6f7173757777787979787877767573706e696763605c54524c46413b322a251e170e06000000000000000000000000000000000000000000000000000001070c141a1d24292c2e34383a3c3f4143444546464645444342403e3b3936302e2b261f1c17110a020000000000000000000000000000000000000000000000000000000000000000000000000000040607090c0e1011121313131211100f0d0b0807050200000000000000000000000000000000000000000000000000000b151f2931393f42444646464646464646464646464646464646464646464646464646464646464646464646464646464643423e3831281f150a00000006111b262f383f4446484b4a50535558585650483f31281d0c02030506090e121415191d2021262b2d33383e464e58636f7c8999a3afab9e9185786b554b4135291d110400101d293643505c6976838f8b7f72656060606060606060606060606060606060606060606060606060606060606060606060606060606065727f8b8f8376695c504336291d100000010b17232e3845515c6673808d99978a7d7063574a3d302417070000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211919191919191919191919191a181d20262b3844505b6674818e9ba7b3a6998d8073665a4d4033271a0d00000000000b17222d3f4c5965727f8c98aaada297887b6e6155483b2e23180c000000000915222f3c4855626f7b8898a3aea9988b7e7265584b3f3225180800000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000060e17202935404b55606d7985929fabb1a7988c7f7265544a3f34281c100300000000000000000000000000000a141d27333f49535e69717e8b949ea3989083786d60606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e616060606060606060606060606060606060606060606060606060606060605957524a40352a1f1307000004111d2935414c55697683909ca9ab9f928578695f606060606060606060606060606060606060606d7986929faca79a8d8174675a4e4134271b0700000e1b2734414e5a6774818d9aa7ada19792919692877f776f6a6562605b545c6062656a6f78808d929ca7afa4999083786c6053463b30251a0e0200000814212e3b4754616e7b8798a3aeaa9d9084776a574d42362a1e12050000000005111d2935414c566a7783909daaafa399877b6e6154483b2e2115080000000000000000000000000009111a222a303940454e53575f62676d7175797b7d8082838485858685858483817f7d7b7874706d66615e56524c443e36302920180f07000000000000000000000000000000000000000000000000030b12181f252a2f35393a404446494c4e5051525253525251504e4c4a4746413c3a37312b28221c140b070000000000000000000000000000000000000000000000000000000000000000000004070c10121316191b1d1e1f1f201f1f1e1d1b19171414110e0806030000000000000000000000000000000000000000000000040d171f272e333637393939393939393939393939393939393939393939393939393939393939393939393939393939393736322d271f160d03000000000a141d262d3337393c3e3f4446484b4b4a453f362d1f160c0b0f1213151a1e2121252a2d2e31373a3d44485058606a74818e9babb5a99d9083766a5d50432f24180d0100101d293643505c6976838f8b7f72655853535353535353535353535353535353535353535353535353535353535353535353535353535865727f8b8f8376695c504336291d1000000006111c2834404b54626f7c88979a8d8073675a4d402e23180c0000000000131f2c3946525f6c7985929facada093877a6d6054473a2d252525252525252525252525262624292c31373f4a54606c7985919eabb3a9988b7e7165584b3e3225180b00000000000616232f3c4956626f7c8998a2aea9978b7e7164544b4034281c1004000004101d2935404b5565727e8b98aaada197887c6f6255483c2f22150900000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211407000000000000000000030a0f182029323b45515d67727e8b97a2adab9f95887b6e6155483b2e23170c000000000000000000000000000000020b17222d38414d57626c75828f97a29f958c7f736a606d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e615553535353535353535353535353535353535353535353535353535353534d4b4740382e24190e020000010d19242f414d5a6774808d9aabaea298887b6e61555353535353535353535353535353535355626f7c8899a3afa9988b7e7265584b3f3225180c00000e1a2734414d5a6774808d9aa7ab9e9285849199928c827c76726e6c666b666d6e72767c828d929ca4aea69f93877c6f655b504437291f14090000000713202d3a4653606d7986929facab9f928578695e52463a2d201407000000000713202d3946525d687885929eabac9f9286796d6053463a2d20130700000000000000000000000009121b232c343c424b51585f62696e747a7d8185888a8c8f9091919292929191908e8c8a8884807d79736d68615e565046413a322a2119100700000000000000000000000000000000000000000000060d151d24293136394045474a515356585a5c5e5e5f605f5f5e5d5b595754524c4847433c38332d261d18120b03000000000000000000000000000000000000000000000000000000000001070c1013181c1f20232527292b2b2c2d2c2c2b2a28262421201e1915120f0a0300000000000000000000000000000000000000000000050d151c2227292a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2a2926221c150d040000000000020b141b22272b2d2f2d3338393b3e3e3d3a342d241b1114171b1f2022252a2d2e3036393a3d4246484f545a616a6f7c87939facb2a8998d8073665a4d4033271a070000101d293643505c6976838f8b7f7265584c4646464646464646464646464646464646464646464646464646464646464646464646464c5865727f8b8f8376695c504336291d10000000000c18232e394653606c7985929c90837669544b4034281c100400000000131f2c3946525f6c7985929facada093877a6d6054473a3232323232323232323232323232332f35393c4347505b66707d8997a1adada297887c6f6255493c2f22160900000000000713202d3a4653606d7985929faba79b8e8174665c5145382c1f160c06060c141f2c3845515d6775828e9ba8ab9e9285786c605346392d20130600000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d21140700000000000205060b0f151a212a323b444e58606d7984919ea9b2a89d908376695f53463a2d1c11060000000000000000000000000000000006111b262f3b45505a616e7b85929fa59f92877c6f666d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e61554846464646464646464646464646464646464646464646464646464646403f3b352e261c120700000000081724313e4a5764717d8a99a3afaa988b7e7165574d42464646464646464646464646424d5765727f8c98abada297887b6f6255483c2f22150900000d1a2734404d5a6773808d9aa6ab9e92857d89929f948f88827e7b79787778797b7f828990949da4aea69e938d80736b6053493f3327170d0300000006121f2b3844505c667784909daaaea298877b6e6154483b2e21150a000000000714212e3a4754616d7a8797a1adaa9e918477665c5145382c1f1306000000000000000000000009121b242d353e464e545c606a6f757b81868a8e929797999b9d9d9e9f9f9f9e9d9d9b999796918d8985807a746e68615a524c443c332b2219100700000000000000000000000000000000000000000910181f272f353b42464b5153545c60636567696b6b6c6c6c6b6b6a686664615e5655534e46443f382f28231d150c05000000000000000000000000000000000000000000000000000003090e12181d1f23282c2d3032343638383939393838373533312e2d2a25211f1b150f0b06000000000000000000000000000000000000000000040b11161a1d1e202020202020202020202020202020202020202020202020202020202020202020202020202020201d1c1a16110a0300000000000000020a11171b1f202222282b2d2f3132312e29221b191e2022272b2d2f31363a3b3e4146474a4d53555960636c717c859199a4afaca096897d706356493d3023160a0000101d293643505c6976838f8b7f7265584c3f393939393939393939393939393939393939393939393939393939393939393939393f4c5865727f8b8f8376695c504336291d1000000915202b353f4744505b6575828f9b918578665c5145382c1f130600000000131f2c3946525f6c7985929facada093877a6d6054473f3f3f3f3f3f3f3f3f3f3f3f3f3f3f40414045474e535b606c7883909da9b3ac9e9285796c605346392d201306000000000006121f2b3844505c6675828f9caaab9e9285796d6053463d31281e171515171e28313a4753606d7985929facaa9b8e8175655b5044372b1f120500000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d21140c0c0c0c0d090e1114171b1f262b333b444c56606a73808c96a1adada1968a7e7164574d42362a1e0a0000000000000000000000000000000000000a141d29333f46525e69717e8a939ea3999083796d6d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b39393939393939393939393939393939393939393939393939393933322f2a241c130a00000000000714212e3a4754616d7a86929faca89b8e8275695e53463d313939393939393939303946525e6976828f9ca9ab9e9285786c605346392d20130600000d192633404c5966737f8c99a6ab9f928578808d939f9c948f8b888685848586888b8f949c9fa6aca49d948f81786c60594f41382d2217050000000003101c28343f4a546875818e9ba8b3aa978a7d7064574a3d32271b0d04000001081623303d495663707c8996a9b3a89c8f827569544b4034281c10040000000000000000000007101b242d363e474f585f666d737c82878e92989b9ea2a9a6a8aaa8a7a6a6a6a7a8a9a8a6a8a19e9a97928c86807a716c615e564d453c342b22190e0500000000000000000000000000000000000009121b222a313940454d53555d6065666d6f72747677787979797877767573716e6867625f5853504a423d342e271e170e05000000000000000000000000000000000000000000000001070c141a1d24292c2e34383a3c3f4143444546464645444342403e3b3936302e2b261f1c17110a0200000000000000000000000000000000000000060e151b1f21222323232323232323232323232323232323232323232323232323232323232323232323232323232322211f1a150e06000000000000000000060b0f121315171c1f2022252524211d1d20252a2d2d3337393c3f4246484b4c525457575f61656b70767e859197a1abb1a79d9184786c605346392d2013060000101d293643505c6976838f8b7f7265584c3f322d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d323f4c5865727f8b8f8376695c504336291d1000010e1a26313d4751595e5f6673808c999786796d6053463a2d20130700000000131f2c3946525f6c7985929facada093877a6d60544c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4d4d4b5153585f626d737f8c959fabafa49a8d8174665b5044382b1f1206000000000003101c28343f4a5464717e8b98a3ada2978a7d7064594f433a30282322222227303a434f5964717e8a98a2aea2988a7d706453493f33271b0f0300000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211919191919191a191e2022272b31373e454d565e686f7c87929fa8b1a79e9184786d6053463b31261a0e000000000000000000000000000000000000020b17212a36424d56616c75818f97a1a0958c80736d798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2626231f19120a0100000000000713202d3946525d6876828f9ca9ac9f92867b6e61584e433b322c292424292c3139424d57616e7b86929faca89b8e8174655b5044372b1f120500000c1825323f4b5865727e8b98a5ac9f92867977818c939a9f9c989993929192939a989c9fa6aba8a09d928d82796d665b50463d2f261b110600000000000b17232e3f4b5865727e8b98a8b2a69a8d807367584e43372b1f15100c090e131e2a36414c5666727f8c99a5b3aa998c7f7366594c402e23180c00000000000000000000050e19222d363e485059616a6f7980878f93999fa3aaabaaaaa29f9d9b9a9a999a9a9b9d9fa2aaa9aba9a19e98928d857e756d685f574e463c342a20170c030000000000000000000000000000000009121b242c343c434b51575e61676d7175797c7f81838485858685858483817f7d7a77736f6a64605b544f454039302920170f05000000000000000000000000000000000000000000030b12181f252a2f35393a404446494c4e5051525253525251504e4c4a4746413c3a37312b28221c140b07000000000000000000000000000000000006101820262b2e2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2e2b262018100600000000000000000000030506060b0f12131518181b1e25292d3036393b3f4446484b4d535457565e616467696e72777d828a9297a1a9b3aa9f958b7e71665b5044382b1f12060000101d293643505c6976838f8b7f7265584c3f322520202020202020202020202020202020202020202020202020202020202025323f4c5865727f8b8f8376695c504336291d100004111d2a36424e59636a6c6c727f8b9894877a6e6154473b2e21140800000000131f2c3946525f6c7985929facada093877a6d605858585858585858585858585858585859595a555d60646a6e767f8c919ca7b1a99f93877c6f62544a3f33281c0f030000000000000b17232e3a4754606d7a86929faca99c9083766b60554b423a342e2f2e2d333a424b55616b7683909daaab9f9285796d6053473a2d22170b0000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2525252525262627252a2d2d33373c434750575f686e7a849199a3afaa9f958b7e71665c504438291f140900000000000000000000000000000000000000050f1925303b44505a616d7a85929ea59f92877c6f798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e22202020202020202020202020202020202020202020202020201a1917130e070000000000000005111d2935414c5664717e8b96a1ada3998d80746a60564d443e39352f2f35383c434b545e6973808d99a3aca096897d706353493f33271b0f0300000b1824313e4b5764717e8a97a4aea399867a6d74808891969d9fa49f9e9e9e9fa4aca9a7a79f9d95918980786d675c544a3f342b1d140a0000000000000615222f3c4855626f7b8896a0acaa9d9184776a6054473c31271f1c181b1a1e242d3946525e6876838f9ca9aea298897c706356493d30231607000000000000000000020d17202b343e48505a616b707c838c92999fa4abaca7a09d999892908f8d8d8d8d8d8f909298989c9fa4abaaa29f97928a827a6e6960584e463c32291e150b00000000000000000000000000000008121b242d363e464e555d60696e74797e8285898b8d8f91919293929291908e8c8a8784807c76716c666059514b433b332921170e0500000000000000000000000000000000000000060d151d24293136394045474a515356585a5c5e5e5f605f5f5e5d5b595754524c4847433c38332d261d18120b030000000000000000000000000000040e18222a31373a3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3a37312a22180e03000000000000000000000000000003060b141a20262b3035393b4146474950535558575e616467686d7074777b7f84898f949fa2a9b2aaa2989083786d60544a3f33281c0f030000101d293643505c6976838f8b7f7265584c3f322519131313131313131313131313131313131313131313131313131313131925323f4c5865727f8b8f8376695c504336291d100006121f2c3845525e6a757979797e8a9795887b6e6255483b2f22150800000000131f2c3946525f6c7985929facada093877a6d656565656565656565656565656565656565666768676d71757b828c919ca4adaba2978e81756a5f5342382d22170b000000000000000613202c3945515d6775818e9ba6ab9f94897d70675d544c443f3c3b3b3c3f444b545d67707d89959faba4998d8174675c5145382c1b11060000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473a32323232323232333430363a3b3f44464e535a61696e7a839096a1abaea3989083786c60544a3f34281c1003000000000000000000000000000000000000000009141f29323e46525e68707e8a939ea399908378798693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e22151313131313131313131313131313131313131313131313130d0c0a07020000000000000000010d1924303a4653606d7984919ea7ab9f92877c6f685e564f47454141414045474e555c666e7b86929faba89e9184786c605346392d22170b0000000a1623303d495663707c8996abb5ab94877b6e6e737d848a9095989b9d9e9f9f9f9e9c9a9895908a847d736d665c554b42382d22190b020000000000000815212e3a47535f6a7784919eabaca095887c6f62584e4339312c282327262b2f35414c56616d7a86929facab9f9285796d6053463a2d20130700000000000000000009141f29323d46505a626c717d8690959fa3ababa49f9b95908c898584828180808081828385888b8f93999fa2aaa9a19e938f847b6f6a60584e443b30271d12070000000000000000000000000006101a242d363f4850585f676d737b80858b8f9298989a9c9e9e9f9f9f9e9e9d9b999795908d88837e786f6b605c554d453b332920170c0300000000000000000000000000000000000910181f272f353b42464b5153545c60636567696b6b6c6c6c6b6b6a686664615e5655534e46443f382f28231d150c05000000000000000000000000000a15202a343c434748494949494949494949494949494949494949494949494949494949494949494949494949494949494847433c342a20150a00000000000000000000000000020a11171f262a32373a4146474c5254535b60626568696e7174777a7d8084888c91959c9fa6adafa9a19892867b6e665c5142382d22170b000000101d293643505c6976838f8b7f7265584c3f3225190c06060606060606060606060606060606060606060606060606060c1925323f4c5865727f8b8f8376695c504336291d10000613202c3946535f6c798786868a909a95887b6f6255483c2f22150900000000131f2c3946525f6c7985929facada093877a72727272727272727272727272727272727272737475777a7d82878f949ca3adaba39992857b6e61584e432f261c11060000000000000004111d2935414c55626f7c88949faba69e9184796d665d56504a494848494950555d666d7984919ea7aa9f93877b6e61554b4034291c0a000000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6054473f3f3f3f3f3f3f3f404042424647495053585f626c717b839095a0a8afa59f92867c6f655b5042382e23170c000000000000000000000000000000000000000000020d17202a36414c56616c75818e96a1a0958b7e788693a0aca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e2215080606060606060606060606060606060606060606060606000000000000000000000000000008131f2c3845515c67727f8b95a0aba39991847a6e68615954514c4e4e4b5153575f676d78839098a2aca0968b7f72665b5044382b1b11060000000815222e3b4855616e7b8899a3afa295897c6f626b6f797e83888b8e909192929291908e8b87837e78706b605c544b43392f261c10070000000000000006121f2b37434e586673808d99a3afa89b8e81756a5f554b433c38342e3431373a4145525d68737f8c99a3afa79b8e8175675c5145382c1f13060000000000000000030d1925303b444e58626c717e879298a0a7afa79f99938e88837f7c79777574737373747577797c7f83878d92989ea5ada59e9691857c6f6a5f564c42392e23180c030000000000000000000000030c18222c363f48505a616a6f7980868d92979c9fa2aaa7a9a8a7a6a6a6a7a8a9a8a6a7a09d9a94908a837c746d675e574d453b32291e150a0000000000000000000000000000000009121b222a313940454d53555d6065666d6f72747677787979797877767573716e6867625f5853504a423d342e271e170e050000000000000000000000030f1b26313c464e53555656565656565656565656565656565656565656565656565656565656565656565656565656565655534e463c31261a0f030000000000000000000000040b141c222831363c43474c5254565e6164656c6f7275787b7e8184868a8d9196989da0a8abb0aba59e9791867d6f695f544a402f261c1106000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000613202c3946535f6c79869293979aa295887c6f6255493c2f22160900000000131f2c3946525f6c7985929facb2a5988c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80808284868a8f92999fa6adaaa29992877d70695e52463c321d140a0000000000000000010d19242f3a47535f6a76828f99a3aca0968f82786d68605c5456555555535b60676d78818f96a0aca2988e8175695f5343392f23180c000000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d60544c4c4c4c4c4c4c4c4c4c4d4e4d5254535b60636a6e757e859195a0a7afa59d938b7f726a5f53493f30261c110600000000000000000000000000000000000000000000050e1925303a44505a606d7a84919ea59e91847a8793a0ada194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e2215080000000000000000000000000000000000000000000000000000000000000000000000000004101c2834404b55606d78839099a3aba09690837a706b64605d555b5b555d60636a6e79818e959faaa49a9184796d60544a3f33281c0a000000000713202d3a4653606d7986929faca4978a7d716460666d71777b7f8183858586858483817e7b76716d666059504a423930271d140a0000000000000000030f1a26313c4854616e7b87929faaac9f92877c6f675d554e46454041414142474c515b606d7a85929eabaca095897d7063554b4034281c100400000000000000010b151f2a36424d56606a717e889299a2aaafa49c959087817c77726f6d6668676766676768666c6f72767b80868e939fa3aaa8a09792867c6f685e544b40342820150900000000000000000000000b151e2a343e48505a626c717c848c92989fa2a9aca8a8a09e9c9a9a999a9a9b9d9fa3ababaaa69f9c95908781796e695e574d443b30261c1106000000000000000000000000000009121b242c343c434b51575e61676d7175797c7f81838485858685858483817f7d7a77736f6a64605b544f454039302920170f050000000000000000000006121f2b37434e585f6262626262626262626262626262626262626262626262626262626262626262626262626262626262625f584e43372b1f120600000000000000000000040d161d262d333b42464e53565e6165686e7175787c7e8184878a8e91939a9a9da0a8aaacaeaca69f9c938e857c6f6b60574d42392e1d140a00000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000613202c3946535f6c7986929fa4a6a295887c6f6255493c2f22160900000000131f2c3946525f6c7985929facb8a79c918c8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8c8d8e9193999c9fa3abaca69f9892877e716b61564d42342a200b0200000000000000000008131e2b37434e58626e7c87929fa7a89e948f827a716d66646262616264656c7079818f939ea8a69f92867b6e61574d4231271d1207000000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d6058585858585858585859595a5b565e6164656c70757c828a9297a0a8afa59e938e81746d62584e41382d1e150a00000000000000000000000000000000000000000000000008131e29323e45525d68707d8a939da1978c808c99a6aea194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e22150801010101010101010101010101010101010101010101010100000000000000000000000000000c18232e3944515c666f7c87929fa4a8a09590847d76716d6769676869676d70757b838e939ea7a59f93887d70665c5142382d22170b0000000006121f2c3844505c667784919eaaa5998c7f7266545c6064696e72747778797979787674716e6964605c544f443f3830271e150b020000000000000000000a15212d3a46535e6975818e98a3aea3999083796d675f5853514b4e4e4e4d53555d606d74818e97a1ada69d9083776b605443392e23180c000000000000000007121d27313946525e696f7c86929aa3ababa39f928d837c756f6a6662605c545a5a5a5a5a545b606265696e747b818a9298a2a9a9a19891847a6e665c51453c31261a0e0500000000000000000007121d27303c46505a626c717e8691969fa2aaaba39f9b9796918f8e8d8d8d8d8f9092999a9ea1a9aba79f9a938d837b6e695e564c42382e23170c0400000000000000000000000008121b242d363e464e555d60696e74797e8285898b8d8f91919293929291908e8c8a8784807c76716c666059514b433b332921170e050000000000000000000815212e3a47535f6a6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6a5f53473a2e211508000000000000000000030c161f282f383f444d53585f62686d72767a7e8185888b8e9196979a9d9fa4acaaacafacaba39f9b948f89817a6f6a60594f453b30271c0b0200000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000613202c3946535f6c7986929facafa295887c6f6255493c2f22160900000000131f2c3946525f6c7985929facb8ada39c9898989898989898989898989898989898989898999a9b9d9fa4abacaba7a09d9490867e716c62594f443b3022180e00000000000000000000010f1b26323c47535f6a73808d959fa8a69e948f847e7974716f6e6e6f7173787d848f939ea5a79f948c7f72695e53453c311f150b01000000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a6d656565656565656565656566676869696e7074787d81878f939ea1a9aca49f938e81786d605b51463c2f261b0c03000000000000000000000000000000000000000000000000020c17202935414c56616b74818e96a19f9285929fabaea194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e22150d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a0907040000000000000000000007121d2834404a54606a727f8c929ca4a7a096918a827d7a7775747475767a7d818790959ea5a59e938d80736b60544b402f261c11060000000003101c28343f4a546875828f9ba8a89b8e817568565153575f6165686a6b6c6c6c6b696765615e5753504a423d342e261e150c070100000000000000000005121e2a36424d57616e7b86929fa6aba0958f82796f6a63605c555b5a5b575f62676d747f8c939ea9a99f948a7d7064594f4430271d120700000000000000000c18232f3943505a616e7b859198a3acaca399928b80786f6a625f585653504a4e4d4d4d4e4a505355575e61696e757e869297a2aaaaa1969082786d60574e42372b21170b0000000000000000000c18232e39424e58616c717f8a9298a0a8aba49f99928e8a8784828180808081828486898d92979ea1a8aca49f9590847b6e685e544a3f342820150a000000000000000000000006101a242d363f4850585f676d737b80858b8f9298989a9c9e9e9f9f9f9e9e9d9b999795908d88837e786f6b605c554d453b332920170c0300000000000000000915222f3c4855626f7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c6f6255483c2f2215090000000000000000000a151e283139424a50575f616a6f757a7f83868b8e9297989b9ea1a8a7aaacafacaaaba39f9c99928e89827c756d6860584f473d33291e150b0000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000613202c3946535f6c7986929facaca295887c6f6255493c2f22160900000000131f2c3946525f6c7985929facacacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a7a8aaa9a7a9a19e9a95908a837b706c625a50473e32291f100600000000000000000000000a15202b37434e58606d78839096a0a8a69e96918b85817e7c7b7b7c7e80848a91969ea5a7a0958f82776c60574d42332a1f0d0300000000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facada093877a72727272727272727272727273737576787a7d8184898e93999ea6ada8a19a938c81786d665c50493f342a1d140a0000000000000000000000000000000000000000000000000000050e1924303a444f59606d7984919aa2989298a2aeaea194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e221a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a171614100b050000000000000000000c18232e39424e58626d73808c929ea1a8a19e948f8a8683828181828386898e93999fa7a39f938f81786d60594f42392e1d140a0000000000000c17232e404c5966737f8c99abaa9d908477685d52464d5355585b5d5e5f5f5f5e5d5b5854534d46443f3830282321201d18130c040000000000000000020e1a25313b46535f69737f8c949fa7a79f948f837c75706d676867676869696e737a818c919ca5aaa1978f82766c6155473d331e150b000000000000000004101c2934404b55616c76828f97a1aaafa49a92877e736d665f58534e4946443f41404040413f4446484d53565e616c717c859298a2aca89f948d80736a5f53473e33281c10040000000000000004101c2834404b545f6a717e87939fa2aaa9a199938e86827e7a777574737373747577797c80858b91969da5afa79f9691847a6e665c50443c32261b0f04000000000000000000030c18222c363f48505a616a6f7980868d92979c9fa2aaa7a9a8a7a6a6a6a7a8a9a8a6a7a09d9a94908a837c746d675e574d453b32291e150a0000000000000000111e2a3744515d6a77848989898989898989898989898989898989898989898989898989898989898989898989898989898983766a5d5043372a1d10000000000000000006111c263039434b545b60696e757c81868b9093999b9ea1a9a8abadafaca9a6a8a09d9a99928f8b86817c766f6b605d564e463d352b21180c030000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000613202c3946535f6c7986929f9f9f9f95887c6f6255493c2f22160900000000131f2c3946525f6c7985929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9f9e9d9c9a9897928e89837e766e69615a50483f352c20170d000000000000000000000000040f1a26313c44505c666e7b8491969ea6a9a19e97918e8b898888888a8d91969ea0a8a59e9590837a6d655b50453b3121180e0000000000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facb2a5988c7f7f7f7f7f7f7f7f7f7f7f7f7f7f80818385878a8d91969b9fa4ababa39f9691887f776d665c544a3f372d22180b0200000000000000000000000000000000000000000000000000000008131e28323e45515d67707d88939fa29fa2aab4aea194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b2e2727272727272727272727272727272727272727272727272727272423201c161008000000000000000007121c27303d46515b646e73808a92979fa3a69f9c9992908f8e8e8f9092989b9fa4a69f99928c81786d665c50473d30271d0b02000000000000061724303d4a5763707d8a99a3ac9f93867a6d6054474246484c4e505252535251504e4b4846423c3b3937332d302d2c29241d160d04000000000000000009141f2a36424d57606d78828f959fa7a69f959087817d79777574747476787b80858e939ca3aaa29892857b6e615a5044352b210c03000000000000000006131f2c3845515c67707d8a949fa9b0a69f93887e716c605c544e47433c3a38342e3433342d3338393c42464d525a616a6f7c86929aa4afa69f92877b6e62594f44392d20150a0000000000000006131f2c3845515c666f7c869299a4aea8a0979187817b75716d6869676766676768676d7073797e848e939fa4aca8a0969083786d60584e43372b20150a0000000000000000000b151e2a343e48505a626c717c848c92989fa2a9aca8a8a09e9c9a9a999a9a9b9d9fa3ababaaa69f9c95908781796e695e574d443b30261c110600000000000000111e2a3744515d6a77849095959595959595959595959595959595959595959595959595959595959595959595959595959083766a5d5043372a1d1000000000000000020c17232e38424b555d666c727b82888e92999c9fa4ababadaeaca9aba39f9d9a9795918d8a86837e7a756f6b636059524c443c342b23190f06000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000613202c3946535f6c7986929393939393887c6f6255493c2f22160900000000131f2c3946525f6c7985929393939393939393939393939393939393939393939393939399929291908f8d8b8885817d77716c615f5750483f362d231a0e05000000000000000000000000000a152028343f4a545e696e7b848f939ea1a8a9a19e9a9795959495979a9ea0a8a8a19e938e837a6e685e53493f33291f0f060000000000000714212d3a4754606d7a8793a0ada69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aea5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facb8a79c918c8b8b8b8b8b8b8b8b8b8b8b8c8c8d8e909297979a9ea1a8acaba39f99928d847d736c655c544a42382e241b100600000000000000000000000000000000000000000000000000000000020c16202935414b55606b74808d96a0abaeb4bcaea194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e6155483b34343434343434343434343434343434343434343434343434343434302f2c28211a110800000000000000000b151e2b343f49525c646e737e858e92999ea1a8a39f9d9c9a9b9c9d9fa3a9a29f9b948f877f776d665c544a3f352c1e150b000000000000000714212d3a4754606d7a86929faca4998a7d7063544b403a3b3f4144454646464543413e3d4347494846443f3f3c3a39352f281f160c0100000000000000030e1a26313b44505c666d7a8390959da5a7a099938e898683828181818385888c92979da5a7a09892867d70695e52483e3323190f000000000000000003101c28343f4a54606d7984919ea6b0aa9e948c7f736c625a504a423c37322d2c282327272722282b2d31363b42465058606a707e88939fa8aea3998f82766c6155493c31261b0f00000000000004111d2935414b55606d79839098a3aba9a09691857d746e6964615d565b5a5a5a5a555c6063666d7179818b939aa4afa89f958c80736a5f54473d32271b0f010000000000000007121d27303c46505a626c717e8691969fa2aaaba39f9b9796918f8e8d8d8d8d8f9092999a9ea1a9aba79f9a938d837b6e695e564c42382e23170c04000000000000111e2a3744515d6a7784909da2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a29d9083766a5d5043372a1d10000000000000000a141e28343f4a545d676d787f868f939b9fa3abacafaca9aaa29f9c999992908d8a8784817d7a76726d68636059544f45413a322b2219110700000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000613202c3946535f6c7987868686868686867c6f6255493c2f22160900000000131f2c3946525f6c79868686868686868686868686868686868686868686868686868686868685858482807e7b7874706b64615a534d453e362d241b11080000000000000000000000000000030c17232e38424d565e696e7a828a91969d9fa7a7a7a4a2a1a1a2a4a6a7a7a09d96918a81796e685e564c41382d21170d000000000000000714212d3a4754606d7a8793a0aca69a8d8073675a4d4034271a0d01000815222e3b4855616e7b8894a1aca5988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facb8ada39c98989898989898989898989898999a9b9c9ea1a9a7aba9a8a19e99928e87817a706b605b534a423930261c1209000000000000000000000000000000000000000000000000000000000000040e18242f3a434f59606d79849199a4afbbb9aea194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e61554840404040404040404040404040404040404040404040404040404040403d3c38332c231a100500000000000000030c19222d37404a525c636c717a81868d9196989b9c9e9f9f9f9f9e9d9b9997928e89827c736c655c544b42382e231a0c03000000000000000613202c3945515d677683909ca9ab9a8e8174665c5145382e323537383939393836313d464e5456555350494b494745413a31281d1307000000000000000009141f28343f4a545e686d7a838e929d9fa7a49f9b9892908e8e8d8e8f9197999ea1a9a29e9590867d706b60574d42362c221108000000000000000006121f2b3844505c66727f8c96a0acaea2988f82776c605a50443f38302b26201f1c171a1a1a171c1f20252a30363e464e58616c73808d96a1acab9f948a7d7064584e43372b1d120700000000000613202c3945515d67737f8c95a0aaada19791847b706b615e5754524c4e4d4d4d4e4b5153545c60676d747f88939fa5afa79f92877c6f62584e43372b1d1207000000000000000c18232e39424e58616c717f8a9298a0a8aba49f99928e8a8784828180808081828486898d92979ea1a8aca49f9590847b6e685e544a3f342820150a000000000000111e2a3744515d6a7784909d9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9d9083766a5d5043372a1d1000000000000006111c26303844505c666d79828c92989ea5acaeabaca49f9d9998928f8c898683807d7a7774716d6865615e56544f48443d353028201910070000000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100006121f2c3845525e6a757979797979797979766a6054473b2e22150800000000121f2b3844515d697479797979797979797979797979797979797979797979797979797979797978777674716f6c65636059555046423c332c241b12090000000000000000000000000000000006111c26303b444d575e686d757e848b9095979a9c9e9e9f9f9f9e9c9a9895908b847e756d675e564c443a2f261b0f05000000000000000714212d3a4754606d7a87939f9f9f9a8d8073675a4d4034271a0d01000815222e3b4855616e7b88949f9f9f988b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929facacacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a6a6a8a9a8a6aba39f9c9996918c87817b746d6761595049413930271e140a000000000000000000000000000000000000000000000000000000000000000007131d28313d45515d676f7c87939fa7b1acaca194877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e61554d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4a48443e352c21160b000000000000000007101b252e38404a525a61686d747b8084888b8e90919292929291908e8c8985817c766f6a605b534b423930261c1108000000000000000004111d2935414b5566737f8c99a7ab9e9285796d6053463e3128282a2b2c2c2c242f39434e58606261605b53585654514b433a2f24180d0100000000000000030b17232e38424c565e686d79818990959b9fa2aaa39f9d9b9a9a9b9c9ea1a9a49f9c97928c837b706b60594f453b30241a100000000000000000000713202d3a4653606d7884919ea8b2a99f92867b6e655b50483e342e261e1b1312100c060d060b0f12131a1f252a343d46505a606d7984919ea8b0a69c8f83766a5f5347392e23180c00000000000714212d3a4754606d7a85929fa7b0a69e92857b6e696059524d47464141404040414045464b51555d606d727f8b939ea9afa3998f82766a605447392f24180c00000000000004101c2834404b545f6a717e87939fa2aaa9a199938e86827e7a777574737373747577797c80858b91969da5afa79f9691847a6e665c50443c32261b0f040000000000111e2a3744515d6a77839093939393939393939393939393939393939393939393939393939393939393939393939393939083766a5d5043372a1d100000000000000b17232e38424f59606d78828f949fa3aaafaca7a09d9a93908c8985827f7c7a7673706d686764605d5654524c48433d383229241e160e07000000000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100004111d2a36424e59636a6c6c6c6c6c6c6c6c6260584e43372b1f130600000000101c2935414d5862696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a69676562605b53544f49453e37312a211a12090000000000000000000000000000000000000a151e29323b454d565d606c71797e83878a8d8f9192929292918f8d8b87837e79716c605d554c443b32281d140a00000000000000000714212d3a4754606d7a8793939393938d8073675a4d4034271a0d01000815222e3b4855616e7b8893939393938b7f7265584c3f3225190c000000000000131f2c3946525f6c7985929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9f9e9d9c9b99979992908c89847f7b746e69605d554f443f382f271e150c020000000000000000000000000000000000000000000000000000000000000000010c161f2935404b55606b73808d95a09f9f9f9f94877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e615a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a57554f473e33281c1004000000000000000009131c262e38404850565e61696e73787c7e818384858686858583817f7c79746f6a625f585049413930271e150a000000000000000000010d18242f3b4855616e7b88959faba1978a7e71645a50433a2f241d151f141c2935404b55606a6f6e6c65676563605d554b4135291d1104000000000000000006111c26303a444c565e676d747c83898e9298999b9d9e9f9f9f9f9e9d9b999993908b857f786e6960594f473d33291f1208000000000000000005111e2a36414c5664707d8a96a1adada1978c7f72695e53493f3628231c140c0a060300000000000306090e1419222b343e45515d67717e8a96a0acab9f94887c6f62544b4034281c100400000006131f2b37434e5866727f8c97a2adaa9e948a7d70695f574f46423b3935303433342e34383a40454b515b626d74818e97a1adab9e94897c6f62554b4035291d1004000000000006131f2c3845515c666f7c869299a4aea8a0979187817b75716d6869676766676768676d7073797e848e939fa4aca8a0969083786d60584e43372b20150a0000000000111e2a3744515d6a77838686868686868686868686868686868686868686868686868686868686868686868686868686868683766a5d5043372a1d10000000000003101c28343f4a54616b74818e949ea6aeafa7a09d95908b8783807c797673706d676764615e565754524c4746413a38322c272119130c0400000000000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d1000010e1a26313d4751595e5f6060606060606055544e463c32271b0f03000000000d1925303b4650585d5f6060606060606060606060606060606060606060606060606060605f5f5e5d5c5a585553504948443d39342b261f180f0800000000000000000000000000000000000000030c172029333b444c525a61676d71767a7e818284858686858483817e7b77716d67615a514b433b322920160b0200000000000000000714212d3a4754606d7a868686868686868073675a4d4034271a0d01000815222e3b4855616e7b868686868686867f7265584c3f3225190c000000000000131f2c3946525f6c798592939393939393939393939393939393939398929291918f8e8d8b8886837f7c78736e69615f57514c433e332d261d150c0300000000000000000000000000000000000000000000000000000000000000000000040d18242f39434f59606d798390999393939393877b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b6e67676767676767676767676767676767676767676767676767676767676767676361594f44382c2014070000000000000000010a141c262e363e444c52575e61666a6f7274767878797978787675726f6d66626058534e443f382f271e150c03000000000000000000000714212d3a46535f697683909da8a99d9083766c61554b40352e27222222262d3845515d676f7c7b797674726f6d675d5145392c2013060000000000000000000a141e28323a444c555c606b6f777d8185898c8e90919292929291908f8d8a86837e79726d665f574f473d352b20170d0000000000000000000714202d3946525e6876828f9ca8b2ab9e9185796d60574d41382d2417110a02000000000000000000000002091019222935404b55606c7884919dabb0a69a8e8174665c5145382c1f13060000000815222e3b4754606a7884919ea9b1a79c8f82756c61574d453d36302d292427272723282c2e343a4145515b606d7a85929eaab0a69b8e8275675d5145392c1f13060000000004111d2935414b55606d79839098a3aba9a09691857d746e6964615d565b5a5a5a5a555c6063666d7179818b939aa4afa89f958c80736a5f54473d32271b0f0100000000101d2936424f5b677177797979797979797979797979797979797979797979797979797979797979797979797979797979797671665b4e4236291c10000000000006121f2b3844505c66707d89939da6b0aca49f959089837f7b76736f6d666663605d555754524c4a4745413a3936302c27211b160d08020000000000000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d1000000915202b353f474e5253535353535353534947433c342b20150a000000000008141f2a343e464d5152535353535353535353535353535353535353535353535353535353535252514f4d4b4846443f3838332d28221a140e06000000000000000000000000000000000000000000050e172129323a414550555c6064686e7174767778797978787674716e6965605d555045403a312920170e040000000000000000000713202c3945525d687679797979797979736e64584c3f3326190d00000714212d3a46535f697679797979797979726d62564a3e3124180b000000000000131f2c3946525f6c798686868686868686868686868686868686868686858585848381807e7c7976736f6c65615e57534d45413a3127221b140b0300000000000000000000000000000000000000000000000000000000000000000000000007121d27313d45515c676f7c86868686868686867b6e6154483b2e211508000000000000000000121e2b3845515e6b7884919eabaea194887b737373737373737373737373737373737373737373737373737373737373737373706b6155483c2f231609000000000000000000020a131c242c323b41464d5254585f626568696b6c6c6c6c6b6a686663605c54544e4e4c4841382f1d150c03000000000000000000000005121e2a36424d5764717e8b96a1ab9f958a7d70675d51454039302f2e2f2f38404b55606d7986888583817e7c796d6054473a2d211407000000000000000000020c162029323a434b515960636b7075797c7f82838485868685858382807d7a76726d67605c544d453d352b23190e050000000000000000000814212e3b4754616e7a87939facafa3998c7f72675d51453b2f261b1206000000000000000000000000000000071018242f3944505b66727e8b99a3aeac9f9285796d6053463a2d2013080000000916222f3c4955626f7c8896a1acaca095897c6f625a50453b332a25201d191a1a1a181c1f23282f353f45515d67727f8b98a2aeac9f9286796d6053473a2d201406000000000613202c3945515d67737f8c95a0aaada19791847b706b615e5754524c4e4d4d4d4e4b5153545c60676d747f88939fa5afa79f92877c6f62584e43372b1d1207000000000e1a27333f4a555f676a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a665f554a3e32261a0d00000000000713202d3a4653606d7883909da5afafa49a938c837d77726e686663605c545653514b4a4746413e3a3935302d2a251e1b17151312100b0600010000000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100000040f19242d353d424546464646464646463c3b37322b22190f040000000000020d18222c343b4144464646464646464646464646464646464646464646464646464646464646454443413e3c3937332d2c27211d170e09030000000000000000000000000000000000000000000000050f1720282f353e434b5153565e616467696b6b6c6c6c6b696765615e5753514b433e352f281f170e050000000000000000000004111d2935414c565d6c6c6c6c6c6c6c6c67645c52473b2f23170b000005121e2b37424d575f6c6c6c6c6c6c6c6c65625b51463a2e221509000000000000121f2b3844515d6974797979797979797979797979797979797979797979787877767573716f6d666662605b53534d47423c352f281f17110a0200000000000000000000000000000000000000000000000000000000000000000000000000010b151f2834404b55606a6f797979797979797976695e53463a2d211407000000000000000000121e2b3845515e6b7884919eabb4a79a8e818080808080808080808080808080808080808080808080808080808080808080807d7063574a3d3024170a00000000000000000000020e1925303b444c525f6060606060605d5d5e5f5f5f5f5e5d5b596060606060605a58534a41362b2014080000000000000000000000020e1a26313b4653606d7984919ea7a79e9184796d605b514b423d3c3b3c3d424a515d67717e8b9892908e8b897e7164574b3e3124180b00000000000000000000050e172029313940454f54596063676d70727576787879797878777573706d6865605d55504a423c332b23191107000000000000000000030f1b27333f495364717e8b9aa4afac9f92867a6e61554b4033291d140a000000000000000000000000000000000007121d28333f4a54616d7a86929facaea298897d706356493d2f24190d0100000d1a2633404d596673808c99a8b2aa9d9083776a6054483e332a211a14110d080d070c1013181d242935414c55606d7985929fabaea2988a7d7164574a3e2e23170b000000000714212d3a4754606d7a85929fa7b0a69e92857b6e696059524d47464141404040414045464b51555d606d727f8b939ea9afa3998f82766a605447392f24180c000000000a16222e39434d555b5d606060606060606060606060606060606060606060606060606060606060606060606060606060605d5b554d43382d22160a0000000003101c28343f4a5464717e8a95a0acaea49f93888078706b65615e565653514a494745403d3a3936302d2c292424242b29262422201f1c1711110c0600000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d1000000008121b242b31363839393939393939392f2e2b27201910070000000000000006101a222a30353839393939393939393939393939393939393939393939393939393939393938373634322f2d2b27221b1c16110c060000000000000000000000000000000000000000000000000000050d161e242931394045474c5254575a5c5e5f5f5f5f5e5c5a5854524d474540393129241d160d050000000000000000000000010d19242f3a444c525f606060606060605a58524a40362b1f13070000020e1a26313c454d535560606060606060585651493f34291e1206000000000000101c2935414d5862696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a6968666462605c545653504946423b373129241e160d0600000000000000000000000000000000000000000000000000000000000000000000000000000000030d18232e39434e5860626c6c6c6c6c6c6c6c6c5e574d42362a1e1205000000000000000000121e2b3845515e6b7884919eabb7a99d938e8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8073665a4d4033271a0d0000000000000000000005111e2a36414c565e6c6c6c6c6c6c6c6a675f555353524f5960636c6c6c6c6c6c67645c53483c3024180b00000000000000000000000009141f2c3844515c66727f8b95a0aca1968e81756e605c544f4a4948494a4e545b606d7984919e9f9d9a92857a6d6053473a2d2014070000000000000000000000050e171f272f343d43484f54555c606366686a6b6c6c6c6c6b6a686664615e5653514b443f38302a211911080000000000000000000005121f2b3744505b6575818e9bacb6a99c8f8276685e5243392f21170b020000000000000000000000000000000000010b17222d3846525d6875828f9ca8b4aa9a8d807367564c4135291d11040005111e2a36424d576976838f9ca9b5ab998c7f7366584e43362c21180f0905010000000004070c1319242f3a45515d6774818e9aa7b4aa9b8e817468544a3f34281c1003000006131f2b37434e5866727f8c97a2adaa9e948a7d70695f574f46423b3935303433342e34383a40454b515b626d74818e97a1adab9e94897c6f62554b4035291d100400000006111c27313b434a4f5153535353535353535353535353535353535353535353535353535353535353535353535353535353504e4a433a31271c11050000000006121f2b3844505c6675828f9ca7b1aa9d928b7e736d66605954524d494644403d3a39352f2e2d2a252120282d3031383533312f2d2b28231c1d181109000000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100000000009121920262a2c2c2d2d2d2d2d2d2d22221f1b150f070000000000000000000810181f25292b2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2b2a29272522201f1b1711100b050000000000000000000000000000000000000000000000000000000000040c13191f272f34383b4146474b4e4f515253535251504e4b4846423b38352f271f18130c040000000000000000000000000008131e28323a414553535353535353534d4c4740382e24190e0200000009141f2a333c424648535353535353534c4a463f372d23180d010000000000000d1925303b4650585d5f606060606060606060606060606060606060605f5f5e5e5c5b5a585553514b4946443f3836312b261f19130c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d27303c464e54555f606060606060605f534d453b31251a0e02000000000000000000121e2b3845515e6b7884919eabb7afa59d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a998d8073665a4d4033271a0d000000000000000000000714202d3946525e68767979797979797771675b4f464854606b70797979797979746e64584c4033271a0d01000000000000000000000004101c2834404a54606d7883919aa4a89e938c80746d6660595755555556585f666c75818e96a1aca3998e8174675d5145392c201306000000000000000000000000050d151d232932383d44484b515356595b5d5e5f5f5f5f5e5d5c5a5754524c47454039342e261e180f0800000000000000000000000613202d394653606c7885929eabb3a9988b7f7265564c4131271d0f050000000000000000000000000000000000000006111c2935414c5665727f8b98aab4aa9d918477685d5245392c201306000714202d3a46525e697885929eabafa399897c6f6256493d32231a0f060000000000000000000108131e2935404b5564707d8a97a9b3aa9d908377665c5044382b1f120600000815222e3b4754606a7884919ea9b1a79c8f82756c61574d453d36302d292427272723282c2e343a4145515b606d7a85929eaab0a69b8e8275675d5145392c1f1306000000000b151f2931393f42444646464646464646464646464646464646464646464646464646464646464646464646464646464643423e3831281f150a00000000000713202d3a4653606d7985929facaea3988d80746c605c544f4746413c3a38342e2d2c292421201d19242c34393d3e4442403e3b3a38342e2e29231b12090000000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100000000000080f151a1d1f20202020202020201615130f0a040000000000000000000000060d14191c1f1f202020202020202020202020202020202020202020202020202020201f1f1e1c1a181513120f0b0600000000000000000000000000000000000000000000000000000000000000000001080d151d23292c3036393b3e414344454646454543413e3b3a36302c29241d150d07010000000000000000000000000000010c1620282f35394646464646464646403f3b362e261c120800000000030e18212a31373a3b464646464646463f3e3a342d251b11060000000000000008141f2a343e464d51525353535353535353535353535353535353535352525251504e4d4b494645403c3937332d2a251f1a150d080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151e2b343c43474953535353535353534846423b33291f140900000000000000000000121e2b3845515e6b7884919eabacacafa9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6998d8073665a4d4033271a0d000000000000000000000814212e3b4754616e7a86868686868683776a5d5144495663707d8686868686868074675a4e4134271b0e010000000000000000000000000c18232e3944515c66707d88939fa6a59c928c8079706b666462616263666a6f78808d939ea9a89f92877b6e62554b4035291d100400000000000000000000000000030b121821272c323839404546494c4f50515253535252504f4d4a4746413a39352f28231c150c060000000000000000000000000815222e3b4855616e7b8897a1adada197887b6e6255483b3022150b0000000000000000000000000000000000000000000d1924303c4855626f7b8898a2aeaca095877a6d6054473a2d211407000814212e3b4754616e7b8797a2adac9f92867a6d6053473a2d2014070000000000000000000000010d18242f3b4754616e7a8797a1adac9f9286796d6053463a2d20130700000916222f3c4955626f7c8896a1acaca095897c6f625a50453b332a25201d191a1a1a181c1f23282f353f45515d67727f8b98a2aeac9f9286796d6053473a2d20140600000000040d171f272e333637393939393939393939393939393939393939393939393939393939393939393939393939393939393736322d271f160d0300000000000815222f3b4855626e7b8898a2aeac9f92867a6d615a504a423d3936302d2c282320201d18141317222c363e45494b514f4d4a4846443f383a342d241b110600000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d1000000000000004090e1112131313131313131309080603000000000000000000000000000002080d10121313131313131313131313131313131313131313131313131313131313131211100e0b0906050300000000000000000000000000000000000000000000000000000000000000000000000000030b12181c1f252a2d2e3134363838393939383634322e2d2a251f1d18120b030000000000000000000000000000000000040d161e24292c393939393939393934332f2b241c140a010000000000060f181f262b2d2e3939393939393932312e29231b13090000000000000000020d18222c343b41444646464646464646464646464646464646464646464545444342403e3c3a38342e2d2b27221b1a140e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c19222b32373b3c46464646464646463b3a36312921170d0300000000000000000000121e2b3845515e6b7884919e9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f998d8073665a4d4033271a0d000000000000000000000814212e3b4754616e7a87939393939084776a5d5144495663707c89939393938d8174675a4e4134271b0e0100000000000000000000000007121c2834404a54606b73808d949fa7a49c928d837d7773706f6e6f7072767c828d929da5aaa1968d8174695f5343392f24180d01000000000000000000000000000001070c161b21272c2e34383a3d3f42434545464645454442403d3a3936302c29241d17110a03000000000000000000000000000a1724303d4a5763707d8a96a9b3ab9e928578695f53473a2e2114030000000000000000000000000000000000000000000813202d394653606c7985929facb1a795897c6f6256493c2f231609000916232f3c4956626f7c8995a9b3aa9e918477675d5145382c1f13060000000000000000000000000714202d3946525e687885919eabaea398887b6e6255483b2f22150800000d1a2633404d596673808c99a8b2aa9d9083776a6054483e332a211a14110d080d070c1013181d242935414c55606d7985929fabaea2988a7d7164574a3e2e23170b0000000000050d151c2227292a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2a2926221c150d040000000000000a1723303d4a5663707d8996aab4a89c8f8275685e52443f38302d2a25201f1c181413100d07111d28343e485055575e5c59575553504a4a453f362d23180c01000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000000000000000001040606060606060606060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c1014191e20212427292b2c2c2c2c2b29272521201e1a14100c070100000000000000000000000000000000000000040c13191d202d2d2d2d2d2d2d2d2726231f19120a0200000000000000060e141a1e21222d2d2d2d2d2d2d2524221e1811090100000000000000000006101a222a303538393939393939393939393939393939393939393939393837363533312f2d2c2823201f1b17110e09030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101920272b2e2f39393939393939392e2d2a251f170f050000000000000000000000121e2b3845515e6b7884919393939393939393939393939393939393939393939393939393939393939393939393939393938d8073665a4d4033271a0d000000000000000000000814212e3b4754616e7a87949f9f9d9084776a5d5144495663707c89969f9f9a8d8174675a4e4134271b0e01000000000000000000000000000c18232e39424f59606d788290959fa7a49d95908984807d7c7b7c7d7f838890949da4aaa39891847a6d61574d4231281d12070000000000000000000000000000000000040a0f161b1d23282c2d30333537383939393938373533312e2d2a251f1d18120c060000000000000000000000000000000c1926323f4c5965727f8c98a5b2a99c8f837669574d42372b1e120600000000000000000000000000000000000000000006121f2b3844505b667783909daab1a4978b7e7164584b3e3125180b000a1723303d4a5663707d8996a3b0a99c90837669554b4035291d100400000000000000000000000005111e2a36414c566a7683909da9b4aa96897c6f6356493c302316090005111e2a36424d576976838f9ca9b5ab998c7f7366584e43362c21180f0905010000000004070c1319242f3a45515d6774818e9aa7b4aa9b8e817468544a3f34281c10030000000000040b11161a1d1e202020202020202020202020202020202020202020202020202020202020202020202020202020201d1c1a16110a03000000000000000b1724313e4a5764717d8a97a4b0a6998d807366564c41342e26201e191312100c070604010815212d3945505a61646b68666462605c545651483f34291d1105000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100000000000000000000000000000000000000000000000000000000000000000000004090e1112131313131313131313060400000000000000000000000000000000000000000000000004080a0a1313131313131313130e0e0b080300000000000000000000000000000000000000000000000000000000000004080e111414181b1c1e1f20201f1e1d1b181514120e0904000000000000000000000000000000000000000000000001080d111314202020202020201a1917130e080100000000000000000003090e12141520202020202020191815120d060000000000000000000000000810181f25292b2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2b2b2928272522201f1c1813120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e151b1f22222c2d2d2d2d2d2d2d21211e1a140d05000000000000000000000000121e2b3845515e6b788486868686868686868686868686868686868686868686868686868686868686868686868686868686868073665a4d4033271a0d000000000000000000000814212e3b4754616e7a8794a1aa9d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e010000000000000000000000000007121c27303d44505c666d7a8390959da5a7a09d95918d8a888888898c90959c9fa6a9a19892867c6f685e52453c311f160c0100000000000000000000000000000000000000040b1012181c1f202326282a2b2c2c2c2c2b2a29272421201d1913100c0701000000000000000000000000000000000e1b2834414e5b6774818e9aa7b3a79a8d8074675a4d4131261a0e02000000000000000000000000000000000000000000030f1c28333f4a546875818e9ba8b3a6998d8073665a4d4033271a0d000b1724313e4a5764717d8a97a4b0a89b8f8275685c4f422f24180c00000000000000000000000000010d192530424f5c6875828f9ba8b0a3968a7d7063574a3d3024170a000714202d3a46525e697885929eabafa399897c6f6256493d32231a0f060000000000000000000108131e2935404b5564707d8a97a9b3aa9d908377665c5044382b1f120600000000000000060a0e10111313131313131313131313131313131313131313131313131313131313131313131313131313131310100d0a050000000000000000000b1724313e4a5764717d8a97a4b0a5998c7f7266594c3f30231c15110e080807070808090e131925303d4955616c71777573716e6d6665625b51453a2e221509000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000000000000000000000000000000000000000000000000000000000000000000080f151a1d1f20202020202020202013100c070100000000000000000000000000000000000000050b101416172020202020202020201b1a18140f0901000000000000000000000000000000000000000000000000000000000000020507080b0e10111213131212100e0b0807050200000000000000000000000000000000000000000000000000000001040707131313131313130d0d0b07020000000000000000000000000002050708131313131313130c0b0906010000000000000000000000000000060d14191c1f1f202020202020202020202020202020202020201f1f1f1e1d1b1a18161313100c0705030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f13151620202020202020201514120e090300000000000000000000000000111d2a3743505c6872787979797979797979797979797979797979797979797979797979797979797979797979797979797979736e63584b3f3226190c000000000000000000000814212e3b4754616e7a8794a1a99d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e0100000000000000000000000000000b151e28343f4a545d686d7a838e939ea0a8a8a09d999795949596999d9fa7aba49f9792867e706a60564c41332a1f0d040000000000000000000000000000000000000000000000070c10131316191c1d1e1f20201f1f1d1c1a171413110d080400000000000000000000000000000000000000101c2936434f5c6976828f9ca9b2a5998c7f7266594c3f3326190900000000000000000000000000000000000000000000000b17222d404d5a6773808d9aa6b3a89b8e8175685b4f4235281c0f000b1825313e4b5864717e8b97a4b1a89b8e8275685b4f4235281c070000000000000000000000000000081b2835414e5b6874818e9ba7b0a4978a7d7164574a3e3124170b000814212e3b4754616e7b8797a2adac9f92867a6d6053473a2d2014070000000000000000000000010d18242f3b4754616e7a8797a1adac9f9286796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724303d4a5763707d8a96abb5a69a8d807367544b403428201c1816151514141515171a1e242b37434e5864717e8482807d7b7977726d62564a3d3124170b000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000000000000000000000000000000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2d2d1f1c18120b0300000000000000000000000000000000000810171c2023242d2d2d2d2d2d2d2d2d282724201a130b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d1012131313131313131313131313131313131313131313121211100f0d0b090706040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030608091313131313131313080705020000000000000000000000000000000f1b27333f4b5660686b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c66635c52473b2f23170a000000000000000000000814212e3b4754616e7a87949c9c9c9084776a5d5144495663707c89969c9c9a8d8174675a4e4134271b0e010000000000000000000000000000030c17232e38424c565e686d79818991969d9fa4aca6a3a2a1a2a3a5a8a9a29f99938e857c706c61584e443a3021180e00000000000000000000000000000000000000000000000000000406070a0c0f10121213131212110f0d0a07070501000000000000000000000000000000000000000000101d2a3643505d697683909ca9b1a4978a7e7164574b3e3124180b0000000000000000000000000000000000000000000000061926323f4c5965727f8c98a5b2a89c8f8275695c4f4236291c0f000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2834414e5b6774818e9aa7b1a4978b7e7164584b3e3125180b000916232f3c4956626f7c8995a9b3aa9e918477675d5145382c1f13060000000000000000000000000714202d3946525e687885919eabaea398887b6e6255483b2f221508000000000000000000000000000000000000000000000105090b0b1313131313131313120706030000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8899a4afa89b8e8275665c51453a322c29232322212121212223252a2f353f47535f6a76828f8f8c8a8886837e7265584b3f3225180c000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100000000000000000000000000000000000000000000000000000000000000008121b242b3136383939393939393939392c29231d150d0300000000000000000000000000000008121a22282d30313939393939393939393533302b251d140b010000000000000000000000000000000000000000000000000000000003090d1012131313131313131313060300000000000000000000000000000000000000000000000000000000000000000004080c0e0f13131313131313131313131313131313131313131313131313131313131313131313131313130f0e0c080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232f3a444e565c5e60606060606060606060606060606060606060606060606060606060606060606060606060606060605a58524a40362a1f1307000000000000000000000814212e3b4754616e7a878f8f8f8f8f84776a5d5144495663707c898f8f8f8f8d8174675a4e4134271b0e0100000000000000000000000000000006111c26303a444c565e676d747d848a90939a9a9c9e9f9f9f9e9d9b9997928d87817a6f6a615a50463c32281e0f060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111e2a3744515d6a7783909daab0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4b1a99c908376695d5043362a1d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000a1723303d4a5663707d8996a3b0a99c90837669554b4035291d100400000000000000000000000005111e2a36414c566a7683909da9b4aa96897c6f6356493c30231609000000000000000000000000000000000000000000060c1115171820202020202020201f1312100c06000000000000000000000000000000000000000000000000000714202d3a4753606d7a86939facab9f9285796d60564c443d38342f2f2f2e2d2e2e2f3031363a4145515b626f7c87939b999798928a7e7164574b3e3124180b000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000000000000000000000000000000000000000000000000000000000000040f19242d353d424546464646464646464638342f271f150b010000000000000000000000000006101a242c33393c3d46464646464646464641403c362f261d1309000000000000000000000000000000000000000000000000000000070e14191d1f20202020202020202012100c06000000000000000000000000000000000000000000000000000000000002090f14181b1c20202020202020202020202020202020202020202020202020202020202020202020202020201c1b18140f0902000000000000000000000000000000000000000000000000000000040607090c0e1011121313131211100f0d0b0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000040607090c0e1011121313131211100e0b080705020000000000000000000000000000000000000000000000000007121d28323c444b505153535353535353535353535353535353535353535353535353535353535353535353535353535353534d4b4740382e24190e02000000000000000000000714212d3a4754606d7a8283838383838174675b4e414855626f7c8283838383827f7265584c3f3225190c00000000000000000000000000000000000a151e28323a444c555c606b70787e83878b8d909192929291908f8c8985817c746d68605850483e342b20160c000000000000000000000000000000000000000000000000000000000000000306060808080808080605030000000000000000000000000000000000000000000000000000111e2b3844515e6b7784919eaaafa396897c706356493d3023160a00000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1aa9d9083776a5d5044372a1d11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1724313e4a5764717d8a97a4b0a89b8f8275685c4f422f24180c00000000000000000000000000010d192530424f5c6875828f9ba8b0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000911171d2124252d2d2d2d2d2d2d2d2b201f1c17110a03000000000000000000000000000000000000000000000006131f2c3945515d677683909dabada2978a7e71685e564f4745403e3c3b3b3a3a3b3b3d3f42464c515a626d76828f99a4a6aa9f92857a6d6053473a2d201407000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100000000000000000000000000000000000000000000000000000000000000915202b353f474e5253535353535353535345403931271d1207000000000000000000000000050e18222c363e44494a5353535353535353534e4c4841392f251a0f03000000000000000000000000000000000000000000000000000811191f25292b2c2d2d2d2d2d2d2d2d1f1c17110a030000000000000000000000000000000000000000000000000000030c131a202527282d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d282725201a130c03000000000000000000000000000000000000000000000004070c10121316191b1d1e1f1f201f1f1e1d1b19171414110e0806030000000000000000000000000000000000000000000000000000000000000000000000000003070c10131416191b1d1e1f1f201f1f1e1c1a181514120e09050200000000000000000000000000000000000000000000010c16202a323a3f43454646464646464646464646464646464646464646464646464646464646464646464646464646464646403f3b362e261c120800000000000000000000000713202c3945525d686d767676767676746f64584c4047535f6a6f767676767676726d62564a3e3125180b0000000000000000000000000000000000030c162029323a434b515960666d71767b7e8183848586858484827f7d79746f6a615e564e463e362c22190e050000000000000000000000000000000000000000000000000000000000060b0f121314141414141413120f0b06000000000000000000000000000000000000000000000000121f2b3845525e6b7885919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0aa9e9184776b5e5144382b1e11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8275685b4f4235281c070000000000000000000000000000081b2835414e5b6874818e9ba7b0a4978a7d7164574a3e3124170b0000000000000000000000000000000000000009121b22292e31323939393939393939382d2c28231c150c030000000000000000000000000000000000000000000004101d2935404b5566737f8c99a3aea99e91857a6d68605953514b4b494848474748484a4b4d53555d606c727f8c949fabaea3998d8074675d5145392c201306000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d100000000000000000000000000000000000000000000000000000000000000e1a26313d4751595e5f606060606060605f514b43392f23180c0000000000000000000000030c17202a343e485055576060606060606060605b59534b41362b20140800000000000000000000000000000000000000000000000007111a232a3135383939393939393939392c28231c150c03000000000000000000000000000000000000000000000000020c151e252c31343539393939393939393939393939393939393939393939393939393939393939393939393939393534312c251e150c020000000000000000000000000000000000000001070c1013181c1f20232527292b2b2c2d2c2c2b2a28262421201e1915120f0a03000000000000000000000000000000000000000000000000000000000000000000060b1012181d1f202325282a2b2b2c2d2c2c2a29272521211e1a14110e0902000000000000000000000000000000000000000000050f1820282f333738393939393939393939393939393939393939393939393939393939393939393939393939393939393933322f2a241c140a00000000000000000000000004111d2935414c565d6069696969696967645c53483c434e585f6269696969696965625b51463a2e221609000000000000000000000000000000000000040d172029303940454f545c6064686e7174767878797878777573706d67625f58524c443d342c241a100700000000000000000000000000000000000000000000000000000000020a11171c1f20212121212121201f1b17110a0200000000000000000000000000000000000000000000121f2b3845525e6b7884919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0aa9d9184776a5e5144372b1e11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2834414e5b6774818e9aa7b1a4978b7e7164584b3e3125180b00000000000000000000000000000000000006111b242d343a3d3e4646464646464646453a38342e261e150a00000000000000000000000000000000000000000000000c18242f3b4754616e7a86929fa8ada19790827a6f6b63605c5557565554545454555658575e61676d747e88939fa6b0a89f92867b6e61554b4035291d1004000000101d293643505c6976838f8b7f7265584c3f3225190c00000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b8f8376695c504336291d10000000000000000000000000000000000000000000000000000000000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c5c554b4034291c1004000000000000000000000b151e29323c46505a61646c6c6c6c6c6c6c6c6c68645d53483c3024180b0000000000000000000000000000000000000000000000030e19232c353c414546464646464646464638342e261e150a00000000000000000000000000000000000000000000000009131e272f373d4042464646464646464646464646464646464646464646464646464646464646464646464646464642403d372f271e1309000000000000000000000000000000000003090e12181d1f23282c2d3032343638383939393838373533312e2d2a25211f1b150f0b060000000000000000000000000000000000000000000000000000000000020a11171c1f24292c2d30323437373839393938373634312e2d2a25201e19140e09020000000000000000000000000000000000000000060f161d23272a2b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2726231f19120a02000000000000000000000000010d1924303a444c52545c5c5c5c5c5c5b58534a41363c464e53555c5c5c5c5c5c585651493f34291e120600000000000000000000000000000000000000050e171e272e343d424a5053565e616567696b6c6c6c6b6a686663605c55534e46413a322b221a110800000000000000000000000000000000000000000000000000000000020b141c22282b2d2e2e2e2e2e2e2d2b27221b140b02000000000000000000000000000000000000000000111e2b3844515e6b7784919eaab0a396897d7063564a3d3023170a00000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a99d9083766a5d5043372a1d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000000000000000000010c17222d363f454a4b53535353535353535246443f3830261c1106000000000000000000000000000000000000000000000714202d3946525e6874808d96a1aaa99f9490847c76706d67666462626160616162636567696e737a818b939aa4afaaa1968d8074695e5343392f24180d01000000101d293643505c6976838f8b7f7265584c3f3225190c06060606060606060606060606060606060606060606060606060c1925323f4c5865727f8b8f8376695c504336291d10000000000000000000000000000000000000000000000000000000000000121f2c3845525e6a75797979797979797976675c5145382c1f130600000000000000000007121c27303a444e58616c70797979797979797979746f64594c4033271a0e010000000000000000000000000000000000000000000009141f2a353e474d51535353535353535353443f3830261c110600000000000000000000000000000000000000000000040f1a252f3941484d4f53535353535353535353535353535353535353535353535353535353535353535353535353534f4d4841392f251a0f04000000000000000000000000000001070c141a1d24292c2e34383a3c3f4143444546464645444342403e3b3936302e2b261f1c17110a020000000000000000000000000000000000000000000000000003090c141c23282b2f35383a3c3f41434445464646454443413e3b3a36312d2a251f1a140d050000000000000000000000000000000000000000050c12171b1d1e20202020202020202020202020202020202020202020202020202020202020202020202020202020201a1917130e0800000000000000000000000000000008131e28323a4145475050505050504e4c4841382f343c4347485050505050504c4a463f372d23180d010000000000000000000000000000000000000000050c151d232830383f44464d5254585a5d5e5f5f5f5e5d5c595653514b47433c3630292019100800000000000000000000000000000000000000000000000000000000000a141d262d3338393b3b3b3b3b3b3937332d261d140a000000000000000000000000000000000000000000111e2a3744515d6a7784909daab0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000c1825323f4b5865727e8b98a5b1a99c8f8276695c504336291d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000000000005111d29343f4850565860606060606060605e53504a42382e23170c0000000000000000000000000000000000000000000005111e2a36414c56606d7a849198a2aaa69f969189827d797573716f6e6e6d6d6e6e707274777b80858e939fa4acaba3989184796d60574d4231281d120700000000101d293643505c6976838f8b7f7265584c3f322519131313131313131313131313131313131313131313131313131313131925323f4c5865727f8b8f8376695c504336291d1000000000000000000104060606060606060606000000000000000000000013202c3946535f6c798786868686868686796d6053473a2d2014070000000000000000081118232e39424c565f6a707e8786868686868686868174685b4e4135281b0e02000000000000000000000000000000000000000000010d1925313c4750585e5f606060606060605f504a42382e23170c000000000000000000000000000000000000000000000814202c37414b53595b60606060606060606060606060606060606060606060606060606060606060606060606060605b59534b41372c20140800000000000000000000000000030b12181f252a2f35393a404446494c4e5051525253525251504e4c4a4746413c3a37312b28221c140b070000000000000000000000000000000000000000000000060d141a1e262e34383a404547494c4e50515252535252514f4d4b4846423b3a36302a251f170e07010000000000000000000000000000000000000001070b0f111213131313131313131313131313131313131313131313131313131313131313131313131313131313130d0c0a070200000000000000000000000000000000020c1620283035393a43434343434341403c362f262a32373b3c4343434343433f3e3a342d251b110700000000000000000000000000000000000000000000030b12181e262e34383b4146474b4e505152535251514f4c4a4645403937322a251e170e07000000000000000000000000000000000000000000000000000000000006111c262f383f444647474747474746443f382f261b11060000000000000000000000000000000000000000101d2a3643505d697683909ca9b1a5988b7e7265584b3f3225180700000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685c4f4235291c0f000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000000000000000000000000000915212e3a45505a62656c6c6c6c6c6c6c6c6b605c544a3f34281c1003000000000000000000000000000000000000000000020e1925303b45525d686f7c869298a0a8a8a09e948f8a8582807e7c7b7b7a7a7b7b7d7e8084878d92979da5afaaa29992867c6f675d51453b311f160c0100000000101d293643505c6976838f8b7f7265584c3f322520202020202020202020202020202020202020202020202020202020202025323f4c5865727f8b8f8376695c504336291d1000000000000004090e11121313131313131313090806030000000000000013202c3946535f6c7986929393939393867a6d6053473a2d20140700000000000000060f19232834404a545e686f7c86929a93939393968f82786d6053463a2d2013070000000000000000000000000000000000000000000004101d2935414d58626a6c6c6c6c6c6c6c6c6c5c544a3f34281c10030000000000000000000000000000000000000000000c1825313d48535d65686c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c68655d53483d3125180c000000000000000000000000060d151d24293136394045474a515356585a5c5e5e5f605f5f5e5d5b595754524c4847433c38332d261d18120b030000000000000000000000000000000000000000070f181f262a30383f44464b515356585b5d5e5e5f605f5f5d5c5a5854534d4746423b3630292018120b03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e161e24292c2d3636363636363433302b251d20262b2e2f36363636363632312e29231b130900000000000000000000000000000000000000000000000000070c151c23282c3036393b3e414345454645454442403d3a38342e2b262019130d050000000000000000000000000000000000000000000000000000000000000b17222d38424a505354545454545453504941382d22170b00000000000000000000000000000000000000000f1c2835424f5b6875818e9ba8b3a6998c807366594d402f23180c00000000000000000000000000000000000000000000010e1b2834414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000000000000000000000000000b1724313d4a56626c717979797979797979786d665c5044382c1f13080000000000000000000000000000000000000000000008141e2935414c56606a707d8691969fa3aba69f9c98928f8c8a89888787878788898b8d9195999fa2a9aba69f9892877e706a60554b4133291f0d040000000000101d293643505c6976838f8b7f7265584c3f322d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d323f4c5865727f8b8f8376695c504336291d100000000000080f151a1d1f20202020202020201615130f0a04000000000013202c3946535f6c7986929f9f9f9f93867a6d6053473a2d201407000000000000040d18212b353d44515c666d7a849198a29f9fa19791847a6d665c5144382c1f12060000000000000000000000000000000000000000000005121f2b3845515e6a74797979797979797976665c5044382c1f12060000000000000000000000000000000000000000000e1b2734404d59656f757979797979797979797979797979797979797979797979797979797979797979797979797979756f65594d4034271b0e00000000000000000000000910181f272f353b42464b5153545c60636567696b6b6c6c6c6b6b6a686664615e5655534e46443f382f28231d150c05000000000000000000000000000000000000081019212931363e424a5053555d606365676a6a6b6c6c6c6b6a696764615e5754524d46423b3329241d150d040000000000000000000000000000000000000000000000000000000000020608080b0e1011121313121211100d0b0807050200000000000000000000000000000000000000000000000000000000000000000000000000040c13191d2021292929292929282724201a13151b1f21222929292929292525221e181109010000000000000000000000000000000000000000000000000000030a11171c1f252a2d2e3234363839393938373533302d2c28231d1b150d0802000000000000000000000000000000000000000000000000000000000000030f1c28333f4a545b60616161616161605b53493f33271b0f03000000000000000000000000000000000000000d1a2734404d5a6773808d9aa6b3a89b8e817568554b4034291c100400000000000000000000000000000000000000000005121e2a36424d576976838f9ca9b2a5988c7f7265594c3f3226190c000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000000000000000005121e2a36424d5765717e868686868686868685786d6053463a3025190d01000000000000000000000000000000000000000000020d19242f3a434e58606b707c848d92999fa2aaaaa29f9c99979595949394949596989a9da0a8abaaa79f9d948f857d706c61584e433a2f21170d000000000000101d293643505c6976838f8b7f7265584c3f393939393939393939393939393939393939393939393939393939393939393939393f4c5865727f8b8f8376695c504336291d100000000009121920262a2c2c2d2d2d2d2d2d2d22221f1b150f070000000013202c3946535f6c7986929facaca093867a6d6053473a2d2014070000000000020b161f2a333d47515b606d78829096a1aaaea39992857b6e685d544a4034281c1004000000000000000000000000000000000000000000000613202c3946535f6c798686868686868686786d6053463a2d2013070000000000000000000000000000000000000000000f1c2835424f5b68758286868686868686868686868686868686868686868686868686868686868686868686868686868175685b4f4235281c0f0000000000000000000009121b222a313940454d53555d6065666d6f72747677787979797877767573716e6867625f5853504a423d342e271e170e050000000000000000000000000000000008111a222b333b424650545c6063676d6f727476777879797978777674716e6966615e56524d453f352f271f160d04000000000000000000000000000000000000000000000000000205090e121415181b1d1e1f20201f1f1e1c1a181514120e090502000000000000000000000000000000000000000000000000000000000000000000000002080d1113141d1d1d1d1d1d1b1a18140f080a0f1215151d1d1d1d1d1d191816120d07000000000000000000000000000000000000000000000000000000000000060c1014191e202125272a2b2c2c2c2b2a292623201f1c18120f0a04000000000000000000000000000000000000000000000000000000000000000006121f2b3844505b666c6e6e6e6e6e6e6c655b5044372b1f1205000000000000000000000000000000000000000c1925323f4c5865727f8b98abb5aa9d908477675c5145382c1f13060000000000000000000000000000000000000000000714212d3a46535f697885929fabb4aa968a7d7063574a3d3024170a000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000000000714212d3a46535e69768390939393939393978a7d7063564c4135291d11050000000000000000000000000000000000000000000008131e28313c464f59606a6f7980878e92989b9fa2aaa6a6a4a2a1a1a0a0a1a1a3a5a7a7aca49f9d9995908a827b706b615a50463d31281d0f05000000000000101d293643505c6976838f8b7f7265584c4646464646464646464646464646464646464646464646464646464646464646464646464c5865727f8b8f8376695c504336291d1000000008121b242b31363839393939393939392f2e2b272019100700000013202c3946535f6c7986929facada093867a6d6053473a2d20140700000000000a141d28313c454f59626d74818e949fa8aea49f92877d6f695f564c42392e23180c00000000000000000000000000000000000000000000000613202c3946535f6c798692939393939386796d6053463a2d2013070000000000000000000000000000000000000000000f1c2835424f5b6875828e9393939393939393939393939393939393939393939393939393939393939393939393938e8175685b4f4235281c0f00000000000000000009121b242c343c434b51575e61676d7175797c7f81838485858685858483817f7d7a77736f6a64605b544f454039302920170f050000000000000000000000000000060f1a232c343d454d535a61666d7075797c7f81838485858685858482807e7b77736e69615e575145403931281f160c030000000000000000000000000000000000000000000002080e11151a1e21222528292b2c2c2c2c2b2b29272522211e1a14120e09020000000000000000000000000000000000000000000000000000000000000000000000010407071010101010100e0d0b08030000030608091010101010100c0b09060100000000000000000000000000000000000000000000000000000000000000000003080e111414181b1d1e1f201f1e1e1c19171313100c0700000000000000000000000000000000000000000000000000000000000000000000000613202d394653606c787a7a7a7a7a7a776c605346392d20130600000000000000000000000000000000000000091623303c4956636f7c8999a4afac9f9286796d6053473a2d22170b0000000000000000000000000000000000000000000815222e3b4855616e7b8897a2adaea298887b6e6155483b2e221508000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000000000815212e3b4854616e7b87939f9f9f9f9fa99b8f8275685e5246392d20150a00000000000000000000000000000000000000000000010c161f2b343d474f585f676d737b81868b8f9298989a9b9d9e9f9f9f9f9f9f9e9d9c9a989a93908d88837d766e69615950483e342b1f160c00000000000000101d293643505c6976838f8b7f72655853535353535353535353535353535353535353535353535353535353535353535353535353535865727f8b8f8376695c504336291d100000040f19242d353d424546464646464646463c3b37322b22190f04000013202c3946535f6c7986929facada093867a6d6053473a2d2014070000000006111c262f3a434d57606b727f8b939da6afa59c928b7e716b60574d443a30271c120700000000000000000000000000000000000000000000000613202c3946535f6c7986929f9f9f9f9386796d6053463a2d2013070000000000000000000000000000000000000000000f1c2835424f5b6875828e9b9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9b8e8275685b4f4235281c0f000000000000000008121b242d363e464e555d60696e74797e8285898b8d8f91919293929291908e8c8a8784807c76716c666059514b433b332921170e05000000000000000000000000030d18212c353e464e575f616c70787d8185898b8e90919192939292908f8d8b87847f7b746e69625b514b433a31281e150b000000000000000000000000000000000000000002080d14191e20262b2e2f323436383939393938373634322e2d2b26201e1a140e090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507080b0e101212131212110f0d0a070604000000000000000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8787878787877a6d6154473a2e211407000000000000000000000000000000000000000714202d3a4753606d7a86939facaea399897d706353493f33271b0f030000000000000000000000000000000000000004111d2935414c5565717e8b98a9b3ac9f9285786d6053463a2d201307000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000000000000000000000007131f2c38434e5866737f8c9aa4afaca8aaac9f92867a6d6154473c32261b0f0000000000000000000000000000000000000000000000040d19222b353d464e555d60696e747a7e8285888b8d8f909192929292929291908f8d8c898683807c76706c615f574f473e362c22190d0400000000000000101d293643505c6976838f8b7f72656060606060606060606060606060606060606060606060606060606060606060606060606060606065727f8b8f8376695c504336291d1000000915202b353f474e5253535353535353534947433c342b20150a000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000071017222d38424c555f69707d87929fa5afa79e938d80736c61594f453c32281e150b0000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000f1c2835424f5b6875828e9ba8acacb2adaba5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a59b8e8275685b4f4235281c0f0000000000000006101a242d363f4850585f676d737b80858b8f9298989a9c9e9e9f9f9f9e9e9d9b999795908d88837e786f6b605c554d453b332920170c0300000000000000000000010b151f2a333e474f5860696e767d84898e9298989a9d9d9e9f9f9f9e9d9c9a9795918c86817b726d605d554b433a30271d1207000000000000000000000000000000000000040c13191f252a2d31373a3b3e41434445464645454443403e3b3a37312d2a251f1a140d05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010507070c0f0e0c0904000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8794949494877a6d6154473a2e211407000000000000000000000000000000000000000613202c3945515d677784909daab4ab9a8d8073655b5044372b1f140a000000000000000000000000000000000000010c13202c3945515d6775828e9ba8b5a89c8f8275665c5044382b1f1206000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000000000000000915222e3b4854606a7784919eaca49f9b9ea5a3998b7f7265584e43372b1c12070000000000000000000000000000000000000000000000071019232b343c434b51575f61676d7175797c7e80828384858586868585848482817f7d7a77736f6a64615a534d453e352c241a10070000000000000000101d293643505c6976838f8b7f726c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c727f8b8f8376695c504336291d1000010e1a26313d4751595e5f6060606060606055544e463c32271b0f030013202c3946535f6c7986929facada093867a6d6053473a2d2014070000050e192228333f4a545d676e7b859299a3afa89f958e81776c605a50473d332a20160c030000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000f1c2835424f5b6875818e9babb5b2a8a19e98989898989898989898989898989898989898989898989898989898988e8275685b4f4235281c0f000000000000030c18222c363f48505a616a6f7980868d92979c9fa2aaa7a9a8a7a6a6a6a7a8a9a8a6a7a09d9a94908a837c746d675e574d453b32291e150a0000000000000000000007121d27313c454f59616a6f7b828a91969b9fa2aaa7a7a5a3a2a2a3a4a5a8a7a7a09d99928e867f756d675d554b42392e23180c0300000000000000000000000000000000080e161e25293036393c4247484b4e50515253535252514f4d4b4846423c3a36302a251f170f0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d111314191c1b19150f090200000000000000000000000000000000000000030613131313131313130d0c0a07020000000000000000000000000003060809131313131313130b0b09050100000000000000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e2114070000000000000000000000000000000000000004101d2935404b556773808d9aa9b3ab9e9184786c6053463c2f261b1106000000000000000000000000000000000007131d28333f4a54606d7a86929facb1a7988b7f7265544a3f34281c1003000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000004101c2834404b54626f7c8996a0a49a938e939eab9d9083776a5f5347392e23180c000000000000000000000000000000000000000000000000071119222a313940454d53555d6065666d6f71737576777879797979787877757472706d6866625f58555046423b332c231a1208000000000000000000101d293643505c6976838f8b7f79797979797979797979797979797979797979797979797979797979797979797979797979797979797979797f8b8f8376695c504336291d100004111d2a36424e59636a6c6c6c6c6c6c6c6c6260584e43372b1f13060013202c3946535f6c7986929facada093867a6d6053473a2d20140700030d17202b343d44505b666d79839197a2abaaa1969083796d655b50483e352b21180e04000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000d1a2734404d5a6773808d99a3aeada196918b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8175685b4f4235281c0f0000000000000b151e2a343e48505a626c717c848c92989fa2a9aca8a8a09e9c9a9a999a9a9b9d9fa3ababaaa69f9c95908781796e695e574d443b30261c11060000000000000000000c18242f39434d57616b707c858f949ea0a8aca8a19e9a989695959697989c9fa2aaaba39f98928b81796d675d544b4034281e150b0000000000000000000000000000020a121a202830353b4146474e5355585b5c5e5f5f5f5f5e5e5c5a5855534d4846423b363029211a120a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f13191d202126292825201b140c0300000000000000000000000000000000060c101220202020202020201a1917130e0800000000000000000000040a0f13151620202020202020181715110c06000000000000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e21140700000000000000000000000000000000000000010d18242f3d495663707c8997a1adaca196897d7063584e41382d22170f06000000000000000000000000000000071118242f3844505b66717e8b98a2aeaca095887b6e6155483b2e23170b00000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000006131f2c3845515c6674818d9aa89f9388828e9baaa095887c6f62544a4034281c10040000000000000000000000000000000000000000000000000710181f282f353b42464c5154545c60626567686a6b6c6c6c6c6c6c6b6a69676563605d5655534e49443e36312a211a110800000000000000000000101d293643505c6976838f918b86868686868686868686868686868686868686868686868686868686868686868686868686868686868686868b918f8376695c504336291d100006121f2c3845525e6a757979797979797979766a6054473b2e2215080013202c3946535f6c7986929facada093867a6d6053473a2d201407010b151f29333d46505a606c78828f95a0a9aba29891847a6e675c53493f362d23190f0600000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000815212e3b4854616e7b86929faaab9e91847f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7d7063564a3d3023170a000000000007121d27303c46505a626c717e8691969fa2aaaba39f9b9796918f8e8d8d8d8d8f9092999a9ea1a9aba79f9a938d837b6e695e564c42382e23170c040000000000000004101d2935404b555f69707d8692979fa6aca69f9c96918e8b898988898a8c8f92989ea1a8aaa29f938f83796d665c51453d30271c1207000000000000000000000000020b141c242c323a41464d5254575f626567696b6c6c6c6c6b6a696765615f5754524d46423b332c241c140a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c10161b1e25292d2e333534312c251e150c0200000000000000000000000000030a11171c1f2d2d2d2d2d2d2d2d2726231f19120a0200000000000000070f161b1f22232d2d2d2d2d2d2d2524211d1811090000000000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e21140700000000000000000000000000000000000000000713202d3a4653606d7985929eacb2a89c8f82756a5f53493f332721180f0802000000000000000000000003091119232935404b55606c7884919daab3a99d908477695f53463a2d1c110600000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000000000000000000000713202d3a4653606d7985929eaa9d90837d8998a2a79a8d8074665c5144382c1f130800000000000000000000000000000000000000000000000000060d161d242931363a4145474a505355585a5c5d5e5f5f5f5f5f5f5e5d5c5a595654524c4847433c39332a261f180f080000000000000000000000101d293643505c6976828f9393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393938f8376695c504336291d10000613202c3946535f6c7987868686868686867c6f6255493c2f2216090013202c3946535f6c7986929facada093867a6d6053473a2d20140707121d27313b454e58616c73808d949ea7afa39992867c6f685e554b41382d241b11070000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000714212d3a46535e6974818e98a2ada196887c7272727272727272727272727272727272727272727272727272727272706b6054483c2f22160900000000000c18232e39424e58616c717f8a9298a0a8aba49f99928e8a8784828180808081828486898d92979ea1a8aca49f9590847b6e685e544a3f342820150a0000000000000006131f2c3845515d676e7b869298a1a9aaa29f948f8984817e7d7c7c7c7d7f82868b91969da4aea59e958f82786d60594f42392e23180c0000000000000000000000010b141d262e363e444c52565e61666a6e717476777879797878777673716e6966615e57524d453e362e261c140a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e12181d1f272b3035393a3f42413d3730271e1409000000000000000000000000030c151c23282c393939393939393933322f2a241c140a00000000000007101920272b2e2f3939393939393932312e29221b120900000000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e211407000000000000000000000000000000000000000006121f2c3844505c6673808d9aa4afaa9e94887c6f655b50443d332a2219140e09060400000100000406090e141a232b353d45515d67717e8a95a0acada2978b7e7265574d42362a1e0a0000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000000000005111d2935414c5664707d8a97a2a9998c807885929fab9e9285796d6053463a3025190d0100000000000000000000000000000000000000000000000000040c12181f262a2f35393a3f4446494b4d4f505152525353525251514f4e4c4a4745413c3b37322d28221a140e06000000000000000000000000101d293643505c69768286868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868376695c504336291d10000613202c3946535f6c7986929393939393887c6f6255493c2f2216090013202c3946535f6c7986929facada093867a6d6053473a2d2014071118242f39434d57606a717e8b929ca6aea49f92877d706a5f564c43392f261b1209000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000005121e2a36424d57616e7b86929fa8a89c8f82766c6565656565656565656565656565656565656565656565656565656360594f44382c2014070000000004101c2834404b545f6a717e87939fa2aaa9a199938e86827e7a777574737373747577797c80858b91969da5afa79f9691847a6e665c50443c32261b0f04000000000004111d2935414b55606d79839098a2aaa9a198928a827c787472706f6f70717275797e848d929fa4aba79f948d80746b60544a4034281c10040000000000000000000009131d262f38404850565e61686e73777b7e81838485868685858482807e7b77736e69615e57504840382e261c13090000000000000000000000000000000000000000000000000000000000000000000000000000000000060c10151a1d24292c32383a4146474c4f4d49423930251b0f0400000000000000000000000a151e262e34384646464646464646403f3b362e261c120800000000040f19222b32383b3c464646464646463e3d3a342d241b1106000000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e211407000000000000000000000000000000000000000003101c28343f4a54616e7b87939fabb0a69c9083776c60584e453c342a251e1a1312100c070e070c1013131a1f262a353d47505a606d7984919ea7b1a99f9285796d6053473b31261a0e0000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000713202d3946525e6875828f9ba9a197897c75828e9baba1978a7d7064564c41362a1e1105000000000000000000000000000000000000000000000000000001070d141a1e24292c2e34383a3c3e40424344454646464645454442413f3d3a3935302e2b26201c170e0903000000000000000000000000000f1c2935424e5a66707679797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797670665a4e4235291c0f000613202c3946535f6c7986929f9f9f9f95887c6f6255493c2f2216090013202c3946535f6c7986929facada093867a6d6053473a2d2014101a232935404b555e696f7c86929fa4aea69d928b7f726b61584e443b31271d140a00000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000020e1a25313b46525e6973808c96a0ac9f948b7e716a5f5658585858585858585858585858585858585858585858585856544f473d33271c10040000000006131f2c3845515c666f7c869299a4aea8a0979187817b75716d6869676766676768676d7073797e848e939fa4aca8a0969083786d60584e43372b20150a00000000000613202c3945515d67737f8c95a0aaaba19792867e766f6c6565636262636465676d7279808b9399a4afa69d92897d70665c5144382c1f150a00000000000000000007101b252f38404a525a61686d747b8084888b8e8f919292929291918f8d8b8884807b746e69615a524a40382e251b0f060000000000000000000000000000000000000000000000000000000000000000000000000002090e11171c1f262b2f35393d43474c5254595c59534b42372c2015090000000000000000000006111c2630383f4453535353535353534d4b4740382e24190e020000000a16202b343d434749535353535353534b4a453f362d22180c010000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e2114070000000000000000000000000000000000000000000c17232e3846535f6975828e99a3afab9f948b7f726a60574e463e36302a25201f1c181b1a1b181c1f20262b31363f474f59616c74808d96a1adada2978d8073675d5145392a1f14090000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000714212e3a4754616d7a86929fab9e928579717e8b99a3a99b8f8275685e5246392d20150a0000000000000000000000000000000000000000000000000000000003090e13191d2023282c2d2f32343537383939393939393837363432302d2c2924211f1b15100b050000000000000000000000000000000d1926323e49545e66696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c69665e54493e3226190d000613202c3946535f6c7986929facaca295887c6f6255493c2f2216090013202c3946535f6c7986929facada093867a6d6053473a2d201418222c353e45515d676e7b859198a3aea79e948d80746d62594f463c32291f150b0200000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000009141f2a36424d57606d7984919aa4a69f92867c6e685d554b4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4a48443d352b21160b0000000004111d2935414b55606d79839098a3aba9a09691857d746e6964615d565b5a5a5a5a555c6063666d7179818b939aa4afa89f958c80736a5f54473d32271b0f01000000000714212d3a4754606d7a85929fa7afa49992857c716c63605b535656555657555c60676d747f87939fa6aea49d9184796d6053463c31261b0f0300000000000000030c19222d37404a525c636c717a81868c9196989a9c9e9f9f9f9f9e9d9c9a9895918d86817b716c645c524a40372d21180e0300000000000000000000000000000000000000000000000000000000000000000001040b1014191c23282c3137394045474e54565e616668655d53493d3125190c000000000000000000000c17232e38424a505f606060606060605a58524a40362a1f13070000030f1b27323d464e545660606060606060585650483f34291d11050000000000000002050708080808080808080814212e3b4754616e7a8794a1a094877a6d6154473a2e21140808080808080808080705020000000000000000000006111c2a36424d57626e7b87929fa8b0a69f92877c6f695f585046413b36312d2c282327272723282c2d31373b42465159606b717e8a929da8b1a79f92857a6d61554b4035291d10040000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000000000000000006121e2b37424d5765727f8b99a3ab9b8e81756d7a86929fac9f92867a6d6154473c32271b0f00000000000000000000000000000000000000000000000000000000000001080d1113171c1f20222527292a2b2c2c2c2c2c2c2b2a2927262321201d1915120f0a0400000000000000000000000000000000000a16212d38424c545a5c60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605c5a544c42382d21160a000613202c3946535f6c7986929facaca295887c6f6255493c2f2216090013202c3946535f6c7986929facada093867a6d6053473a2d2016202a343e47515b606d79839097a1aaa9a0958f82786d605b51473d342a20170d030000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000030e1a25303b45515d67707d88939fa6a29891847a6d675c544b423f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3d3c38332b231a0f05000000000613202c3945515d67737f8c95a0aaada19791847b706b615e5754524c4e4d4d4d4e4b5153545c60676d747f88939fa5afa79f92877c6f62584e43372b1d120700000005111e2a36424d5766727f8c97a2adaa9f93877d706a615a5350494a4949494a4b51555c606d73808c949fabaca0958b7e7164584e43372b1f1206000000000000000a151e2b343f49525c646e737e858d92999da0a8a9a29f9d9c9b9c9d9fa2aaa7a09d99928e857e736e645c52493f332a1f14090000000000000000000000000000000000000000000000000000000000000001080d11161c1f252a2e34383c42474b5153586062686d72756f65594d4134281b0e00000000000000000003101c28343f4a545c6c6c6c6c6c6c6c6c66635c52473b2f23170a000006131f2b38434e5860626c6c6c6c6c6c6c65625a50453a2e211509000000000002090e121415151515151515151515212e3b4754616e7a8794a1a094877a6d6154473a2e211515151515151515151514120e09020000000000000000000e1a26313b47535f6974808d96a0abaea39991857b6e6a615a524c46423c3a38342e3434342e34383a3c42474d535b626b707d86929fa4aeaaa0958b7f72685e5243392f24180d010000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000000000814212e3a47535f697683909daba3998a7e716875828f9caba3998c7f7265584e43372b1d1207000000000000000000000000000000000000000000000000000000000000000104060c10121316181a1c1d1e1f1f20201f1f1e1e1c1b19171413110d0806030000000000000000000000000000000000000005101c26313a42494e505353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353504e49423a31261c1005000613202c3946535f6c7986929f9f9f9f95887c6f6255493c2f2216090013202c3946535f6c7986929facada093867a6d6053473a2d201e28323c464f59636d75818e959fa9aaa1979083796d665c50493f352c22180e05000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000009141f2935404b55606b73808d949fa8a0968f82796d665c544b433a323232323232323232323232323232323232302f2c27211a110800000000000714212d3a4754606d7a85929fa7b0a69e92857b6e696059524d47464141404040414045464b51555d606d727f8b939ea9afa3998f82766a605447392f24180c0000000714202d3a46525e697784909da9a8a2988d80746b60585046443f3d3c3c3d3e40454b515b606d7882909ca6b0a89d9083776a5f53473a2e21150600000000000006111c26303d46515b646e74808a92979fa3a9a19e999792908f8f8f909298989d9fa7a39f97928a80736e635b51453b31261a0e0400000000000000000000000000000000000000000000000000000000040a0f13191d20272c3036383f44464e53555d60656a6f747a7f8175685c4f4235291c0f00000000000000000006121f2c3844505c667679797979797979736e63584b3f3226190c00000815222e3b4754606a6f79797979797979716c62564a3d3124170b00000000050d141a1e2021212121212121212121212e3b4754616e7a8794a1a094877a6d6154473a2e2121212121212121212121201e1a140d05000000000000000009141f2b37424d57606d79849199a4afaba19791847c706c615e56534d494644404141414141404546494d53575f616d727d869298a2aeaca2989083786c60564c4131281d1207000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000000030f1b27333f4953626e7b88959fac9f92867a6d64717e8b99a3ab9d9083776a605447392e23180c0000000000000000000000000000000000000000000000000000000000000000000000030607090b0d0f101112131313131212110f0e0c0a0707040100000000000000000000000000000000000000000000000a151f2831383e4243464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464643423e3831281f150a00000613202c3946535f6c7986929393939393887c6f6255493c2f2216090013202c3946535f6c7986929facada093867a6d6053473a2d2026303a444e58616b727f8c939ea7aca29891857b6e675d544a3f372d231a100600000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000020c18242f39434f59606d78829096a0a89f948f82786d665d554c443b332b2525252525252525252525252525252322201c160f08000000000006131f2b37434e5866727f8c97a2adaa9e948a7d70695f574f46423b3935303433342e34383a40454b515b626d74818e97a1adab9e94897c6f62554b4035291d100400000814212e3b4754616e7b8795989a9b9c92857a6d61594f463e37332d2f2f302e34394045505c666f7c88949fabaca095887b6f6255483c2d22170b0000000000000c17232e38424f59626d74808d929ea1a9a39f97918c8885838282838385888b90959ea1a8a29f928d80736d62574d42362a20160a0000000000000000000000000000000000000000000000000001070c10151b1e24292c33383b42464a5053575f62676d71777c81868c83776a5d5144372a1e110000000000000000000713202d3a4653606d78868686868686868073665a4d4033271a0d00000916232f3c4956626f7c868686868686867e7165584b3e3225180b000000050f171f252a2d2e2e2e2e2e2e2e2e2e2e2e2e3b4754616e7a8794a1a094877a6d6154473a2e2e2e2e2e2e2e2e2e2e2e2e2d2a251f170f0500000000000000030e1a26313c45515d676f7d87939fa4aea9a19691867e756e68615e575653514a4e4e4d4e4e4b515356575f62696e767f879298a2aaafa49a92867c6f665b50443a301f160c01000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000005121f2b3744505b6573808d99a7ac9c8f837668606d7a86929faca095887c6f62554b4034281c100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d161f262d32353639393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393635322d261f160d0300000613202c3946535f6c7987868686868686867c6f6255493c2f2216090013202c3946535f6c7986929facada093867a6d6053473a2d232e38424c565f6a707d87939fa5afa49a92867c6f695e554b42382e251b11080000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000000007121d27313d44505c666d7a849197a1a69e948f81786d675d564d453d3528231c141919191919191919191919171614100b050000000000000815222e3b4754606a7884919ea9b1a79c8f82756c61574d453d36302d292427272723282c2e343a4145515b606d7a85929eaab0a69b8e8275675d5145392c1f130600000b1825323e4b5865717e888a8b8d8e908e8174685e52473d342b272223222323282f343f4a545f6a76828f9cacb1a7998c7f736653493f33271b0f030000000003101c28343f4a54606b727f8c929ca4aaa299928c84807b787675757677797b7f838a91969fa6a49c928b7f72695f53463d32271b0f030000000000000000000000000000000000000000000003090e12181c1f262b2f35393d44484d52545c60646a6e74797e83898e929084776a5d5144372a1e110000000000000000000713202d3a4653606d798693939393938d8073665a4d4033271a0d00000916232f3c4956626f7c8993939393938b7e7165584b3e3225180b0000020d17212930363a3b3b3b3b3b3b3b3b3b3b3b3b3b4754616e7a8794a1a094877a6d6154473b3b3b3b3b3b3b3b3b3b3b3b3b3a36302921170d020000000000000009151f2935404b55606b727f8b929da4ada9a198928a817a746e696562605c545b5a5a5a5b545c606266696e747b828b9299a2aaaea39f93887e706a5f544a3f32291e0d0400000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000000000000000613202d394653606c7884919eaba49a8b7f72655d6875828f9caaa79a8d8074675c5145382c1f14080000000000000000000000000000000000020507080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b0906010000000000000000040d151c212629292d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d292926211c150d0400000006121f2c3845525e6a757979797979797979766a6054473b2e2215080013202c3946535f6c7986929facada093867a6d6053473a2d28343f4a545e686f7c869299a4afa59f93887e706a60574d433a30261c1309000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000010b151f28343f4a545e686e7b859298a2a69e938f82796d685f574f473e342e261e160d0c0c0c0c0c0c0c0c0c0a09070400000000000000000916222f3c4955626f7c8896a1acaca095897c6f625a50453b332a25201d191a1a1a181c1f23282f353f45515d67727f8b98a2aeac9f9286796d6053473a2d20140600000714212d3a4754606d797c7d7f808183847d7063564c41352b221b17161616181d232e38424e5864717d8a9aa4afa99c8f8276655b5044372b1f12050000000006121f2c3844505c666f7c87929fa4aba29892878079736f6a6a696869656c6e72777d848f949fa6a49f92867b6e61584e43382b1f13060000000000000000000000000000000000000000060b0f141a1d23292c32373a4145474f54565e61666d71767b80858b90959b9d9084776a5d5144372a1e110000000000000000000713202d3a4653606d7986939f9f9f998d8073665a4d4033271a0d00000916232f3c4956626f7c89959f9f9f988b7e7165584b3e3225180b000009141f29333b4246484848484848484848484848484854616e7a8794a1a094877a6d6154484848484848484848484848484846423b33291f140900000000000000030d18242f3a434f59626d74808d929ca3adaaa29f938e86807b76726f6d6669686767676869666d6f72777b81868f949fa3ababa39f918c7f726c61584e42382d20170d0000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000004101d2935404b5563707d8996a1ac9f93877b6e615664717e8a98a2ab9e9285796d6053463b3025190e02000000000000000000000000000003090e12141519191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191816120d070000000000000000030a1016191c1d20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201d1c1916100a030000000004111d2a36424e59636a6c6c6c6c6c6c6c6c6260584e43372b1f13060013202c3946535f6c7986929facada093867a6d6053473a2d353d44505c666d7a849198a2aba69d938c7f726c61584e453b31281e140a01000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000030d17232e38424c565f696f7c869299a3a59e948f827a6e69605950443f38302820180f07000000000000000000000000000000000000000d1a2633404d596673808c99a8b2aa9d9083776a6054483e332a211a14110d080d070c1013181d242935414c55606d7985929fabaea2988a7d7164574a3e2e23170b00000613202c3945515d676d6f707273757678706b6054443a30231a0f0b0609070c121c26303c4754616d7a86939facab9f9285796c605346392d20130600000003101c28343f4a54606d78839099a3afa39992867d736d67625f585c5c535b6061656c707a828f949fa9a2988f82766a6054473b2e221508000000000000000000000000000000000002080d11171c1f262a2f34383c43474c5254596063696e73797d82888d92979da0a79d9084776a5d5144372a1e110000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2aca4988b7e7165584b3e3225180b00020e1a25303b454d52545454545454545454545454545454616e7a8794a1a094877a6d61545454545454545454545454545454524d453b30251a0e020000000000000007131d28313d47515b606c77808c919ea1a9aea59e98928d87837f7c79777674747474747677797c7f83888e92999fa6aea8a199928b7f736d635a50463c2f261c0e050000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000006131f2c3945515d6774818e9ba8ab9c908376695e53606d7a86929faca2978a7d7164564d41362a1e110500000000000000000000000000060d141a1e2122262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262525221e181109010000000000000000050a0d0f101313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313100f0d0a05000000000000010e1a26313d4751595e5f6060606060606055544e463c32271b0f030013202c3946535f6c7986929facada093867a6d6053473f383d47515b606d78828f96a0aaa89f948e81746d635a50463c33291f160c0200000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000006111c26303a444d57606a707d879298a2a69e9490847b6f6b625a504a423a322a21191106000000000000000000000000000000000005111e2a36424d576976838f9ca9b5ab998c7f7366584e43362c21180f0905010000000004070c1319242f3a45515d6774818e9aa7b4aa9b8e817468544a3f34281c10030004111d2935414c555d606264656768696b6360594f4432291e110800000000010a14202d3946525e687784919daaaea298877a6e6154473b2e21140800000006121f2c3844505c66727f8b95a0aba89f92877d706b605d55534e4f4f495053555a61686d79829097a1a49f94897c6f6256493c2f231609000000000000000000000000000001040a0f13191c22282b3136394045474e53565d60656b70757b80848a8f949a9fa2a7a09d979083776a5d5144372a1e110000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0005121e2a36424d575e616161616161616161616161616161616e7a8794a1a094877a6d616161616161616161616161616161615e574d42362a1e120500000000000000010c161f2b353f44505b656c747f8a92979ea6acaaa29f9a93908c898684828181808181828486898c90959a9fa3ababa49f9691877e736d635b51473e342a1d140a000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000714202d3a4753606d7985929faba3998b7f726557515d6775818e9ba9a99c8f8275685e5246392d20160a000000000000000000000000060f181f262a2d2e3232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232312e29231b13090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915202b353f474e5253535353535353534947433c342b20150a000013202c3946535f6c7986929facada093867a6d6059504a42454f59626d74808d949fa8a9a0968f82786d605b51483e342b21170d040000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000a151e29323c454e58616b707d869298a2a69f9691857d716c605c544c443c332b2317110a020000000000000000000000000000000714202d3a46525e697885929eabafa399897c6f6256493d32231a0f060000000000000000000108131e2935404b5564707d8a97a9b3aa9d908377665c5044382b1f120600010d19242f3a434c51545557585a5b5d5e56544f473d3320170d00000000000005111d2a36414c566875828e9ba8b3aa95897c6f6256493c2f2316090000000713202d3a4653606d7984919ea7ada1968d80736b6059514b474342423f44464850565d676d7a85929b9993908c8275685c4f4235291c0f02000000000000000000000001070d11161b1e252a2d33383b42464b5153585f62686d72777d82868c91969c9fa6a39f9b95908b857f7366594c403326190d0000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000714202d3a46525e696e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e7a8794a1a094877a6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e695e52463a2d2014070000000000000000040d192327333f49535b606d737d858f949da0a7acaca49f9c989892918f8e8d8d8d8e8f919298999d9fa7acaca69f99938d847d716c635b51493f352c22180b02000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000000000005111e2a36414d5664717e8a98a2ac9f92867a6e61544b5563707d8a97a1ac9f92867b6e6154473d32271b0f0100000000000000000000030d18212931363a3b3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3e3a342d251b110700000000000000000000000000000000000000000000000000000000050a0d0f101313131313130f0f0d0904000000000000000000000000000000000000000000000000000000000000040f19242d353d424546464646464646463c3b37322b22190f04000013202c3946535f6c7986929facaea194887b706b605b544c4d57606b727f8b929da6aba19791847a6d665c51493f362c22190f05000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000030c17202a333d464f59616b707d869298a1a8a09792877e746d665d564d453d3527221b140b0300000000000000000000000000000814212e3b4754616e7b8797a2adac9f92867a6d6053473a2d2014070000000000000000000000010d18242f3b4754616e7a8797a1adac9f9286796d6053463a2d201307000008131e28313a414547494a4c4d4e50514948443d352b210e05000000000000010d192530414e5b6774818e9aa7b0a3968a7d7063574a3d3024170a000004101d2935404b5564717d8a96a1acaa9e9184796d60594f45403937312d3337393e444c555e68717e8b8e8a86837f7c6f6255483c2f22150900000000000000000000040a0f13181d20272c3036383f44464d53555c60646a6f747a7f84898f92999ea1a9a19e99928e89837e79736d63574b3e3225180c0000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000815212e3b4854616e7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7c8995a2a295887c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e6154483b2e211508000000000000000000071017222d384149505b636b707b828990959c9fa4acaca9aaa39f9d9c9b9a9a9a9b9c9d9fa3aaaaababa39f9b948f878079706b625a514940372e231a100600000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000714202d3946525e6876828f9caaab9c8f8276685e524653606d7985929eaba3998c7f7266584e43372b1d12070000000000000000000009141f29333b4246484c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4a463f372d23180d0100000000000000000000000000000000000000000000000000030a11161a1c1d2020202020201c1b1915100902000000000000000000000000000000000000000000000000000000000008121b242b31363839393939393939392f2e2b272019100700000013202c3946535f6c7986929facb8ab9e92857d736c665e56555f69707d87929fa4aea39992857b6e685d544a40372e241a100700000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000050e18212b343e474f59616b707d8691969fa7a199928b80786d685f574f473f332d261d150c03000000000000000000000000000916232f3c4956626f7c8995a9b3aa9e918477675d5145382c1f13060000000000000000000000000714202d3946525e687885919eabaea398887b6e6255483b2f2215080000010c161f282f35393a3c3d3f404243453d3b38332b23190f0000000000000000081a2733404d5a6673808d99a6b0a4978a7d7164574a3e3124170b00000613202c3945515d6775828f9ba8aea3988b7e71675d51473d352f2b2622272b2d323a434c56606d7883817e7a76736f6a5f53473b2e2115080000000000000000070c10151b1d24292c32383a41464a5053575f61676d71767c81868b91959b9fa3a69f9c96918c86817c77716d67635b51463b2f22160a0000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00121f2b3845525e6b788487878787878787878787878787878787898e99a4a4988e888787878787878787878787878787878784786b5e5245382b1f120000000000000000000006111b262f383f44515961696e757d83898f939a9c9fa2aaa7a8aaa9a7a7a7a7a7a9a9a8a6a9a29e9b99928e88827c746d676059504840372e251c11080000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000814212e3b4754616e7b86929faca3998b7e7165564c44515c6674818d9aa8ab9d9184776a605447392f23180c000000000000000000020e1a26313b454d535559595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959585651493f34291e1206000000000000000000000000000000000000000000000000040d151c2226292a2d2d2d2d2d2d292825211b140c03000000000000000000000000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2d22221f1b150f070000000013202c3946535f6c7986929facb9ada197928780786d68605d676e7b859299a3aea49f92877d6f695f564c42392e251c12080000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000060f19222c353e474f59606b6f7c8490959ea5a39f928d827a6e69605950443f382f271e150d040000000000000000000000000a1723303d4a5663707d8996a3b0a99c90837669554b4035291d100400000000000000000000000005111e2a36414c566a7683909da9b4aa96897c6f6356493c30231609000000040d161e24292c2d2f313234353638302f2c272119110700000000000000000d1a2633404d596673808c99a6b1a4978a7e7164574b3e3124180b00000714202d3a4753606d7a86929facac9f92867a6d60554b403529241d1a171b1f2028313a44515c666d7775716d6866625f584e43372b1f1206000000000000030b12181c1f262b2f35393d43484c52545b6063696e73797e83888e92989da0a8a29f9a94908a847f7a756f6b65605d55514940352a1e12060000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00121f2b3845525e6b7885919494949494949494949494949494949599a0aaaaa098959494949494949494949494949494949184786b5e5245382b1f1200000000000000000000000a141d262d3340474f575e616b70777d82878b8f9298989a9b9d9e9e9f9f9f9e9d9d9b999797928e8a86817c766f6a605d554f473e362e251c130a000000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000006131f2b37434e5865727f8c99a3ac9f92867a6d615447404a54636f7c8996a1aca095897c6f62554b4034291c1004000000000000000005121e2a36424d575f616565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565625b51463a2e2216090000000000000000000000000000000000000000000000030d161f272d3235363939393939393635312c261e150c020000000000000000000000000000000000000000000000000000000000080f151a1d1f20202020202020201615130f0a04000000000013202c3946535f6c7986929facb9b3a9a199938c827a6f6a656d79839097a1aba59c928b7e716b60574d443a30271c130a000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000007101a232c353e474f59606a6f7a838f939fa4a49d948f847b706b625a5049413930271f160d0400000000000000000000000b1724313e4a5764717d8a97a4b0a89b8f8275685c4f422f24180c00000000000000000000000000010d192530424f5c6875828f9ba8b0a3968a7d7063574a3d3024170a00000000040c13191d202122242527282a2b252423211c170d0801000000000000000e1b2734414e5a6774818d9aa7b0a4978a7d7164574a3e3124170b00000a1723303d4a5663707d8998a3aea89b8e8275675d51433a2f23181d1d1d1d1d161f2834404a545c606a6864615e5655534e463c32261b0f030000000000030c151c23282c31373a4045474f54565e61666c70767b80858b90959a9fa2a8a09e98928e88837e79736e6863605953514b4340372e23190d020000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00121f2b3845525e6b7885919ea1a1a1a1a1a1a1a1a1a1a1a1a1a1a2a4aab2b2aaa4a2a1a1a1a1a1a1a1a1a1a1a1a1a1a19e9185786b5e5245382b1f120000000000000000000000020b141b2227353e454d525960636b70757b7e8285888b8d8f9091929292929191908e8c8a8885817e7a746f6a626058514b433d352d241c130a01000000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000000000815212e3b47535f6a7783909dabaa9c8f8275685e5246394653606c7884919eaba89a8d8174675c5145382c1f140900000000000000000714212d3a46535f696e72727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272726d62564a3e3125180b00000000000000000000000000000000000000000000000a151f2831383e424346464646464642413d3730271e140900000000000000000000000000000000000000000000000000000000000004090e11121313131313131313090806030000000000000013202c3946535f6c7986929facb9bab2aba49f948f847c726c77818f95a0a9a79e938c80736c61594f453c32281e150b01000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000008111a232c353d474f585f686e79818c939aa2a69f9691857d716c605b534a423931281f160d04000000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8275685b4f4235281c070000000000000000000000000000081b2835414e5b6874818e9ba7b0a4978a7d7164574a3e3124170b000000000008121a22282d303132323232323231302d282219130c04000000000006121e2b37424d576875828f9ba8b4aa96897d7063564a3d3023170a00000d1a2733404d5a6673808d99aab4aa978b7e7164554c4131282a2a2a2a2a2a2a2a2a232e39424a51535d5b5754524c4847433c342a20150a0000000000000b151e272e34383c43474b5153596063686d72787d82878d92979d9fa7a49f9c96918b86817c76716d66615e56544f47454039312e251c1207000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00121f2b3845525e6b7885919e9f9f9f9f9f9f9f9f9f9f9f9f9f9fa1a3a8b0b0a8a3a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9e9185786b5e5245382b1f12000000000000000000000000020a1117232c333b42464f54596063696e7276797c7e808283848585868585848382807d7b7975716d68625f58544e45403a312b231b120a0100000000000000000000000b1825313e4b5864717e8b97a4aca89b8e8175685b4e4235281b0f08040000000000000000000003050e1b2734414e5a6774818d9aa7aca4978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000003101c28343f4a54626f7c8895a0aca3988b7e7164564c413744505b6573808d9aa7ab9f9285796d6053473b30251a0e02000000000000000815222e3b4855616e7b7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7265584c3f3225190c0000000000000000000000000000000000000000000005111c27313a434a4e505353535353534f4d49423930261b1004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facb9b2a8a09da09f9691877f76808c939ea7a89f958e81776c605a50473d332a20160c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000008111a232b353d464e565e676d7780889298a0a8a09792877e736c655c544b433a31281f160c030000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2834414e5b6774818e9aa7b1a4978b7e7164584b3e3125180b0000000005101a242c33393c3e3f3f3f3f3f3f3e3c393329241e16100c0709060b1117232d3a47535f697884919eabaea398887b6e6155483b2e2215080004101c2834404b546976828f9ca9aea398887b6f6255483c2f3737373737373737373737373039404446514e4b4746413c3b37322a261f180f060000000007121c2730394044464e53555d60656b6f757a7f848a8f939a9ea1a9a29e99938f89847f7a746f6a64605c54524c48433d39352f271f1c130a00000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00121f2b3845525e6b78849193939393939393939393939393939394979ea8a89e97949393939393939393939393939393939185786b5e5245382b1f12000000000000000000000000000006111a202930363d44484f54565e6165666d6f7174757778787979787877767573716f6d6664605d56534e47433d352f281f191109000000000000000000000000000b1825313e4b5864717e8b979f9f9f9b8e8175685b4e4235281b1614100b05000000000000060b0f12131b2734414e5a6774818d9a9f9f9f978b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000000000006121f2b3844505c6673808d9aa7ac9f92867a6d6054473a333f4953626f7c8895a0aca2978a7e7164574d42362a1e1205000000000000000a1724303d4a5763707d8a8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c86796c5f5346392c2013000000000000000000000000000000000000000000000a16222d38434c545a5d6060606060605c5a544c42372c2115090000000000000000000000000000000000000000000000000000000105090b0b13131313070604000000000000000000000000000013202c3946535f6c7986929facb9aca0969196a0a199928c838c929ca5aaa1969083796d655b50483e352b21180e040000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000081119232b343c444d555d656c737e8691969fa6a299928b80776d665d554b433a31281e150a0000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000b17222c363e44494a4b4b4b4b4b4b4a49453e352f281f1c18171616171b222935404b55616e7b8896a1acac9f9286796d6053463a2d2013070006131f2c3845515c667884919eabac9f9286796d6053464444444444444444444444444444444444444444444444444444443b3a36312a21180e030000000c18232e39424a5153585f62676d72777c81868c91969c9fa4a7a09d97928d87827d78726d68625f5853504a46413b38322c29241d150d0a0100000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00121f2b3845525e6b788486868686868686868686868686868686878c97a3a3978c878686868686868686868686868686868684786b5e5245382b1f12000000000000000000000000000000080e171f2f3a454f575c5e60605f545c60626567686a6b6b6c6c6c6b6a6a68666462605c5454524c47433c383229241d160d0700000000000000000000000000000b1825313e4b5864717e8b93939393938e8175685b4e42352b2423201c170e09030000020a11171b1f20252c34414e5a6774818d93939393938b7e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000000000713202d3a4653606d7985919eabaa9b8f8275675d5145392d3847535f6a7784909daaa99c8f8276695e52463a2d20160a000000000000000a1724303d4a5763707d8a96989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989286796c5f5346392c2013000000000000000000000000000000000000000000010d1a26323e4a545e66696c6c6c6c6c6c69655e54493d3125190d0000000000000000000000000000000000000000000000000000060c111517182020201f1413100c0701000000000000000000000013202c3946535f6c7986929facb7aa9d91849196a0a39f9490949ca4aba29891847a6d675c53493f362d23190f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000071019222a323b434b535b606c707c848f949da4a39f928d81786d675d554b433a30261c110600000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000004101c28333e4850555758585858585857555045413a312c282323222322282d333d45515d67727f8c99a8b2a99d908376665c5144382c1f1206000713202d3a4653606d7986939facaa9d908477665c50505050505050505050505050505050505050505050505050505050504846423b332a1f1409000004101c2834404a545c60646a6f747a7e83898e92999ea1a8a39f9b95908b85807b75706c65605d56534e46443f3836302c271f1d18120b03000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00111e2a3743505c687278797979797979797979797979797979797a8794a1a094877a797979797979797979797979797979797872685c5043372a1e11000000000000000000000000000000000f1b2834404c5761686b6c6c6c605c5455585a5c5d5e5f5f565d6065696b6c6b6965605c554e463c37312b272018130c040000000000000000000000000000000b1825313e4b5864717e868686868686868175685b4e42393831302d28221a140c07070b141b22272b2d323939414e5a677480868686868686867e7164584b3e3125180b000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f06060403010000000000000203060e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000000004111d2935414c5563707d8a97a1ada2988a7e7164554c41352b37434e5866737f8c99a7ac9f93877b6e6154483d32271b0f010000000000000a1724303d4a5763707d8a969f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9286796c5f5346392c2013000000000000000000000000000000000000000000030f1c2935424e5a6670767979797979797570655a4d4135281b0f020000000000000000000000000000000000000000000000000911181d2124252d2d2d2c201f1c18120b030000000000000000000013202c3946535f6c7986929facaea194877b849196a1a69f9c9fa6afa39992867c6f685e554b41382d241b110700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000071018202931394149505a616a6f7a828d929fa4a49c938e82796d675d554b42382e23171006000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000814212d3944505a616465656565656564615a514c433e38342e302f302d33383f44505a606d7985929eabb1a7998c807366544a4034281c1004000815212e3b4854616e7b879aa4afa99c90837669545d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d55534d453b31261a0e020006121f2c3844515c666d71767c81858b90959b9fa3a8a19e99928e89837e79736e6963605b53524c47433c38342e2a251e1b16100c070100000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000f1b2834404b5660686b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6e7a8794a1a094877a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6860564b4034281b0f00000000000000000000000000000005111e2a3744505c6873787979796d665c504b4d4f4c52565e61686d727678797876726d675f584e463c30261c160d0701000000000000000000000000000000000a1724303d4956626c7179797979797979756f65594d4646453d3c39332a261f181212181d262d3337393e4546464c58646e7479797979797979716c6256493d3024170a000b1825313e4b5864717e8b97a4aca89b8e8175685b4e4235281b13131311100e0a050005090d0f1013131b2734414e5a6774818d9aa7aca4978b7e7164584b3e3125180b0000000000000613202c3945515d6775818e9ba9ac9f92867a6d6053473a2f26323c4855616e7b88959faba4998c7f7266594f43382c1d12070000000000000a1724303d4a5763707d8a93939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939286796c5f5346392c201300000000000000000000000000000000000000000003101d2a3643505d6976828686868686868275695c4f4236291c0f03000000000000000000000000000000000000000000000009121b22292e3132393939392d2c29231d150d0300000000000000000013202c3946535f6c7986929facada09386797b849197a1a9a9abb0a89f92877d706a5f564c43392f261b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000060e171f282f383f4450585f686d78808b9399a3a59e948f82796d675d544a3f342822180b020000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000a1623303c4955616c71727272727272716c605d554f4645403e3d3c3c3d3f44495059616c73808d97a1adab9f95887c6f6255483c2e23180c00000916232f3c4956626f7c8995acb6a89c8f82756a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a615f574d42362a1e1205000713202d3a4653606d787e83888d92989da0a7a69f9c96918c86817c77716d67615f5753504945413a37312c28231c19140f0a0400000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000b17232f3a454e565c5e6060606060606060606060606060616e7a8794a1a094877a6d6160606060606060606060606060605e5c564e453a2f23170b00000000000000000000000000000005121f2b3845525e6b7885868686786d60534a4c51565e61686d737a7f82858685837f796f6a5f584e42382e23170b0000000000000000000000000000000000000815212d3945505a62646c6c6c6c6c6c6c68655d53535353514a49443e363129231d1d23282f383f44464b52535353535c64676c6c6c6c6c6c6c64625a5045392d211508000b1825313e4b5864717e8b979f9f9f9b8e8175685b4e423528202020201d1d1a16110b1015191c1c2020202734414e5a6774818d9a9f9f9f978b7e7164584b3e3125180b0000000000000714212d3a4754606d7a86929facaa9b8e8175675d5145392c212d3a46535f697683909dabab9e9184776b605448392f24180c0000000000000a1724303d4a5763707d8686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c5f5346392c201300000000000000000000000000000000000000000003101d2a3643505d69768390939393938f8275695c4f4236291c0f030000000000000000000000000000000000000000000006111b242d343a3d3e464646463a38342f271f150b01000000000000000013202c3946535f6c7986929facada093867a6e7b859197a1a9b3aca1968b7f726b60584e443a31271d140a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000000000050d161d262d333e464e565d666d747f879298a2a69e949082796d665c50443f342a1d140a0000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000b1724313e4a5764717e7e7e7e7e7e7e7d756d67615953514b4b4a49494a4a50535b606b707e88939fa9b0a69d9083766a5f53473b2e1c120700000a1623303d495663707c8996a3afa89b8e8177777777777777777777777777777777777777777777777777777777777777776e695f53463a2d21140700101d293643505c6976828a90949a9fa2aaa29f9a948f8a847f7a756f6a64605d55534d46443f38352f2b261f1c17110e0802000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0007121e28333c454b50525353535353535353535353535354616e7a8794a1a094877a6d61545353535353535353535353535352504b453c33281e120700000000000000000000000000000003101d2a3643505d6976839098897c6f635a56555d60686d737a80858b8f9192928f8b847c6f6a5f544a3f34281c1003000000000000000000000000000000000005111d29343e48505658606060606060605b595e606060605e57555046423b342f27272e343c41495053585f6060605f5c585a60606060606060585650483e34291d1105000b1825313e4b5864717e8b93939393938e8175685b4e42352d2d2d2d2d2a2926221c151b212528292d2d2d2d34414e5a6774818d93939393938b7e7164584b3e3125180b000000000005121e2a36424d5765717e8b98a2aea2988a7d7064554b4035291e2a36424d5765727f8b99a3aca096897c6f63554b4035291d100400000000000916232f3c4855616b707979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746a5e5145382b1f1200000000000000000000000000000000000000000003101d2a3643505d697683909c9f9f9c8f8275695c4f4236291c0f03000000000000000000000000000000000000000000010c18222d363f454a4b535353524745403931271d1207000000000000000013202c3946535f6c7986929facada093867a6d6f7c859297a2aaab9e91847a6d675c554b423930261e140b020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000040b141b2227343c444c545c606d727e869298a2a69f958f82786d605a50463c2f261c110600000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000003101d2a3643505d6976838b8b8b8b8b8b8a817a706b64605c545756555657545b60656c727d86929aa4afaa9f948a7d7064584e43372b1f0b0000000a1724303d4a5763707d8a96a3b0ab9e928583838383838383838383838383838383838383838383838383838383838383837b6e6155483b2e22150800101d2a3743505d6a7683909c9fa6a8a09d98928d88837d78736d6862605853514b46423b37332d29241e1b15100c06000000000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00010c17212a333a4043454646464646464646464646464754616e7a8794a1a094877a6d6154474646464646464646464646464543403a332a21170c01000000000000000000000000000000010e1b2834414e5b6774818e9a8e81756c656364676d737a80868d92989c9e9f9e9c9691857c6f665c5044382b1f13080000000000000000000000000000000000000c17222d363e45494b5353535353535359636b6c6c6c6c6b64615a534d45403931303940454d535b60656c6c6c6c6b686157535353535353534b49453e362d22170c00000b1825313e4b5864717e868686868686868175685b4e423939393939393736322d271f262c3235363939393939414e5a677480868686868686867e7164584b3e3125180b00000000000714212d3a46535e697683909caaab9f9285796d6053463a2f241a26313b4754616d7a86929faca89a8e8174675d5145392c1f140900000000000714202c38444f5961636c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a62584d4135291d100000000000000000000000000407090a0b0b0b0b0b0b101d2a3643505d697683909ca9a89c8f8275695c4f4236291c0f0b0b0b0b0b0b0a09070400000000000000000000000005111d29343f485056586060605f53514b43392f23180c000000000000000013202c3946535f6c7986929facada093867a6d6a6f7c859298a2aaa1968f82796d675c544a423830261d140b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000000000020a1117222a323a424a505b626c717d869298a2a79f948e81746d62584e42382d22170b00000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000030f1c2936424f5c6975828f9898989898938e847d76706d6666646362636465666c71787f879298a2acaca2988f82766c6155463c32261b0f0000000a1724313d4a5764707d8a97a3b0ada1979290909090909090909090909090909090909090909090909090909090909090887b6e6255483b2f22150800101d2a3743505d6a7683909da9a49c96918b85817c76716d66615e56544e4745403936312b27221b19130f0a030000000000000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000050f1821282f34373839393939393939393939393b4754616e7a8794a1a094877a6d6154473a39393939393939393939393837342f2821180f0500000000000000000000000000000000000c1825323f4b5865727e8b98938b7f75717071747a80858d92989fa2aaa4a3a5a8a1979083786d6053463a2f24190d01000000000000000000000000000000000006111b242d34393d3e464646464646525e6b757979797978706c615f57514b433e3d424b51575f656c71787979797873685c504646464646463e3d39342d241b110600000a1724303d4956626c7179797979797979756f65594d3b46464646464644423e39312930383d41434646464646464c58646e7479797979797979716c6256493d3024170a00000000000815212e3b4854616e7b87939faca99b8e8174675c5145382c1d14202d3946525e6876828f9caaab9f9285796d6053473b31251a0e00000000000714212d3a46535f696e72727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272726d62564a3e3125180b00000000000000000000040b10131616171717171717171d2a3643505d697683909ca9a89c8f8275695c4f4236291c17171717171717161613100b05000000000000000000000915212e3a45505a62656c6c6c6c605c554b4034291c10040000000000000013202c3946535f6c7986929facada093867a6d606a6f7d869298a3a89f948f82796d665c544a42382f261d140b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000000000000000000061018202830383f44515a616b707d869299a4a69d938b7e716a5f544a3f33281d1207000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000020e1b2835414e5b6874818e9ba5a5a5a59e96918a837d79767271706f6f707275787d838b9299a2aaafa49a92867b6e61594f44342a20150a0000000a1724313d4a5764707d8a97a3b0b3a9a19e9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d94887b6e6155483b2e22150800101d2a3743505d6a7683909da99c928d847f7a746f6a64605c54524c48433d38352f2a261f1b17110d080100000000000000000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000060f171e23282a2b2d2d2d2d2d2d2d2d2d2d2e3b4754616e7a8794a1a094877a6d6154473a2e2d2d2d2d2d2d2d2d2d2d2b2a28231e170f060000000000000000000000000000000000000815222f3b4855626e7b88959b918b827e7d7e81858c92989fa2a29f9a9796989c9f9f958a7d7164554c4135291d110400000000000000000000000000000000000009121b22292d303139393939394653606c7987868686847d756e69605c554f46454f545c60696e777e8586868685786b5f5245393939393931302d29221b12090000000815212d3945505a62646c6c6c6c6c6c6c68655d534648535353535353504f4a433b313a42494e4f53535353535348535c64676c6c6c6c6c6c6c64625a5045392d2115080000000007131f2c38434e5866737f8c9aa4ada2978a7d7063554b4034281c111d2a36414c5664717e8b98a2aea2988b7e7164574d42362a1b1106000000000815222e3b4855616e7b7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7265584c3f3225190c000000000000000000070f161b20222324242424242424242a3643505d697683909ca9a89c8f8275695c4f42362924242424242424242322201c160f070000000000000000000b1724313d4a56626c71797979796d675c5145382c1f13060000000000000013202c3946535f6c7986929facada093867a6d60606a707d869299a3a69f948f82786d665c544a42382f261d140a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e161e262e343f485059606b707e87939fa6a59f92867c6f665b5044392e23180c000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000010e1a2734414d5a6774808d9aa7b1b4aea8a19e94908a85827f7e7d7c7c7d7f82858a90959fa3ababa39f93887e71695f53473e3322180e040000000a1723303d4a5663707d8996a3b0b8b0aba99f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa9aaaaaaaaaa94877a6e6154473b2e21140800101d2a3743505d6a7683909da69a8d8079726d68625f5853504a46413b38322c29241d1a150f0b0600000000000000000000000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000000050c12171b1e1f202020202020202020212e3b4754616e7a8794a1a094877a6d6154473a2e212020202020202020201f1e1b17120c05000000000000000000000000000000000000000814212e3a47535f6a7784919d9b948f8b898a8d92989fa2a29f98928d8a898b90949c9c8f8276675d5145392c201306000000000000000000000000000000000000000911171d2124252d2d2d2d313e4b5864717e889396918a827b736d67615953525960666d737b828b929792877e7064574a3d312d2d2d2d2524211d1711090000000005111d29343e48505658606060606060605b59534d535f6060606060605d5b554d4339424c545a5c6060606060605f5353585a60606060606060585650483e34291d1105000000000915222e3b4854606a7784919eacab9e9285796d6053463a2e23180d1925303a4754606d7a86929facaa9c8f8276695e5346382d22170b000000000a1724303d4a5763707d8a8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c86796c5f5346392c2013000000000000000007111921272c2f303131313131313131313643505d697683909ca9a89c8f8275695c4f4236313131313131313131302f2c272119110700000000000000000b1825323e4b5865717e86868686796d6053473a2d20140a0000000000000013202c3946535f6c7986929facada093867a6d6058606b707d879299a3a69e948f81786d665c544a41382f261b11060000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000010000040607080707050100040c141c2328363e474f59616c727f8c949faaa3989083786c60554b4034281c10040000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000d1a2633404d596673808c99a6b4aaa29f9a9f9f9c98928f8c8a8988898a8b8e92979da0a7aea8a199928b7f726c61574d42352c21100600000000091623303c4956636f7c8996a2afb0a69f9c9393939393939393939393939393939393939393939393939c9ea6b0aea398877a6d6054473a2d21140700101d2a3743505d6a7683909da99c928d847f7a746f6a64605c54524d48443d39352f2b261f1c17110d080200000000000000000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000000001070b0f1112131313131313131314212e3b4754616e7a8794a1a094877a6d6154473a2e2114131313131313131312110f0b0701000000000000000000000000000000000000000006121e2b37424e5765727e8b95a09e9c9896979a9fa2a39f98928c85817e7d7e838c929f92867a6d6054473a2d2114070000000000000000000000000000000000000000060c1115171820202024303d4956626c717f8b919e948f868079706b615f5d606b6f797f868f949f93887e716c6155493c3023202020181715110c060000000000000c17222d363e45494b535353535353534e4d4d575e6c6c6c6c6c6c6c6a665f554a3e49545e66696c6c6c6c6c6c6c5e574d4e535353535353534b49453e362d22170c0000000004101c2834404b54626f7c8996a0aca99a8e8174665c5144382c1d120813202c3945515d6775818e9ba9ac9f93877b6e6153493f33271b0f030000000a1724303d4a5763707d8a96989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989286796c5f5346392c201300000000000000040f19232b32383b3d3e3e3e3e3e3e3e3e3e3e43505d697683909ca9a89c8f8275695c4f423e3e3e3e3e3e3e3e3e3e3d3b38332b23190f05000000000000000a1723303d4a5663707d8993988a7d7063574a3d31261b0f0300000000000013202c3946535f6c7986929facada093867a6d605359616b717e87929aa4a69e938e81786d665b534941382d2217140a01000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000020608080e070c101313151413110d0802020a1117242c353d47505a606c77828f98a2aa9f958b7e71675c5145382c1f14080000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000c1926323f4c5965727f8c98a5aea298928d939aa0a29f9c999796959697989b9ea1a9acaba39f9691877f726d625a50453c31231a1000000000000815222f3b4855626e7b8895a9b3ab9f948f8686868686868686868686868686868686868686868686868f949eaaac9f928579675d5145392c20130600101d2a3743505d6a7683909da9a49c96918b86817c76716d66615e56544f4745403937312b28221c19130f0a040000000000000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000000020405060606060606060814212e3b4754616e7a8794a1a094877a6d6154473a2e211407060606060606060504020000000000000000000000000000000000000000000000020e1a26313c4653606c78839097a1a8a4a3a4aaa29f98928d86807a74717072767f8c94998a7d7063574a3d3024170a0000000000000000000000000000000000000000000005080a0b131315212d3945505a626d727f8b919c98928c847d756e69686d747c838c92989c918b7f726c625a5044392d201413130b0a0805000000000000000006111b242d34393d3e464646464646464246535e69767979797979797771665b4f424e5a66707679797979797976695e5346464646464646463e3d39342d241b11060000000006131f2c3845515c6674818d9aa8ada197897d7063544a4034281c0b04111d2935414b5564707d8a97a2ada49a8c7f73655b5044372b1f13070000000a1724303d4a5763707d8a969f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9286796c5f5346392c2013000000000000000b16212b353d4448494a4a4a4a4a4a4a4a4a4a4a505d697683909ca9a89c8f8275695c4f4a4a4a4a4a4a4a4a4a4a4a4948443d352b21160b000000000000000815222f3b4855626e7b88959a8d817467584e43372b1f120600000000000013202c3946535f6c7986929facada093867a6d60534f59616c717e88939fa3a59e938e81786c655b53493f3327261c130a010000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000003090e1214151a1c181c1f202121201d19130c050006121a232b353e44505b656e7b86929faaa79e9184796d6053463b3025190d0100000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000b1825313e4b5864717e8b97a4ab9f9286818890959b9fa3aba4a3a2a2a3a5a8a9a7a8a19e99928d847d716d625b51483e332a1f110800000000000714212d3a4754606d7a8797a2ada99c8f82797979797979797979797979797979797979797979797979828f9ca9ab9e9184786b554b4135291d110400101d2a3743505d6a7683909c9fa6a8a09d98928d88837e79736e6863605953514b47423c38332d2a251e1b15100c07010000000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e2114070000000000000000000000000000000000000000000000000000000000000000000009151f2b3844505b666f7c8591969c9f9f9e9c98928d86807a736d686463656d76828f998d8073665a4d4033271a0d00000000000000000000000000000000000000000000000000000605111d29343e48505a626d727f8c929c9f96918a827b73717a818891959f9d928c7f736d625a50483e33281c1004060000000000000000000000000009121b22292d3031393939393939393b4854616e7b86868686868683776a5d50444f5c6976828686868686867b6e6154483b39393939393931302d29221b120900000000000713202d3a4653606d7985929eabab9e9185796d6053463a2e23180c010d18242f3a4653606d7985929fabac9e9184786c6053463a2f24180d0100000a1724303d4a5763707d8a93939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939286796c5f5346392c201300000000000004101b27323d474f54565757575757575757575757575d697683909ca9a89c8f8275695c57575757575757575757575756544f473d33271c10040000000000000714202d3a4753606d7a86979e9184786a5f53473a2e21150800000000000013202c3946535f6c7986929facada093867a6d605347505a616c727f8b919ba4a59e938e81776c655b504440382e261c130a0100000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000000000060e151a1e2122272823282c2d2e2e2d2a251e160e05000811192327333f49535e69737f8c98a2ada1968b7e7164564c41362a1e110500000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000a1724313d4a5764707d8a97a3ac9f9286797c83898e9299999c9d9e9f9f9f9e9d9b9896918c86807a706b625a51493f362c21180e0000000000000613202c3945515d677885929eabaa9d9184776c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c667784919eaaa99c8f8376695c50432f24180d0100101c2936434f5c6976828a8f949a9fa2a9a29f9a94908a84807b756f6b65605d55534d46443f3836302b271f1c18120e0903000000000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000000000000030f1c28333f4a545f6a6f7c848c909292918f8b86807b746e68605d56565b64707d8a998f8275685c4f4235291c0f020000000000000000000000000000000000000000000000000000000c17222d363f48515b636d737f8c929ca09e948f867f7d848d939aa09d938d80736d635b51483e362c22170b000000000000000000000000000000000911171d2124252d2d2d2d2d2d2e3b4854616e7b87939393939083776a5d50444f5c6976828f93939393877b6e6154483b2e2d2d2d2d2d2524211d171109000000000005111d2935414c5664707d8a97a2ada89a8d8074665c5044382b1c12070007131f2c3845515c6674818e9aa8aca096897c7063554b4035291d110400000a1724303d4a5763707d8686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c5f5346392c20130000000000000713202c38444f59606364646464646464646464646464697683909ca9a89c8f827569646464646464646464646464646360594f44382c20130700000000000006131f2c3945515d677885929e96887b6f6255483c3025190d01000000000013202c3946535f6c7986929facada093867a6d60534748505a626d727f8c929ca4a59d938e80776c605c524a40382e251c130a01000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000000060f181f262b2d2e34352e34383a3b3a3936302820160c0200071117222d38414d57606d7a86929faca89c908376685e5246392d20140700000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000a1623303d495663707c8996a3afa399867a6f787d82868a8c8f909192929291908e8b8884807b736d68605950483f372d241a0f0600000000000004111d2935414c55697683909ca9ab9f928578695f606060606060606060606060606060606060606d7986929faca79a8d8174675a4e4134271b0700000713202d3a4653606d787d82888d92979da0a7a69f9c97918c86817c77726d67625f5753504a46413a37322c29231d1a140f0b0600000000000000000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000000000000000b17222d38424e585f6a6f797f83858684827f7a736e69615e56524c4a54606d7987868683776a5e5144372b1e110400000000000000000000000000000000000000000000000000000006101b242d363f49515b636d73808d929da49e98928c8a91969fa49e938e81746e645b51493f362d241a10050000000000000000000000000000000000060c111517182020202020212e3b4854616e7b87949f9f9d9083776a5d50444f5c6976828f9c9f9f94877b6e6154483b2e2120202020181715110c060000000000000713202d3946525e6875828f9ba9ada196897c6f63544a3f34281c0b000004101c2834404b5463707c8996a1ada89b8e8174675d5145392c20140900000916232f3c4855616b707979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746a5e5145382b1f120000000000000916222f3b4854606b7071717171717171717171717171717683909ca9a89c8f82757171717171717171717171717171706b6054483b2f22160900000000000004101d2935404b556a7783909d998c7f7266564c41362a1d1105000000000013202c3946535f6c7986929facada093867a6d6053473e48515b626d737f8c929ca4a59d938d80746e645c524a40372e251c1309010000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000030e18212a31373a3b414243404546484746413a32281e1308000006111b262f3b45525d6875828e9ba8ac9f93877a6e6154473b2e21140800000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000916222f3c4955626f7c8895a2b5ab94877b6e6c70757a7d808284848586858583817f7c78736e68605d564f473f362d251b120800000000000000010d19242f414d5a6774808d9aabaea298887b6e61555353535353535353535353535353535355626f7c8899a3afa9988b7e7265584b3f3225180c000006121f2c3844505c666d71767b80858b90959b9fa3a9a19e99928e89837e79746e6964605b54524c47433d38342f2a251f1b17110d080100000000000000000000000000000713202d3a4653606d798693a0aca69a8d8073675a4d4034271a0700000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e211407000000000000000000000000000000000000000000000000000000000000000000000006111c262f3c464e585f676d727678797876726d68615e56524c454145515d67757979797771675b4f43362a1d10040000000000000000000000000000000000000000000000000000000009121b242d373f49525b636e74808d929da5a39f99979ea1a69e948e81786c605c524940372d241b1108000000000000000000000000000000000000000005080a0b1313131315212e3b4854616e7b8794a1aa9d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e21151313130b0a080500000000000000000714212e3a4754616d7a86929facab9e9184786c605346392e23170b0000000c18232e394653606c7884919eabac9f92857a6d6053473b31261a0e02000714202c38444f5961636c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a62584d4135291d100000000000000a1623303d495663707d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7e83919daaaa9d90837e7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d706356493d3023160a000000000000000c18242f424f5c6875828f9b9c908376685e5246392d201307000000000013202c3946535f6c7986929facada093867a6d6053473a3f49515b636d73808d929da5a59d928d80746e635c524940372e251b13090000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d2013070000000000000000000000000000000000000000000009151f2a333c4247484d4f504b51535454524c443a3025190d0100000a141d2935414c5664717e8b97a4afa49a8a7e7164574b3e3124180b00000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000815212e3b4854616e7b8794abb5a295887b6f6263686d7073767778797978787674726f6a66615e56524c433d352d241b1309000000000000000000081724313e4a5764717d8a99a3afaa988b7e7165574d42464646464646464646464646424d5765727f8c98abada297887b6f6255483c2f221509000003101c28343f4a545c60646a6e74797e83898e92989ea0a8a39f9b95908b85807b76706c66615e56544e4745403936312b27221b19130c04000000000000000000000000000713202d3a4653606d798693a0aca79a8e8174675b4e412e23180c00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e2114070000000000000000000000000000000000000000000000000000000000000000000000000a141d2a343c464e555d6065696c6c6b6965615e56524d46413b35414b555d6b6c6c6c6a675f564b3f33271b0e02000000000000000000000000000000000000000000000000000000000009121b252d374049525c646e74808d939da59f9f9f9fa79f948f82786d665b504a40372e251b1209000000000000000000000000000000000000000000000000000606060815212e3b4854616e7b8794a1a99d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e2115080606000000000000000000000006121e2b37424d5765727f8b99a3aea89a8d8073655b5044372b1c110600000007121f2b3844505b6673808d9aa8aea2988b7e7164574d42362a1e12050004101c28333e474f5557606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605f5e5850473c3125190d000000000003101d2a3643505d6976838a8a8a8a8a8a8a8a8a8a8a8a8a8a8a9195a0acab9f95908a8a8a8a8a8a8a8a8a8a8a8a8a8a8a83776a5d5044372a1d1104000000000000071a2734414d5a6774808d9a9f93867a6d6154473a2e23180c000000000013202c3946535f6c7986929facada093867a6d6053473a373f49525b636e74808d939da5a49d928d80736e635b51493f372d251b120900000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaca09386796d6053463a2d201307000000000000000000000000000000000000000000020e1a26313c454d53555a5b5c555c6061615e564c41362a1d11050000020b19242f3c4955626f7c8895a2b6ac998d8073665a4d4033271a0d00000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000714212d3a4754606d7a8799a4afa296897c6f63565d606366696a6b6c6c6c6b6a6865625f5854524d45413a312b231b1209010000000000000000000714212e3a4754616d7a86929faca89b8e8275695e53463d313939393939393939303946525e6976828f9ca9ab9e9285786c605346392d2013060000000c17232e38424a5053575f62676d71777c81868c91969c9fa4a7a09d97928d87827d78726d6862605853514b46423b37332d29241e160d0a0100000000000000000000000713202d3a4653606d798693a0aca89b8f827568544b4034281c1004000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000000000000000000000000000814212e3b4754616e7a87949f9f94877a6d6154473a2e211407000000000000000000000000000000000000000000000000000000000000000000000000020b18222a343c434b5154595d5f5f5e5c5854524c46423b36302f3a434b515e6060605e5b564d44392e22170b0000000000000000000000000000000000000000000000000000000000000009131c252e37404a525c606c77818e93939393939393959082796d665c544a3f382e251c130900000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b87949c9c9c9083776a5d50444f5c6976828f9c9c9c94877b6e6154483b2e211508000000000000000000000000000814212e3a47535f697683909d9f9fa096897c6f6253493f33271b0a00000000030f1c28333f4a54626f7c8895a09faa9c908376695f53463a2d21140700000b16212c353e44484a5353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353514d473e352a1f1409000000000003101d2a3643505d6976839097979797979797979797979797979da0a8b1b1a79f9d97979797979797979797979797979083776a5d5044372a1d11040000000000000c1926323f4c5965727f8c98a4998b7e7164544a4034281c10040000000013202c3946535f6c7986929facada093867a6d6053473a2d374049525c606c77818e939ea6a49c928c80736d635b51493f372d241b1209000000000000000000000000000000000000000000000000010101010101010101010613202c3946535f6c7986929facaca09386796d6053463a2d20130701010101010101010101000000000000000000000006121e2b37424d575f616768696a676d6e6d685e5246392d2013080000000814212e3b4754616e7a8794a1ada89b8e8175685b4e4235281b0f02000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0000000613202d394653606c7986939faca3968a7d706357525457595c5d5e5f5f5f5e5d5b5855534e4746413b352f281f19110900000000000000000000000713202d3946525d6876828f9ca9ac9f92867b6e61584e433b322c292424292c3139424d57616e7b86929faca89b8e8174655b5044372b1f120500000006111c2630383f44464e53555d60656a6f747a7f848a8f93999ea1a9a29f9a938f8a847f7a746f6a64605c55534d46443f38352f28201c140a00000000000000000000000713202d3a4653606d798693a0aca99d908376665c5145382c1f130700091623303c4956636f7c8996a2afa4988b7e7165584b3e3225180b0000000000000000000000000000000000000814212e3b4754616e7a8792929292877a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000000000000000000061018222a313a4145474c50525352504c4746413a36302a2528313a414547535353514f4b443b32281d110600000000000000000000000000000000000000000000000000000000000000010a131c252e384044505b656c7881868686868686868683796d675d544a42382d261c130a0100000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b878f8f8f8f8f83776a5d50444f5c6976828f8f8f8f8f877b6e6154483b2e211508000000000000000000000000000815222f3b4855626e7b8895939393939184776a605441382d22170b00000000000b17222d3847545f6a7784919393939394887b6e6155483b2e221508000005101a232c33383c3d464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464645413c352c23190e03000000000003101d2a3643505d697683909c9f9f9f9f9f9f9f9f9f9f9f9f9fa9abb0b8b8b0aaa89f9f9f9f9f9f9f9f9f9f9f9f9f9d9083776a5d5044372a1d11040000000000000b1724313e4a5764717d8a97ab9b8e8275665c5144382c1f12060000000013202c3946535f6c7986929facada093867a6d6053473a2d2e374044505b656d78818e949ea6a49c928c7f736d635b51493f362d241b120900000000000000000000000000000000000000010406070d0d0d0d0d0d0d0d0d0d0d13202c3946535f6c7986929facaca09386796d6053463a2d20130d0d0d0d0d0d0d0d0d0d0d07060400000000000000000814212d3a47535f696e7475767778797b7a6d6154473a2f24190d0100000714202d3a4753606d7a8693a0ada89c8f8275695c4f4236291c0f03000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000005121f2b3744505b657885929faba4978b7e7164584b474a4d4f515152535252504e4c4947433c39363029241e160d0700000000000000000000000005111d2935414c5664717e8b96a1ada3998d80746a60564d443e39352f2f35383c434b545e6973808d99a3aca096897d706353493f33271b0f03000000000a151e262e34383c42474b5153586062686d72787d82878d92979c9fa6a49f9c96918c86817c76716d67615e5753504945413a322e261c1207000000000000000000000713202d3a4653606d798693a0acac9f9286796d6053463a2e23180d060a1723303d4a5663707d8996a3b0a4978b7e7164584b3e3125180b0000000000000000000000000000000000000814212e3b4754616e7a8786868686877a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000000000000000000000610181f282f35393a3f43454645433f3a3936302a251f191f282f35393a46464644433f39322920160b000000000000000000000000000000000000000000000000000000000000000000010a131c2627333f49535b666c757979797979797979776d675d554b42392f261c140a010000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8283838383828074675a4e414d5a6673808283838383827a6e6154473b2e211408000000000000000000000000000d1a2733404d5a66738086868686868686807366584e432f261b1106000000000006111c2b37434e5866737f86868686868686807366594d4033261a0d00000008111a21282c2f3039393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393835312a231a110700000000000003101d2a3643505d6976839093939393939393939393939393939c9fa6b0b0a69e9c93939393939393939393939393939083776a5d5044372a1d11040000000000000916232f3c4956626f7c8995ab9f9285796d6053463a2d2013090000000013202c3946535f6c7986929facada093867a6d6053473a2d2027333f49535c666d78828f949fa6a49c918c7f726d625b51483f362d241b12080000000000000000000000000000000001070d1113141a1a1a1a1a1a1a1a1a1a1a1a202c3946535f6c7986929facaca09386796d6053463a2d201a1a1a1a1a1a1a1a1a1a1a1a1313100c070000000000000815222e3b4855616e7b80828384858687807367554c4135291d120c070a0a15212e3b4854616e7b8794a1aea89c8f8275695c4f4236291c0f03000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000030f1b27333f495e6b7884919eaba5988b7f7265584c3f3d404344454646454543413f3c3b37322d2a251f19130c0400000000000000000000000000010d1924303a4653606d7984919ea7ab9f92877c6f685e564f47454141414045474e555c666e7b86929faba89e9184786c605346392d22170b0000000000030c151c23282c3137394045474e54565e61666c70757b80858a90949a9fa2a8a19e98928e89837e79736e6963605b53524c4440382e24190e020000000000000000000713202d3a4653606d798693a0acaea398897c6f62544b4034281f1612101824313e4b5764717e8a97a4b1a4978a7e7164574b3e3124180b0000000000000000000000000000000000000714202d3946525e687579797979797975685e5246392d201307000000000000000000000000000000000000000000000000000000000000000000000000000000060d161d24292c2d323639393836322e2d2a251e19140d161d24292c2d3939393736332e2820170e0400000000000000000000000000000000000000000000000000000000000000000000010a1417222d38414a545b60686c6c6c6c6c6c6c6c6a605d554c433930271d140a02000000000000000000000000000000000000000000000000000000000000000714202d3946525e686e767676767676746e64584c404b58636e737676767676766e685e5246392d201407000000000000000000000000000c1926323f4b57636e7379797979797979736e6358463d321d140a000000000000000f1b26323c4b57636d7379797979797979736e63574b3f3226190c000000000810161c2023242d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2b29251f1911080000000000000003101d2a3643505d69768286868686868686868686868686868690949fabaa9e948f86868686868686868686868686868683776a5d5044372a1d11040000000000000814212e3b4754616e7a8799a3a297897c706356493d31261a0e0200000013202c3946535f6c7986929facada093867a6d6053473a2d20222d38414a545c666d79828f949fa7a49c918c7f726d625b51483f362c241a12080000000000000000000000000000040c13181d2021272727272727272727272727272c3946535f6c7986929facaca09386796d6053463a2d27272727272727272727272727201f1c18120b03000000000915222f3c4855626f7b888e8f9192978f8276675d5145392f241d181616141b222f3c4955626f7c8895a2afa89b8e8275685b4f4235281c0f02000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000b17222d44505d6a7783909daaa6998c7f7366594c403333363738393939383735322f2e2b26201e19140d080b09050100000000000000000000000008131f2c3845515c67727f8b95a0aba39991847a6e68615954514c4e4e4b5153575f676d78839098a2aca0968b7f72665b5044382b1b1106000000000000030a11171c1f262b2f35393d43474c52545b6063696e73797e83888e92989da0a7a39f9b95908b85807b75706c65605d56524a40352a1f13070000000000000000000713202d3a4653606d798693a0acb4aa998d8073665c51453b3128201f1c1e26323f4c5965727f8c98a5b0a3968a7d7063574a3d3024170a00000000000000000000000000000000000005111e2a36414c565e616c6c6c6c6c6c615e564c4135291d110500000000000000000000000000000000000000000000000000000000000000000000000000000000040c13181d2021262a2c2c2b292521201d19130e09040c13181d20212d2d2d2b2a27221d160e050000000000000000000000000000000000000000000000000000000000000000000000000006111b262f38424a50535b60606060606060605d54514c433a31271e150b02000000000000000000000000000000000000000000000000000000000000000005111e2a36414c565e6169696969696967645c52473c47525c6366696969696969615e564c41362a1e1105000000000000000000000000000a17232f3b47525c63666c6c6c6c6c6c6c66635c5247342b200b02000000000000000a15202f3b46515b63666c6c6c6c6c6c6c66635c52473b2f23170a0000000000050b1014161720202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d19140e070000000000000000030f1c2935424e5a66707679797979797979797979797979797982909ca9a89c8f827979797979797979797979797979797771665b4f4236291d10030000000000000613202d394653606c7986929fa99a8d807367574d42372b1e120600000013202c3946535f6c7986929facada093867a6d6053473a2d201b262f38424a545c676d798290959fa7a39b918b7f726d625a50483e362c241a1108000000000000000000000000040d161d24292c2d34343434343434343434343434343946535f6c7986929facaca09386796d6053463a34343434343434343434343434342d2c28231d150c030000000713202d3a4653606d7985929c9d9f9f92867a6d60554b40352f2923232324262d36424d5765717e8b98a4b1a69a8d8073675a4d4034271a0d01000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000061d293643505c6976838f9ca9a69a8d8073675a4d403427292a2b2c2c2c2b2a282522211f1b1919191919181715110c06000000000000000000000004101c2834404b55606d78839099a3aba09690837a706b64605d555b5b555d60636a6e79818e959faaa49a9184796d60544a3f33281c0a000000000000000000060c10151a1d24292c32383a41464a5053575e61666d71767c81868b91959b9fa3a79f9d97928d87827d78726d68635c52473b2f23170a0000000000000000000713202d3a4653606d798693a0acb8ab9e9285796d60574d433a322d2c282a2d36424d576774818e9aa7b3a995897c6f6256493c2f231609000000000000000000000000000000000000010d1925303b444c52545f5f5f5f5f5f54524c443a3025190d01000000000000000000000000000000000000000000000000000000000000000000000000000000000001070d111314191d1f201f1d191413110d0802000001070d1113142020201e1d1b17110b040000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262f383f44464e5353535353535353504745413a31281f150c03000000000000000000000000000000000000000000000000000000000000000000010d1925303b444c52545c5c5c5c5c5c5a58524a4136404a52585a5c5c5c5c5c5c54524c443b3025190d010000000000000000000000000007131f2a35404a52575a606060606060605a58524a403522190f000000000000000004121e2a354049515759606060606060605957524a40352a1f1307000000000000000407090a131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131312100d0903000000000000000000010d1a26323e4a545e66696c6c6c6c6c6c6c6c6c6c6c6c6c6c76838f9ca9a89c8f82756c6c6c6c6c6c6c6c6c6c6c6c6c6c6a665f554a3e32261a0e0100000000000005121f2b3744505b657784919eaa9d918477695f53473a2d21140800000013202c3946535f6c7986929facada093867a6d6053473a2d20141d263039424b555d676d79839095a0a8a39f93887f726c625a50483e362c231a110800000000000000000000010c161f282f35393a40404040404040404040404040404046535f6c7986929facaca09386796d6053464040404040404040404040404040403a38342e271e150b00000006121f2c3844515c6676828f9caaaba2988b7e72675d51454039342f3030312f383f46525e6975818e9ba8b3a9988b7e7265584b3f3225180c00000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000020f1c2935424f5c6875828f9ba8a79a8e8174675b4e413428252525252525252525252525252525252525252524211d17110900000000000000000000000c18232e3944515c666f7c87929fa4a8a09590847d76716d6769676869676d70757b838e939ea7a59f93887d70665c5142382d22170b000000000000000000000003090e12181d1f272b3036383f44464d53545c60646a6f747a7f84898e92999ea1a8a19e99938f89847f7a736e63574b3f3226190c0000000000000000000713202d3a4653606d798693a0acb9ada1978b7e71695e554c443e3a3834363a3d46535e697784909daaada297877a6e6154473b2e2114080000000000000000000000000000000000000008141e29323b4146475353535353534746413a32281e13080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010406070c10121312100c070705010000000000000104060713131311100e0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d262d333839424646464646464646443a39352f281f160d03000000000000000000000000000000000000000000000000000000000000000000000008141e29323b4146475050505050504e4c4741382f3840474b4d5050505050504746413b32291e14080000000000000000000000000000020e19242e3840474b4d535353535353534d4b4740382e2410070000000000000000020d19232e3740464b4c535353535353534d4b4740372e24190e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16222d38434c545a5d606060606060606060606060606976838f9ca9a89c8f827569606060606060606060606060605d5b554d43392d22160a00000000000000030f1b27333f49536976838f9ca9a096887b6e6155483b2f24190d01000013202c3946535f6c7986929facada093867a6d6053473a2d2014141e273039434b555d676d7a839096a0a8a49a93887e716c615a50483e352c231a110800000000000000000007131d28313a4145474d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d535f6c7986929facaca09386796d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4645403930271d1207000004101c2834404a5465727e8b98a2aeaa9e9184796d605b514b45403e3d3d3d3f4149505b616e7b86929facada197887c6f6255493c2f22160900000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000020e1b2835414e5b6874818e9ba7a89b8f8275685c4f4235323232323232323232323232323232323232323232312e29221b12090000000000000000000007121d2834404a54606a727f8c929ca4a7a096918a827d7a7775747475767a7d818790959ea5a59e938d80736b60544b402f261c11060000000000000000000000000001070c10161b1e252a2d33383b42464b5153585f62676d72777c82868c91969c9fa4a49f9c96918b868073665a4d4033271a0d0000000000000000000713202d3a4653606d798693a0acb1a7a09d92857b6e675d56504846443f4246474f58616e7b8795a0acab9f928578685e5246392d20140700000000000000000000000000000000000000020d1720293036393b4646464646463a3935302820160c020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c22282b2d353939393939393939372d2c29241e160d04000000000000000000000000000000000000000000000000000000000000000000000000020d1720293036393b43434343434341403c362f262e353b3f404343434343433b3936302920170d0200000000000000000000000000000007121c262e353b3f4046464646464646403f3b352e261c120000000000000000000007121c252e353b3e4046464646464646403f3b352e251c12070000000000000000000000000000000000000000000000000000000000000000000004090d0f101313131313130e0d0b0803000000000000000000000000000000000000000000000000000000030f1b26323c464e53555656565656565656565656565c6976828f9ca9a89c8f8275695c56565656565656565656565655544e463c32271b0f0300000000000000000b17222d414e5b6874818e9ba7a8988c7f7265554c4135291d1104000013202c3946535f6c7986929facada093867a6d6053473a2d20140c151e273039434c555d686e7a849196a1a9a49a93877e716c615a50473e352c231a110700000000000000010d18242f3a434b51545a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5f6c7986929facaca09386796d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a53514b42392e23180c0000000c18232e3a4754616d7a86929fa9aca1968d80746d605d55514b4a49494a4b4f535b606d74818e98a3aeab9e9285796d6053463a2d20130700000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000010d1a2734404d5a6773808d9aa6a99c8f8376695c50433f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3e3d3a342d241b1106000000000000000000000c18232e39424e58626d73808c929ea1a8a19e948f8a8683828181828386898e93999fa7a39f938f81786d60594f42392e1d140a0000000000000000000000000000000000040a0f13191c22282b3136394045464e53555d60656b70757b7f848a8f939a9fa2a8a09e989083776a5d5144372a1e110000000000000000000713202d3a4653606d798693a0acaca09590959082796d68615a5553504a4d525459606a74808d9aa7b1a99c8f827669564d41362a1e11050000000000000000000000000000000000000000050e171e252a2d2e3939393939392e2d29251e160e04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030607090b0d0f1111121313121211100f0d0a080705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171c1f20282d2d2d2d2d2d2d2d2a21201d19130c040000000000000000000000000000000000000000000000000000000000000000000000000000050e171e252a2d2e3636363636363433302b241d242a2f32333636363636362e2d2a251e170e0500000000000000000000000000000000000a141c242a2f32333939393939393933322f2a241c140a00000000000000000000000a131c232a2f32333939393939393933322f2a241c130a000000000000000000000000000000000000000000000000000000000000000000020a1015191b1c2020202020201b1a17140e08010000000000000000000000000000000000000000000000000006131f2b37434e585f62636363636363636363636363636976828f9ca9a89c8f827569636363636363636363636363636260584e43372b1f13060000000000000000061a2633404d596673808c99a6a99c8f8276675d5145392c201306000013202c3946535f6c7986929facada093867a6d6053473a2d2014070c151e27313a434c565e686e7b849196a1a9a49992877e716c61594f473e352b23190f0400000000000004111d2935414b555d606767676767676767676767676767676767676c7986929facaca09386796d676767676767676767676767676767676767605c544b4034281c100400000713202d3946525e6874808d97a2ada89d928c7f746d67605c5557565657585960656c727f8b939daaafa4998d8074665c5044382b1f120600000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000d192633404c5966737f8c99a6aa9d9083776a5d504c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4b4a453f362d22170c0100000000000000000007121c27303d46515b646e73808a92979fa3a69f9c9992908f8e8e8f9092989b9fa4a69f99928c81786d665c50473d30271d0b020000000000000000000000000000000000000002080d11171c1f252a2e34383c43474c5154596063686e73797d82878d92979da0a79d9084776a5d5144372a1e110000000000000000000713202d3a4653606d798693a0acaa9d9084909490827a716c6562605c54565e61646b707c87929facb0a6998c7f7266594c3f3025190e02000000000000000000000000000000000000000000050d14191e20212c2c2c2c2c2c21201d19130c040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104060b10121315171a1c1d1e1f1f201f1f1e1d1b19171514120e09060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f12131b20202020202020201d1413110d080100000000000000000000000000000000000000000000000000000000000000000000000000000000050d14191e20212929292929292726241f1a13191f23262729292929292921201e19140d05000000000000000000000000000000000000020a12191f2326272d2d2d2d2d2d2d2726231f19120a020000000000000000000000010a12191e2325262d2d2d2d2d2d2d2626231f19120a010000000000000000000000000000000000000000000000000000000000000000040c141b212528292d2d2d2d2d2d2726241f1a130b020000000000000000000000000000000000000000000000000815212e3b47535f6a6f707070707070707070707070707075828f9ca8a89c8f827570707070707070707070707070706f6a6054473b2e22150800000000000000000b1825323e4b5865717e8b98a4ac9f92867a6d6054473a2d22170b000013202c3946535f6c7986929facada093867a6d6053473a2d201407030c151f28313a444c565e696e7b849197a1a9a39992877e706c61594f473d352b21160b0000000000000613202c3945515d676d737373737373737373737373737373737373737986929facaca0938678737373737373737373737373737373737373736d665c5145382c1f1306000005111d2935414c56616d7a85929fa5aea49b918c8079716d67656463636465686b70787f87929fa5afa89f93877b6e61544a3f34281c100300000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000c1925323f4c5865727f8b98a5aa9e9184776b5e5858585858585858585858585858585858585858585858585650483f34291d1105000000000000000000000b151e2b343f49525c646e737e858e92999ea1a8a39f9d9c9a9b9c9d9fa3a9a29f9b948f877f776d665c544a3f352c1e150b0000000000000000000000000000000000000000000000060b0f141a1d23282c32373a4145474f54565e61666d70767b80858b90959b9d9084776a5d5144372a1e110000000000000000000713202d3a4653606d798693a0aca396897d85929490847d76726e6d666b6b696e71757d859299a3afab9f94887b6e6155483b2e221508000000000000000000000000000000000000000000000002080d1114142020202020201413110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070d1113171c1f20222426292a2b2b2c2c2c2b2b2a28262422211e1a1312100c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306060f131313131313131311070604010000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d1114141d1d1d1d1d1d1b1a17140e080e1317191a1d1d1d1d1d1d1414110d0802000000000000000000000000000000000000000000070e1317191a202020202020201a1917130e08000000000000000000000000000000070d12161919202020202020201a1917130e07000000000000000000000000000000000000000000000000000000000000000000020c161e262c3135363939393939393433302b241d140b0100000000000000000000000000000000000000000000000916222f3c4955626f7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d82909ca9a99d90837d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c6f6255493c2f22160900000000000000000a1723303d4a5663707d8996a3aea3998a7d7164544a3f33281c0f030013202c3946535f6c7986929facaca093867a6d6053473a2d20140700030d161f28323b444d575f696e7c859297a2aaa39992877e706b61594f473d32271b100400000000000714212d3a4754606d79808080808080808080808080808080808080808087929facb3a69a8d8080808080808080808080808080808080808080796d6053463a2d2013070000010d1925303a46525e68717e8b939da5ada39b928d847e797572717070707274777d828c9299a3afaaa1968e8174695f5342382e23170b0000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000b1825313e4b5864717e8b97a4ab9f9285786565656565656565656565656565656565656565656565656565625a50453a2e21150900000000000000000000030c19222d37404a525c636c717a81868d9196989b9c9e9f9f9f9f9e9d9b9997928e89827c736c655c544b42382e231a0c030000000000000000000000000000000000000000000000000003090e12181c1f262b2f35393d44484d52545c6064696e74797e83898e929084776a5d5144372a1e110000000000000000000714202d3a4753606d7a8693a0ada194887b7e8b9296918a837f7b79787778797a7d82889297a1abafa4998f8276695f53473a2d211408000000000000000000000000000000000000000000000000000105070813131313131307070501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e13181d2023282b2d2f3133353737383939393837373533312e2d2a26201f1c17110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010507081010101010100e0d0b08030002070a0c0d1010101010100807050100000000000000000000000000000000000000000000000002070a0c0d131313131313130d0c0a0702000000000000000000000000000000000002060a0c0d131313131313130d0c0a0702000000000000000000000000000000000000000000000000000000000000000000000a141e2830383d414346464646464641403c362f261d13080000000000000000000000000000000000000000000003101d2a3643505d69768289898989898989898989898989898990949fabab9f959089898989898989898989898989898983776a5d5044372a1d1104000000000000000815222f3b4855626e7b8895a99f9f9b8e8174665b5044382b1f12060013202c3946535f6c7986929f9f9f9f93867a6d6053473a2d2014070000040d162029323b454d575f6a6f7c859298a29fa39992877d706b60594f44382c20130700000000000814212e3b4754616e7a878d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d9299a3afb5a89d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d867a6d6053473a2d20140700000008131e2a36414c56626c74818e939da4aea49d96918b85827f7d7c7c7d7e8184898f949fa3abaaa29891847a6d60574d4230261c11060000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000a1724313d4a5764707d8a97a3ac9f93867872727272727272727272727272727272727272727272727272716c62564a3d3124170b000000000000000000000007101b252e38404a525a61686d747b8084888b8e90919292929291908e8c8985817c766f6a605b534b423930261c11080000000000000000000000000000000000000000000000000000000000070c10151b1e24292c32383b41464a5053575f62676d71777c81868c83776a5d5144372a1e110000000000000000000714212d3a4754606d7a8793a0ada194877b74818e949e95908c888685848585878a8f939aa1a9afa59f93877c6f62574d42372b1e1206000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f151a1d24292c2e34383a3c3e404244444546464545444342403d3b3a36312d2c28231c19130d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000040607090c0e1011121313131211100f0d0b08070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b26303a42494e4f5353535353534e4c4741382f241a0e0300000000000000000000000000000000000000000003101d2a3643505d6976839096969696969696969696969696969c9fa6b0b1a79f9d96969696969696969696969696969083776a5d5044372a1d1104000000000000000714202d3a4753606d7a8697939393939285796c605346392d2013060013202c3946535f6c7986929393939393867a6d6053473a2d201407000000040e172029333b454e585f6a6f7c8692989393939992867d706b6054483b2f22160900000000000814212e3b4754616e7a87949a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9fa3abb5b9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a93867a6d6053473a2d201407000000020d1925303a44505a606d78818d929fa2aaa8a09e97928f8c8a89898a8b8e91969c9fa6ada7a09892867c6f685d52453c311e140a000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b00000000091623303c4956636f7c8996a2afa4998c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7e7165584b3e3225180b00000000000000000000000009131c262e38404850565e61696e73787c7e818384858686858583817f7c79746f6a625f585049413930271e150a0000000000000000000000000000000000000000000000000000000000000000040a0f13191d20272c3036383f44464d53555d60656a6f747a7f8175685b4f4235281c0f0000000000000000000714212e3a4754616d7a8794a0b4ab94877a6d78828f939f9d989a939291919298979b9fa4acaba39f938d80736a6054453c31261a0e020000000000000004080c0e0f0c07070501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c151b20262b2f35393a3f4446484a4d4f5051525253525251504e4c4a4846423d3a38342e29251e19140d050000000000000000000000000000000000000000000000000000000000000000000000000004070c10121316191b1d1e1f1f201f1f1e1d1b19171414110e0806030000000000000000000000000000000000000000000000000004090e1112131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130b0a08040000000000000000000000000004080a0b1313131313131313131313131313131311100e0b06000000000000000000000005090d0f101313100f0d090500000000000000000000000000000000000000000000000000000000000000000000000000000915212c38424c545a5c6060606060605a58524a41362b1f140800000000000000000000000000000000000000000003101d2a3643505d697683909c9f9f9f9f9f9f9f9f9f9fa3a3a3a9abb0b9b9b1aba9a3a3a39f9f9f9f9f9f9f9f9f9f9d9083776a5d5044372a1d11040000000000000006131f2c3945515d677885868686868686867c6f6256493c2f2316090013202c3946535f6c798786868686868686796d6053473a2d20140700000000050e172129333c464e58606a707d8686868686868686867c706356493d3023160a00000000000814212e3b4754616e7a8794a1a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6acafb5acacacaea8a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a093867a6d6053473a2d2014070000000008131e29323f44505c666d78808b92989fa3aba9a29e9b9897969697989b9ea0a8aca9a19e9590867d6f6a60564c41332a1f0c02000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000915222f3c4855626f7b8895a2b5ab9b918c8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b85786b5f5245382c1f12050000000000000000000000010a141c262e363e444c52575e61666a6f7274767878797978787675726f6d66626058534e443f382f271e150c030000000000000000000000000000000000000000000000000000000000000000000001080d11161b1f252a2e34383c42474b5153586062686d72756f65594d4134281b0e0000000000000000000814212e3b4754616e7a87949f9fa39986796d6d79818c92989fa29f9e9e9e9fa2aaa8a9aaa29f99928b81786d60584e43332a1f150900000000000002090f14181b1b191413110d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b121820262b31373a4145474a50535557595c5d5e5e5f5f5f5e5e5d5b595755534d4946443f3835302a251e170e0802000000000000000000000000000000000000000000000000000000000000000001070c1013181c1f20232527292b2b2c2d2c2c2b2a28262421201e1915120f0a0300000000000000000000000000000000000000000000080f151a1d1f20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020171714110c05000000000000000000050c11141717202020202020202020202020202020201e1d1b17120b0400000000000000020a1015191c1c20201c1c1915100a020000000000000000000000000000000000000000000000000000000000000000000000000d1925313d49545e65696c6c6c6c6c6c67645c52473c3024170b00000000000000000000000000000000000000000003101d2a3643505d6976839093939393939393939393939b9ea5afb7b7b6b7b9b8afa59d9b93939393939393939393939083776a5d5044372a1d11040000000000000004101d2935404b55687378797979797979796f6a6054483b2e22150900121f2c3845525e6a75797979797979797976675c5145382c1f13060000000000050f18212a333c464e58606b70797979797979797979706b6054483b2f22160900000000000814212e3b4754616e7a87949f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f93867a6d6053473a2d20140700000000020d172028343f4a545c666d747e858e92999ea1a8a7a8a5a4a3a3a3a5a7a8aca49f9d97928c837b6f6b60584e443a3021180e00000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b000000000815212e3b4854616e7b8794abb5ada39b989898989898989898989898989898989898989898989898989285786b5f5245382c1f1205000000000000000000000000020a131c242c323a41464d5254585f626568696b6c6c6c6c6b6a686663605c54544e47433c332d261d150c030000000000000000000000000000000000000000000000000000000000000000000000000001040b1014191c23282c3137394045474e54565e616568655d53483d3125190c0000000000000000000815222e3b4855616e7b889393939392867966676d787f868d92989a9c9e9e9f9f9e9d9c9998928d877f746d665c50463d3221180e030000000000030b131a202527282621201d19130f0a040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c151d232831373c42474b5154545c60626466686a6a6b6c6c6c6b6a6a686664615f575653504a46413a3630292019130d05000000000000000000000000000000000000000000000000000000000003090e12181d1f23282c2d3032343638383939393838373533312e2d2a25211f1b150f0b060000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c171008000000000000000810171c2123242d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b2a27231d160e050000000000040c141b212528292d2d292825211b140c0400000000000000000000000000000000000000000000000000000000000000000000020f1b2835414e5a657076797979797979746e64584c4033261a0d00000000000000000000000000000000000000000003101d2a3643505d6976828686868686868686868686868e939ea9b0aba9abacb2a99d938e86868686868686868686868683776a5d5044372a1d110400000000000000000c18242f39435761686b6c6c6c6c6c6c6c6260584e43382c1f130700111d2a36424e59636a6c6c6c6c6c6c6c6c6c5c554b4034291c1004000000000000060f18212a343d464f5960636c6c6c6c6c6c6c6c6c6360594f44382c20130700000000000814212e3b4754616e7a8793939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393867a6d6053473a2d2014070000000000050e17232e38424a545c606c717a81868d9196989a9c9e9f9f9f9f9e9d9c999a93908b857f786e6960594f463c32281e0f0600000000000b1825313e4b5864717e8b97a4aca89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7aca4978b7e7164584b3e3125180b000000000714212d3a4754606d7a8799a3afacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a59e9285786b5f5245382c1f120500000000000000000000000000010a121a202830363b4246484e5355585b5d5e5f5f5f5f5e5d5b595653514a47433d373127221b140b03000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e11171c1f262b2f35393d43474c5254595b59534b42372c2015090000000000000000000916232f3c4956626f7c86868686868685786b5c666c727b80858a8d8f9192929291908f8c8a86807b726d605c544a3f342b200f060000000000020b151d252c313435332e2d2a251e1b16110d0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810191e272e343c43474d53555d6064666d6f7173757777787979787877767573706e696763605c54524c46413b322a251e170e06000000000000000000000000000000000000000000000000000001070c141a1d24292c2e34383a3c3f4143444546464645444342403e3b3936302e2b261f1c17110a020000000000000000000000000000000008121b242b3136383939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393931302d28221a1208000000000008121a22282d3031393939393939393939393939393939393736332e2820170e04000000020c161e262c32353639393635322c261e160c0200000000000000000000000000000000000000000000000000000000000000000003101c2936434f5c6976828686868686868074675a4e4134271b0e010000000000000000000000000000000000000000030f1c2935424e5a667076797979797979797979797979818e9ba7a69f9c9ea1a8a79b8e817979797979797979797979797771665b4f4236291d1003000000000000000007121d2731454f575d5f6060606060606056544e463d32271b0f03000e1a26313d4751595e5f606060606060605f514b43392f23180c0000000000000000060f18222b343d474f54565f606060606060605f56544f473d32271b100400000000000814212e3b4754616e7a868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796d6053473a2d20140700000000000006111c263038424a505a61686e747b8084888b8e90919292929291908f8d8a87837e79726d665f574f473d342b20160c0000000000000b1825313e4b5864717e8b979f9f9f9b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9a9f9f9f978b7e7164584b3e3125180b000000000613202c3945515d677986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9e9285786b5f5245382c1f1205000000000000000000000000000000080e161e252a30363a3c4347484b4e50515253535252504e4c494644403937322b262017110a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c10151a1d24292c32373a4146474c4f4d48423930251b0f040000000000000000000815222e3b4754606a6f797979797979787368545b60696e74797d808284858685858482807d7a746e69625b504a42382e22190f00000000000009131d272f373d40423f3a3936302c27201d18130f0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009111a222a303940454e53575f62676d7175797b7d8082838485858685858483817f7d7b7874706d66615e56524c443e36302920180f07000000000000000000000000000000000000000000000000030b12181f252a2f35393a404446494c4e5051525253525251504e4c4a4746413c3a37312b28221c140b070000000000000000000000000000040f19242d353d4245464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646463e3c39332c241a100500000005101a242c33393c3e4646464646464646464646464646464644433f39322920160b0000000a141e2830383d4143464643413d3830281e140a000000000000000000000000000000000000000000000000000000000000000000020f1c2835424f5b6875828e939393938d8073675a4d4034271a0d010000000000000000000000000000000000000000010d1a26323e4a545e66696c6c6c6c6c6c6c6c6c66707d89939eab9f94909196a1ac9f93887c6f666c6c6c6c6c6c6c6c6c6a665f554a3e32261a0e010000000000000000010b151f333d454c5052535353535353534948433d342b21160a00000915202b353f474e5253535353535353535345403931271d1207000000000000000000061019222b353d4448495253535353535353524948443d352b21160b0000000000000714202d3946525e687679797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797976675d5145392c201306000000000000000a141e2630383f4450565e61696e73787b7e81838485868685858482807d7a76726d67605c544d453d352b22190e040000000000000b1825313e4b5864717e8b93939393938e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d93939393938b7e7164584b3e3125180b0000000004111d2935414b556b7885929393939393939393939393939393939393939393939393939393939393939285786b5f5245382c1f120500000000000000000000000000000000050c13191f252a2d32373b3c3f414345454646454543423f3c3a38342e2b27201b150b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e12181d1f272b3035393a3f42413d3730271e14090000000000000000000006131f2b37434e5860626c6c6c6c6c6c6b68615750575e61676d7073767778797978777673706d67615e5751443f3830261c10070000000000040f1a252f3941484d4e4c4746413a38322c29241d1a15100c070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b232c343c424b51585f62696e747a7d8185888a8c8f9091919292929191908e8c8a8884807d79736d68615e565046413a322a2119100700000000000000000000000000000000000000000000060d151d24293136394045474a515356585a5c5e5e5f605f5f5e5d5b595754524c4847433c38332d261d18120b030000000000000000000000000915202b353f474e52535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534a49453e362c22170c0000000c17222c363e45494a53535353535353535353535353535353514f4b443b32281d12060005101b26303a42494e4f53534f4e49423a30261b10050000000000000000000000000000000000000000000000000000000000000000020e1b2835414e5b6874818e9b9f9f998c807366594d4033261a0d000000000000000000000000000000000000000000000a16222d38434c545a5d6060606060606057606d7883919da5a499908384919ea6a49a9083786d6057606060606060605d5b554d43392d22160a00000000000000000000030d212b333b404445464646464646463c3b38322b22190f040000040f19242d353d424546464646464646464638342f271f150b0100000000000000000000071019232b32383b3d4646464646464646463d3b38322b23190f0400000000000005111e2a36414c565e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5d554b4035291d110400000000000000020c141e262e343e444c52575e61666a6f727476777879797978777573716d6865605d55504a423c332b23191007000000000000000b1825313e4b5864717e868686868686868175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a677480868686868686867e7164584b3e3125180b00000000010d18242f44515e6b7784868686868686868686868686868686868686868686868686868686868686868685786b5f5245382c1f1205000000000000000000000000000000000002080d141a1e20262b2e2f323536383939393938373533302d2c28231c1b150f0a030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c10161b1e25292d2e323534312c251e150c0200000000000000000000030f1b27323d464e545660606060606060595751444d53555c606367696b6b6c6c6b6a696663605d55534d453f342e261e140a0000000000000814202c37414b53595b5954524c48433d39352f2b261f1c18120e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d353e464e545c606a6f757b81868a8e929797999b9d9d9e9f9f9f9e9d9d9b999796918d8985807a746e68615a524c443c332b2219100700000000000000000000000000000000000000000910181f272f353b42464b5153545c60636567696b6b6c6c6c6b6b6a686664615e5655534e46443f382f28231d150c0500000000000000000000000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060575550483e33281c11040004111c28333e48505557606060606060606060606060606060605e5b564d44392e23170b000915212c38424c545a5c60605c5a544c42382c2115090000000000000000000000000000000000000000000000000000000000000000010e1b2734414e5a6774818d9aa7a5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000005111c27313a434a4e50535353535353535e69727f8c95a0a99f93877c7e8a949faba0958c7f72695e53535353535353504f4a433b31271c110500000000000000000000000f1921292f343738393939393939392f2e2c27211910070000000008121b242b3136383939393939393939392c29231d150d0300000000000000000000000007111921272c2f30393939393939393939302f2c272119110700000000000000020e1925303b444c525f6060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605f514b433a2f24180d010000000000000000020c141c2328323b41464d5354585f626567696b6c6c6c6c6b6a696664615e5653514b443f38302a2119110700000000000000000a1724303d4956626c7179797979797979756f65594d4034271b0e01000000000000000000000000010d1a2733404c58646e7479797979797979716c6256493d3024170a0000000000071d2a37434f5c67727779797979797979797979797979797979797979797979797979797979797979797873685d5044372b1e11050000000000000000000000000000000000000003090e12151b1f212225282a2b2c2c2c2c2b2a282623201f1c18120f0a04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f13191d202126282825201b140c030000000000000000000000000a16202b343d434749535761686b6c6c66635b5146464b515357565e61666a6c6c6a66605d56514c46423b3328231c140c020000000000000c1825313d48535d656866615e56544f4745403a37312c28231c1a140f0b0600000000000000000000000000000000000000000000000000000000000000000000000000000007101b242d363e474f585f666d737c82878e92989b9ea2a9a6a8aaa8a7a6a6a6a7a8a9a8a6a8a19e9a97928c86807a716c615e564d453c342b22190e0500000000000000000000000000000000000009121b222a313940454d53555d6065666d6f72747677787979797877767573716e6867625f5853504a423d342e271e170e0500000000000000000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d211408000814212d3945505a61646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a675f564b3f33271b0e000d1925323d49545e66696c6c69665e54493d3225190d0000000000000000000000000000000000000000000000000000000000000000010d1a2734404d5a6773808d9aa6a5988b7e7265584b3f3225180c00000000000000000000000000000000000000000000000a151f2831383e42434646464643505a616e7b86929fa7a2978d817476828f99a3a79f92867b6e61594f434646464644423e3931291f150b000000000000000000000000070f171e24282b2c2d2d2d2d2d2d2d23221f1b160f0700000000000009121920262a2c2c2d2d2d2d2d2d2d2d1f1c18120b030000000000000000000000000000070f161b2022232c2d2d2d2d2d2d2d2c2322201b160f0700000000000000000008141e29323b4146535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535345403a31281d130700000000000000000000020a1117202930363b4246484e5355585b5d5e5f5f5f5f5e5d5c5a5754524c47454039342e261e180f070000000000000000000815212d3945505a62646c6c6c6c6c6c6c68655d53483d3124180c00000000000000000000000000000b1824303c48535c64676c6c6c6c6c6c6c64625a5045392d21150800000000020f1b27333f4b5660676b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6861574c4034281c0f0300000000000000000000000000000000000000000002050a0f121515181b1d1e1f20201f1f1d1b19161312100c07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d111314191c1b19150f090200000000000000000000000000040f19222b32373b3c505c6873787979736d63574b434750555d60686d7276787977736d685f584e443b31292117110a02000000000000000e1b2734404d59656f75726d6863605953514b47433c38342e2a251f1b17110d08020000000000000000000000000000000000000000000000000000000000000000000000050e19222d363e485059616a6f7980878f93999fa3aaabaaaaa29f9d9b9a9a999a9a9b9d9fa2aaa9aba9a19e98928d857e756d685f574e463c342a20170c030000000000000000000000000000000009121b242c343c434b51575e61676d7175797c7f81838485858685858483817f7d7a77736f6a64605b544f454039302920170f05000000000000000000121f2c3845525e6a7579797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979716c6155493c3023170a000a1723303c4955616c71797979797979797979797979797979797771675b4f43362a1d10000f1c2835414e5a66707679797670665a4e4135281c0f0200000000000000000000000000000000000000000000000000000006050403020d1a2633404d596673808c99a6a4978b7e7164584b3e3125180b0203040506000000000000000000000000000000000000030d161f272d323536393935404b55616c75828f98a2a79f92857a6d6e7c87929fa9a2988f82756c61554b403539393736322d271f170d0300000000000000000000000000060d13181c1e1f202020202020201615130f0a040000000000000000080f151a1d1f20202020202020202013100c070100000000000000000000000000000000040b101316161f202020202020201f161613100b0400000000000000000000020d1720293036393b4646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464639352f281f160c01000000000000000000000000060e171e252a31363a3c4347484b4e50515253535252514f4d4a4746413a39352f28231c150c060000000000000000000005111d29343e48505658606060606060605b59534b41372c20140800000000000000000000000000000814202b36414a53585a60606060606060585650483e34291d110500000000000b17232e3a444e565c5e60606060606060606060606060606060606060606060606060606060606060605f5d574f453b2f24180c00000000000000000000000000000000000000000000000000030608090c0e10121213131212100f0c09070604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010507070c0f0e0c09040000000000000000000000000000000007101920272b3845525f6b788586867f7366574d4e535a61676d727a7f83858584807a6f6a5f564d42362a1f14080000000000000000000f1b2835424e5b6875817f7a756f6b65605d55534e4644403936302b27221b19130f0a040000000000000000000000000000000000000000000000000000000000000000020d17202b343e48505a616b707c838c92999fa4abaca7a09d999892908f8d8d8d8d8d8f909298989c9fa4abaaa29f97928a827a6e6960584e463c32291e150b00000000000000000000000000000008121b242d363e464e555d60696e74797e8285898b8d8f91919293929291908e8c8a8784807c76716c666059514b433b332921170e05000000000000000013202c3946535f6c79878686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867e7164574a3e3124170b000b1724313e4a5764717d8686868686868686868686868686868684776a5e5144372b1e1100101c2936434f5c69768286868276695c4f4336291c10030000000000000000000000000000000000000000000000030608091211100f0e0d1926333f4c5966727f8c99a5a4978a7d7164574a3e3124170d0e1011121307060401000000000000000000000000000000040d151c2226292a2d2c3945515d67707d8a949eaaa0958b7f72686a73808d97a1aa9e938a7d70675d51453c31262a2926221c150d0500000000000000000000000000000002070c0f11121313131313131309090703000000000000000000000004090e111213131313131313131306040000000000000000000000000000000000000000000307090a1313131313131313130a09070400000000000000000000000000050e171e252a2d2e393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939392c29241d160d040000000000000000000000000000050d14191f252a2d31373a3c3f41434445464646454442403e3a3936302c29241d17110a030000000000000000000000000c17222d363e45494b535353535353534e4d4841392f251a0f040000000000000000000000000000030f1a252f3841484c4e535353535353534b49453e362d22170c00000000000006121d28323c444b4f51535353535353535353535353535353535353535353535353535353535353535352504c453d33291e1307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070f161b2a3743505d6a7683908f8276695e54585f626c71797f858c909292908c857c6f695e52463b3025190e020000000000000000101d2a3743505d6a76838c86817c77726d67625f5853514a46423b37332d29241e1b15100c0701000000000000000000000000000000000000000000000000000000000009141f29323d46505a626c717d8690959fa3ababa49f9b95908c898584828180808081828385888b8f93999fa2aaa9a19e938f847b6f6a60584e443b30271d12070000000000000000000000000006101a242d363f4850585f676d737b80858b8f9298989a9c9e9e9f9f9f9e9e9d9b999795908d88837e786f6b605c554d453b332920170c030000000000000013202c3946535f6c798692939393939393939393939393939393939393939393939393939393939393939393939393939393939393938a7e7164574a3e3124170b000b1724313e4a5764717d8a93939393939393939393939393939184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000000000000040a0f1315161f1e1d1c1b1a1925323f4c5865727f8b98a5a3968a7d7063574a3d3024191a1b1c1d1e1f1413110d08010000000000000000000000000000030a11161a16202b37434e58606d7984919ea6a59d9083786d60606d7a85919ea6a59e9184796d60584e43372b20161a16110b0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d14191e20212d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d201d18130c040000000000000000000000000000000002080d141a1e21262b2e2f323436383939393938373633312e2d2a25201d18120c06000000000000000000000000000006111b242d34393d3e4646464646464642403d372f271d13090000000000000000000000000000000008131d262f363c4041464646464646463e3d39342d241b1106000000000000010c16202a323a3f434446464646464646464646464646464646464646464646464646464646464646464544403b332b21170d0200000000000000000000000000000000000000000000000000000000000000000000020608080c0f111213131312100e0c08070502000000020404060606060606000000000000000000000000000000000001040707131313131313130d0c0a07020000000000000000000000000002060808131313131313131310060603000000000000000000000000040a1b2835424e5b6875818e92877b6e6663646a6f767e848c92989d9f9f9d9791857b6e61564d41362a1e11050000000000000000101d2a3743505d6a768390928e89837e7a746f6a64605c54524d46443f3835302b271f1d18120e09030000000000000000000000000000000000000000000000000000030d1925303b444e58626c717e879298a0a7afa79f99938e88837f7c79777574737373747577797c7f83878d92989ea5ada59e9691857c6f6a5f564c42392e23180c030000000000000000000000030c18222c363f48505a616a6f7980868d92979c9fa2aaa7a9a8a7a6a6a6a7a8a9a8a6a7a09d9a94908a837c746d675e574d453b32291e150a0000000000000013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b000b1724313e4a5764717d8a979f9f9f9f9f9f9f9f9f9f9f9f9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000070f161b1f22232c2b2a2928272625323e4b5865717e8b98a4a396897c706356493d3025262728292a2b2c21201d19130c040000000000000000000000000000000508131e28323a47535f6a73808d96a1aa9e93897d70665c5d67717e8b949faba1968d80736a5f53473e32281e13080500000000000000000000000000000000000407090a13131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130a0907040000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080e1114142020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202013110d07010000000000000000000000000000000000000003090e12151a1f212225282a2b2c2c2c2c2b2a29272421201e1913100d07010000000000000000000000000000000009121b22292d3031393939393939393534312c251d150b0100000000000000000000000000000000010b141d252b3033343939393939393931302d29221b12090000000000000000040e1820282e33373839393939393939393939393939393939393939393939393939393939393939393837342f2921190f0600000000000000000000000000000000000000000000000000000000000000000003090e121415191b1d1f1f201f1f1d1b191514120e09030b0e10111313131313130b0b0905010000000000000000000001080d111314202020202020201a1916130d0700000000000000000000030a0f1214151f202020202020201c13120f0b0600000000000000000000000c1926333f4c5966727f8c998f8279727071757c838a91969fa2aaa3a3a9a1978e8174685e5246392d2014060000000000000000101d2a3743505d6a7683909d9b95908b85807b76716d66615e5753504945413a37322c29241d1a15100b060000000000000000000000000000000000000000000000010b151f2a36424d56606a717e889299a2aaafa49c959087817c77726f6d6668676766676768666c6f72767b80868e939fa3aaa8a09792867c6f685e544b40342820150900000000000000000000000b151e2a343e48505a626c717c848c92989fa2a9aca8a8a09e9c9a9a999a9a9b9d9fa3ababaaa69f9c95908781796e695e574d443b30261c110600000000000013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4978a7d7164574a3e3124170b000b1724313e4a5764717d8a97989898989898989b9ea6b0aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000007101920272b2e2f3938373635343331313e4a5764717d8a97a4a295897c6f6256493c3132333435363738392d2c29241e160d040000000000000000000000000000020c1924303a44505a626e7c87929fa8a2988e81756b605455606c78839099a4a89f92877c6f625a50443a3024190c03000000000000000000000000000000040b101316162020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020171614100b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205070813131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313060401000000000000000000000000000000000000000000000002050a0f121515181b1d1e1f20201f1f1e1c1a171413110d080401000000000000000000000000000000000000000911171d2124252d2d2d2d2d2d2d282724201a130b03000000000000000000000000000000000000020b131a202427272d2d2d2d2d2d2d2524211d17110900000000000000000000060e161d23272a2b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2b28241e170f070000000000000000000000000000000000000000000000000000000000000000060b0f151a1e212225282a2c2c2d2c2b2a282522211e1a1410171b1d1e202020202020181715110c060000000000000000040c13191d202d2d2d2d2d2d2d2d2625231e19120a0100000000000000060e151a1f21222c2d2d2d2d2d2d2d29201f1c17110a020000000000000000000a1623303d495663707c8998948f837e7d7e828790949ea1a19e9996979a9f9f92877b6e6154473b2d22170b0000000000000000101d2a3743505d6a7683909da7a09d98928d88837e79736e6963605b53524c47433c38352f2b261f1c17110e0802000000000000000000000000000000000000000007121d27313946525e696f7c86929aa3ababa39f928d837c756f6a6662605c545a5a5a5a5a545b606265696e747b818a9298a2a9a9a19891847a6e665c51453c31261a0e0500000000000000000007121d27303c46505a626c717e8691969fa2aaaba39f9b9796918f8e8d8d8d8d8f9092999a9ea1a9aba79f9a938d837b6e695e564c42382e23170c04000000000013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a978a7d7164574a3e3124170b000b1724313e4a5764717d8a8b8b8b8b8b8b8b8b8f939eaaaa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000000040f19222b32373b3c4544434241403f3e3d3d4a5763707d8a96a3a295887b6f6255483c3d3e3f4041434445463a39352f281f160c01000000000000000000000000000a141e2935414c56616c76828f99a3a89f92867b6e61594f505b656f7c87939fa9a3999082766c62564c4135291e150a0000000000000000000000000000070f161b2022232d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2323201c16100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030608090c0e10111213131312110f0d0b070705010000000000000000000000000000000000000000000000060c11151718202020202020201b1b18140f0901000000000000000000000000000000000000000001080f14181a1b20202020202020181715110c06000000000000000000000000040c12171b1d1e20202020202020202020202020202020202020202020202020202020202020201f1e1c18130d0600000000000000000000000000000000000000000000000000000000000000020a11171b1f262b2e2f32353738393939383735322e2d2b261f1c23272a2b2d2d2d2d2d2d2524211d181109000000000000040d161e24292c393939393939393933322f2a241c130a000000000000060f1820262b2e2f3939393939393939362d2b28221c140b0200000000000000000713202d3a4653606d7985929f95908b898b8f93999fa39f97918c8a8a8e9299998c7f7265544a3f33281c0f0300000000000000101d2a3743505d6a768390979d9fa7a29f9a94908a85807b75706c65605d56544e4745403937312b28231c1914100b040100000000000000000000000000000000000c18232f3943505a616e7b859198a3acaca399928b80786f6a625f585653504a4e4d4d4d4e4a505355575e61696e757e869297a2aaaaa1969082786d60574e42372b21170b0000000000000000000c18232e39424e58616c717f8a9298a0a8aba49f99928e8a8784828180808081828486898d92979ea1a8aca49f9590847b6e685e544a3f342820150a000000000013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8a7e7164574a3e3124170b000815222e3b4855616e7b7f7f7f7f7f7f7f7f7f818f9ba8aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000a16202b343d4347495251504f4e4d4c4b4a49495663707c8996a3a194887b6e615548494a4b4c4d4e4f5051524745413a31281e130800000000000000000000000006111c26303845525d68717e8b949faba1968c8073695e534749535f6a74818d97a2ab9f948b7e71685d52463d30261c110600000000000000000000000007111921272c2f303939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939302f2c27211a11080000000000000002080d101213131313131313130707040100000000000000000000000000000000000000000000000000030613131313131313131313120f0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005080a0b131313131313130f0e0c080400000000000000000000000000000000000000000000000003080b0d0e131313131313130b0a080500000000000000000000000000000001060b0f1111131313131313131313131313131313131313131313131313131313131313131312110f0c070200000000000000000000000000000000000000000000000000000000000000060b141b22272b31373a3b3f4244454646464543413f3b3a37312c282e33363739393939393932312e29221b120900000000010c1620282f35394646464646464646403f3b352e251c120700000000040d18222a31373a3b4646464646464646433938332d261d140a000000000000000006131f2c3845515c6774818d98a09d9896979b9fa49f99928d85807d7d818792998f8276665b5044382b1f1206000000000000000c1926323f4c5965727f858b90959b9fa3a69f9c97918c87827d78726d6862605853514b47423c38342e2a251e1b16110d0801000000000000000000000000000004101c2934404b55616c76828f97a1aaafa49a92877e736d665f58534e4946443f41404040413f4446484d53565e616c717c859298a2aca89f948d80736a5f53473e33281c10040000000000000004101c2834404b545f6a717e87939fa2aaa9a199938e86827e7a777574737373747577797c80858b91969da5afa79f9691847a6e665c50443c32261b0f040000000013202c3946535f6c7986929facb3a79a8d80808080808080808080808080808080808080808080808080808080808080808080808080807c6f6255483c2f221509000714212d3a46535f696e7272727272727272727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000030f1b27323d464e54565f5e5d5c5b5a595857565556626f7c8995a2a194877a6e615455565758595a5b5c5d5e5f54524c433a2f24190d0100000000000000000000000b17232e38424e58606d7a85929ea6a69e9184796d60574d42414e58616d7a85929ea7a69e92857a6d61584e42382e23170c0200000000000000000000040f19232b32383b3d46464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646463d3c38332c231a10050000000000060d14191c1f1f202020202020201413110d0801000000000000000000000000000000000000000000060c1012202020202020202020201e1b161009010000000000000002080d101213131313131313090806030000000000000000000000000000000000000000000000010407071213131313131313131313120f0a050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f181d262d33373c4247484c4e505252535252504e4c4846423c3834393f43444646464646463e3d3a342d241b110600000008131e28323a414553535353535353534d4b4740372e24190d020000010c161f2a343c43474852535353535353534f46443f382f261c11060000000000000004101c2834404b55616e7b86929fa4a5a3a4a7a09d948f868079737070747d87939285796c605346392d201306000000000000000b1825313e4a57626d72797e83898e92999ea1a8a19e99928f89847f7a746f6a65605d55534d46443f3836302c27201d19130f0a0400000000000000000000000006131f2c3845515c67707d8a949fa9b0a69f93887e716c605c544e47433c3a38342e3433342d3338393c42464d525a616a6f7c86929aa4afa69f92877b6e62594f44392d20150a0000000000000006131f2c3845515c666f7c869299a4aea8a0979187817b75716d6869676766676768676d7073797e848e939fa4aca8a0969083786d60584e43372b20150a0000000013202c3946535f6c7986929facada0938679737373737373737373737373737373737373737373737373737373737373737373737373736f6a5f53473a2e2115080005121e2a36424d575f616565656565656566727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000006131f2b37434e5860626c6b6a696867666463626160626f7b8895a2aa93867a6d606162636465666768696a6b6c605d564c4135291d11040000000000000000000003101c28343f4a54606a74818d97a1ab9f948a7e71675d51453b3c46525e68727e8b95a0aca1978e81746a60544a3f34281f1409000000000000000000000b16212b353d44484953535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534a48443d352c21160b000000000810181f25292b2c2d2d2d2d2d2d2d2d201d19130c04000000000000000000000000000000000000030a11171c1f2d2d2d2d2d2d2d2d2d2d2b27211b130a010000000000060d14191c1f1f2020202020201515120f0a030000000000000000000000000000000000000001080d1113141f202020202020202020201e1b161009010000000000000004090e1112131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130b0a0804000000000000000000000001060b0f111113131313131207060300000000000000000000000000000000000000000000000000000000000000000000060606060606060503000000020608080c0f111213131312100e0b08070502000000000000000000000000000000000000000000000000000008111a212a2f383f44464d5355585b5d5f5f605f5e5d5b5855534d46443f444b4f515353535353534b4a453f362d22180c0100010d19242f3a444c525f606060606060605957524940352a1e1307000007131d28313c464e53555f606060606060605c53504a42382d22170b00000000000000000c18232e3946525e69727f8b929b9e9f9e9b959089827b736d6763646b74818e98887b6e6255483b2f221508000000000000000916222e3a46515b62676d71777c81868c91969c9fa6a39f9b96918c86817c77716d67615f5753504a46413b38322c29241e1b15100c0700000000000000000003101c28343f4a54606d7984919ea6b0aa9e948c7f736c625a504a423c37322d2c282327272722282b2d31363b42465058606a707e88939fa8aea3998f82766c6155493c31261b0f00000000000004111d2935414b55606d79839098a3aba9a09691857d746e6964615d565b5a5a5a5a555c6063666d7179818b939aa4afa89f958c80736a5f54473d32271b0f0100000013202c3946535f6c7986929facada093867a6d676767676767676767676767676767676767676767676767676767676767676767676767625f584e43372b1f120600020e1a26313b454d53555858585858585966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000815222e3b4754606a6f7877767574737271706f6e6d686e7b8894a1a39886796c6c6d6e6f7071727374767778796d685d5245392c201306000000000000000000030c19232b3844505c666f7c87939fa9a3998f82766c61554b403335414c56606c7883909aa4a99f93887c6f665c50443b30251a0d03000000000000000004101b27323d474f5456606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606056554f473d33271c1004000006101a222a3035383939393939393939392c29241e160d0400000000000000000000000000000000030c151c23282c3939393939393939393937332c251c1309000000000810181f25292b2c2d2d2d2d2d2d22211f1b150e060000000000000000000000000000000000040c13191d20212b2d2d2d2d2d2d2d2d2d2d2b27211b130a010000000000080f151a1d1f20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020171714110c050000000000000000040c12171b1d1e20202020201f1312100c060000000000000000000000000000000000000000000000000000000105090b0b13131313131312120f0c04090e121415191b1d1f1f201f1f1d1b181414110e0802000000000000000000000000000000000000000000000008111a232c333c41495053575f6265686a6b6c6c6c6b6a6865615f5753504a4e565b5e606060606060585650483f34291d11050004111d2935414c565d6c6c6c6c6c6c6c6c66635b52473b2f23160a00071018242f3a434e585f626c6c6c6c6c6c6c6c69605b544a3f33281c0f030000000000000007121d2a36424d56626d7380898f9292918f8a837d766e69605d5559626f7c89988a7d7063574a3d3024170a0000000000000006121e29353f4951555c60646a6f757a7f848a8f949a9fa2a8a09e98928e88837e79736e6964605c54524c48443d39352f2b261f1c18120b030000000000000006121f2b3844505c66727f8c96a0acaea2988f82776c605a50443f38302b26201f1c171a1a1a171c1f20252a30363e464e58616c73808d96a1acab9f948a7d7064584e43372b1d120700000000000613202c3945515d67737f8c95a0aaada19791847b706b615e5754524c4e4d4d4d4e4b5153545c60676d747f88939fa5afa79f92877c6f62584e43372b1d120700000013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a55534e463c31261b0f03000009141f2a333b4246484c4c4c4c4c4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000916232f3c4956626f7c8584838281807f7e7d7c7b7a79787a8794a19f92867978797a7b7c7d7e7f8081828384867a6d6054473a2d2114070000000000000000000b151e2a36414d56606d78839099a4a99f92877c6f625a5043392f303a44505b666f7c87939faaa49a9083786d60574d42362a1f150b01000000000000000713202c38444f5960636c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6361594f44382c20140700020d18222c343b414446464646464646464639352f2820160c010000000000000000000000000000000a151e262e343846464646464646464646433e372e251b1005000006101a222a303538393939393939392f2e2b2620181006000000000000000000000000000000040d161e24292c2d383939393939393939393937332c251c13090000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c171008000000000000060e161d23272a2b2d2d2d2d2d2c201f1c17110a03000000000000000000000000000000000000000000000000060c111517182020202020201f1e1c1810151a1e212225282a2b2c2d2c2b2a282521201e19140f0a040000000000000000000000000000000000000000060f1a232c353e454d535b6064696e72757778797979787674726e6964605c545660676a6c6c6c6c6c6c65625a50453a2e211509000713202c3945525d687679797979797979736d63574b3f3225190c050e19222935404b555f6a6e7979797979797979766c665b5044382b1f120600000000000000000e1925303b44515b636e737d82858684827d78706b625f57514b53606d788686867f7265584c3f3225190c00000000000000010d18232d373f434b5153586062686d73787d82888d92989da0a8a29f9b95908b85807b76706d66615e56544f4745413a37312c28231d150c030000000000000713202d3a4653606d7884919ea8b2a99f92867b6e655b50483e342e261e1b1312100c060d060b0f12131a1f252a343d46505a606d7984919ea8b0a69c8f83766a5f5347392e23180c00000000000714212d3a4754606d7a85929fa7b0a69e92857b6e696059524d47464141404040414045464b51555d606d727f8b939ea9afa3998f82766a605447392f24180c00000013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4847433c342a20150a000000030e18212a31363a3b3f3f3f3f3f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000916232f3c4956626f7c8991908f8e8d8c8b8a898887868583919daa9f92878385868788898a8b8c8d8e8f9091877a6d6054473a2d211407000000000000000007121d27303946525e68727f8b95a0aba1978d80746a5f53483e312728333f4a54606b74818e98a2aca0958c7f72695e52463e31271d1207000000000000000916222f3b4854606b707979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979706b6155483c2f2316090008141f2a343e464d5152535353535353535345413a32281e1308000000000000000000000000000006111c2630383f44535353535353535353534f4940372c21160a00020d18222c343b4144464646464646463c3a37312a22180e0300000000000000000000000000010c1620282f35393a4546464646464646464646433e372e251b1005000008121b242b3136383939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393931302d28221a120800000000040e1820282e3337383939393939392d2c28231c150c03000000000000000000000000000000000000000000000911181d2124252d2d2d2d2d2d2c2b28241c1f262b2e2f32353738393939383735312e2d2a251f1b150d07010000000000000000000000000000000000020b18212c353e474f575f656c71767b7f8183858586858583817f7b77716d665f58677277797979797979716c62564a3d3124170b000714212d3a4754606d7a86868686868686807366594d4033261a0d0b16202b343d45515d676e7c868686868686868682796c605346392d201306000000000000000009141f29323f49525c636b707578797875706c656059534d4544505c6674797979726d62564a3e3124180b000000000000000007111b252d31394045474e54565e61666d70767b81858b91959b9fa3a79f9d97928d87827d78736e6863605954514c47433c38342e271e150b000000000005111e2a36414c5664707d8a96a1adada1978c7f72695e53493f3628231c140c0a060300000000000306090e1419222b343e45515d67717e8a96a0acab9f94887c6f62544b4034281c100400000006131f2b37434e5866727f8c97a2adaa9e948a7d70695f574f46423b3935303433342e34383a40454b515b626d74818e97a1adab9e94897c6f62554b4035291d1004000013202c3946535f6c7986929facada093867a6d6053474040404040404040404040404040404040404040404040404040404040404040403c3a37312a22180e0400000000060f181f262a2d2e323232333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000916232f3c4956626f7c89959d9c9b9a99979695949992919195a0aca399929091929995969798999a9b9c9d93877a6d6054473a2d21140700000000000000000c18232e39424f59616e7b85929fa7a79e92857a6d60584e43362c1f222d38424f59616e7a86929fa7a79f92867b6e61594f43392f24180c030000000000000a1623303d495663707d86868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867d7063564a3d3023170a000d1925303b4650585d5f606060606060605f524c443a2f24190d01000000000000000000000000000c17232e38424a505f60606060606060605f5a52493e33271b0f0008141f2a343e464d51525353535353534847433c342a20150a0000000000000000000000000008131e28323a41454752535353535353535353534f4940372c21160a00040f19242d353d4245464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646463e3c39332c241a10050000010c16202a323a3f43444646464646453a38342e261e150a00000000000000000000000000000000000000000009121b22292e313239393939393939373430282c31373a3b3f4244454646464543413e3b3936302b272018130c04000000000000000000000000000000000a141d2a333e474f5961696e787e83888b8e909292939291908e8b88837e786f6a606a77848686868686867e7165584b3e3225180b000714212d3a4754606d7a8793939393938c807366594d4033261a0a141d28323d46515b606d798391989393939991847a6d665b5044382b1f12060000000000000000020d17202d37404952596063686b6c6b6864605b534f47423c3f4a545c6a6c6c6c65625b51463a2e2215090000000000000000000a131b1f272f34383d43474c52545c60646a6e747a7f84898f92999ea1a9a29f9a938f8a847f7a75706b65605d55534e4645403930271d1207000000000714202d3946525e6876828f9ca8b2ab9e9185796d60574d41382d2417110a02000000000000000000000002091019222935404b55606c7884919dabb0a69a8e8174665c5145382c1f13060000000815222e3b4754606a7884919ea9b1a79c8f82756c61574d453d36302d292427272723282c2e343a4145515b606d7a85929eaab0a69b8e8275675d5145392c1f1306000013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343434342f2e2b2620181006000000000000060e141a1e2122252526333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000916232f3c4956626f7c8995a2a7a6a5a4a3a2a1aaa29f9e9da0a7b1aba39f9d9e9fa2aaa2a3a4a4a5a6a7a093877a6d6054473a2d2114070000000000000004101c2834404b54606b75818e98a2aca0958b7e72685d52463c31241a1c262f3d46525e68727f8c95a0aca2988e81756b61554b4035292015090000000000000a1623303d495663707c89939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393897d7063564a3d3023170a00101c2935414d5862696c6c6c6c6c6c6c6c6c5d564c4135291d110400000000000000000000000003101c28343f4a545c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e12000d1925303b4650585d5f60606060606055534e463c31261b0f030000000000000000000000030c19242f3a444c52545e6060606060606060605f5a52493e33271b0f000915202b353f474e52535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534a49453e362c22170c000006121d28323c444b4f5153535353535246443f3830261c11060000000000000000000000000000000000000006111b242d343a3d3e4646464646464544403b34383c4247484c4e505252535252504e4b4746413b373229241d160d05000000000000000000000000000006111b262f3c454f59616b707b838a9095989b9d9e9f9f9f9e9d9b9895908b837c706b67798592939393938a7d7164574a3e3124170b000714212d3a4754606d7a87939f9f9f998c807366594d4033261a111c262f3a444e58626d75818e95a0aaa59f92877c6f685e544a3f33281c0f03000000000000000000050e1b252e3740474f54565c5f5f5e5c57535049413d373138424a50535f6060585651493f34291e1206000000000000000000010a0d151d23292c32383a41464a5053585f62676d72777d82878d92979d9fa7a49f9c96918c86827c77726d67625f5853514b42392e23180c000000000814212e3b4754616e7a87939facafa3998c7f72675d51453b2f261b1206000000000000000000000000000000071018242f3944505b66727e8b99a3aeac9f9285796d6053463a2d2013080000000916222f3c4955626f7c8896a1acaca095897c6f625a50453b332a25201d191a1a1a181c1f23282f353f45515d67727f8b98a2aeac9f9286796d6053473a2d201406000013202c3946535f6c7986929facada093867a6d6053473a2d2727272727272727272727272727272727272727272727272727272727272722211f1b150e06000000000000000003090e121415191926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000916232f3c4956626f7c89959b9a999998979695949892919095a0aba39992909192989495969798999a9b9c93877a6d6054473a2d211407000000000000040d1a242c3845515c66707d89939eaaa59d9083786c60564c41342a2012141d2a36414c56606d7883919da5aa9e938a7d70675d51453c31261a0d0400000000000a1623303d495663707c89969f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f96897d7063564a3d3023170a00121f2b3844515d6974797979797979797976685d5245392c20130700000000000000000000000006121f2c3844505c66767979797979797979766c5f5346392d201300101c2935414d5862696c6c6c6c6c6c6c625f584e43372b1f120600000000000000000000000b151e2935414c565d606b6c6c6c6c6c6c6c6c6c6c645a4f43372b1e12000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060575550483e33281c1104000b17232e3a444e565c5e60606060605f53504a42382e23170c000000000000000000000000000000000000010c18222d363f454a4b53535353535352504c454044464e5355585b5d5e5f605f5e5d5b5854524d47433d352f281f170f05000000000000000000000000000b17222d38414d57616b707d8690959d9fa7a8aaaaa39f9e9e9e9fa3a09d9590867d706d798698a29f9f96897d7063564a3d3023170a000714212d3a4754606d7a8793a0aca6998c807366594d4033261a17222d38424c56606a727f8b939ea8a79e938b7f726a60564c42382d22170b000000000000000000000009131c252e353d4448494f5253514f4a46443f382f2b2630383f44465353534c4a463f372d23180d010000000000000000000000030b12181c1f272b3036383f44464e53555d60656b70757b80858b90959b9fa3a8a19e99928e89847f7a746f6a64605c544b4034281c10040000030f1b27333f495364717e8b9aa4afac9f92867a6e61554b4033291d140a000000000000000000000000000000000007121d28333f4a54616d7a86929facaea298897d706356493d2f24190d0100000d1a2633404d596673808c99a8b2aa9d9083776a6054483e332a211a14110d080d070c1013181d242935414c55606d7985929fabaea2988a7d7164574a3e2e23170b000013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1515120f0a040000000000000000000000020507080c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000916232f3c4956626f7c89908f8e8d8c8b8a898887868584839099a49f9287838485868788898a8b8c8d8e8f90877a6d6054473a2d2114070000000000010c161f2a36424d57606d7984919da5aa9e93897c6f665b50443a3022180e0b1925303b44515c66707d89939eaaa59e9184796d60574e42372b20160c01000000000a1623303d495663707c8996a3acacacb5afaca7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a396897d7063564a3d3023170a00131f2c3946525f6c7986868686868686867a6d6054473a2d2114070000000000000000000000000713202d3a4653606d788686868686868686796c605346392d201300121f2b3844515d697479797979797979766a5f53473a2e2115080000000000000000000007121d27303945525d686d78797979797979797979766c5f5346392d201300111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d211408000f1b27333f4b5660676b6c6c6c6c6c6c605c544a3f34281c1003000000000000000000000000000000000005111d29343f485056586060606060605f5d574f4a5153575f6265686a6b6c6c6c6b6a6864615e56544e45413a312921170f050000000000000000000000030f1b27333f49535f69707d8792989fa7aba7a09d9898929191919299989d9f9892877d707a8794aab4a396897c706356493d3023160a000714212d3a4754606d7a8793a0ada6998c807366594d403326172128333f4a545e686f7c87929fa5aaa0958e81756d62584e443a2f261c11060000000000000000000000010a131c232b33383c3d42454645423d3937332d261d1e262e34383a4646463f3e3a342d251b11060000000000000000000000000001070c10161b1e252a2e34383c43474b5154596063696e73797e83888e92989ea1a8a39f9b95918b85817c76716d665c5145382c1f1306000005121f2b3744505b6575818e9bacb6a99c8f8276685e5243392f21170b020000000000000000000000000000000000010b17222d3846525d6875828f9ca8b4aa9a8d807367564c4135291d11040005111e2a36424d576976838f9ca9b5ab998c7f7366584e43362c21180f0905010000000004070c1319242f3a45515d6774818e9aa7b4aa9b8e817468544a3f34281c10030013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0908060300000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000916222f3c4955626f7c83838281807f7e7d7c7b7a7978777887939f9e9184787879797a7b7c7d7e7f80818283847a6d6054473a2d211407000000000007131d28313a46535f69737f8c96a0aca2988e81756b60544a3f32281e100608141e2834404a54606b75828f98a2aca0968c80736a5f53473e32281e1308000000000a1623303d495663707c8996a7b1bbb5aba39f9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a96897d7063564a3d3023170a00131f2c3946525f6c7985929393939393877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693939393939386796c605346392d201300131f2c3946525f6c79868686868686867c6f6255483c2f221509000000000000000000000c18232e39424f59606d7a85868686868686868686796c605346392d201300121f2c3845525e6a7579797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979716c6155493c3023170a00111d2a37434f5c6772777979797979786d665c5044382c1f120600000000000000000000000000000000000915212e3a45505a62656c6c6c6c6c6c6c696157545c60646a6e72757778797979787674716e68626058514b433b332921170d030000000000000000000005121f2b3744505b656e7b859299a2aaaaa39f95918b888584848586888b90959e9992857b7b8894a1aea295897c6f6256493c2f231609000714212d3a4754606d7a8793a0ada6998c807366594d4033261e29333b44505b666d7a849199a3aea2989083796d605b51463d32281d140a00000000000000000000000000010a111921272c2f303538393835312d2b27221b14151c23282c2d39393932312e29231b13090000000000000000000000000000000000040a0f13191c23282b31373a4145474f54575e61676d71767c81868c91969c9fa4a7a09d98928e88837e796d6053463a2d20130700000613202d394653606c7885929eabb3a9988b7f7265564c4131271d0f050000000000000000000000000000000000000006111c2935414c5665727f8b98aab4aa9d918477685d5245392c201306000714202d3a46525e697885929eabafa399897c6f6256493d32231a0f060000000000000000000108131e2935404b5564707d8a97a9b3aa9d908377665c5044382b1f12060013202c3946535f6c7986929facada093867a6d6053473a2d201407010101010101010101010101010101010101010101010101010101010000000000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000815212e3b47535f6a6f77767574737271706f6e6e6d66667885929e9d9083766b676d6e6f7071717273747576776d675d5145392c20130600000000020b18242f3a43505a616e7b86929fa8a89f92867b6e61594f42382d20160c00020c18232e39424f59616e7b86929fa8a89f92867b6e625a50443a2f24190c020000000a1623303d495663707c8995a0a9b3afa399928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d897d7063564a3d3023170a00131f2c3946525f6c7985929f9f9f9f93877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d7986939f9f9f9f9386796c605346392d201300131f2c3946525f6c79859293939393887b6f6255483c2f22150900000000000000000005101c2834404b54606b74818e979393939393939386796c605346392d20130013202c3946535f6c79878686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867e7164574a3e3124170b00111e2b3844515e6b7784868686868686786d6053463a2d20130800000000000000000000000000000000000b1724313d4a56626c71797979797979787369585f666d71777b7f8183858586858583817e7b756f6a605d554d453b33291f150b010000000000000000030f1b27333f4953606c77829097a2abaaa398928b837f7b79787778797b7f83899196978f827c8895a2aea295897c6f6256493c2f231609000714212d3a4754606d7a8793a0ada6998c807366594d40332627303b454f59606c78828f96a1aba49f92857b6e675d51493f342b20160b02000000000000000000000000000000070f161c202223292c2c2b2924201f1b17110a0a11171c1f202c2d2d2524221e181109010000000000000000000000000000000000000002080d11171c1f262b2f35393d44484d53555c60646a6f747a7f848a8f939a9fa2aaa29f9a94908a8376695d5043362a1d1000000815222e3b4855616e7b8897a1adada197887b6e6255483b3022150b0000000000000000000000000000000000000000000d1924303c4855626f7b8898a2aeaca095877a6d6054473a2d211407000814212e3b4754616e7b8797a2adac9f92867a6d6053473a2d2014070000000000000000000000010d18242f3b4754616e7a8797a1adac9f9286796d6053463a2d2013070013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000006131f2b37434e585f626a69686766666564636261605c6a7784919d9c8f8275695c60616263646566676869696a605d554c4135291d1104000000000a141d2935404b55616c75828f98a3aca0968c7f73695e52473d2f261c0e04000007121c27303d46535e69737f8c96a0aca3998f82766c61564c4135291e140a0000000714202d3a4753606d79839097a2acac9f928780808080808080808080808080808080808080808080808080808080808080808080808080807b6e6255483b2f22150800131f2c3946525f6c7985929facaca093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929f9f9f95887b6f6255483c2f2215090000000000000000050e1b242c3845515c666f7c88939fa99f9f9f9f9f9386796c605346392d20130013202c3946535f6c798692939393939393939393939393939393939393939393939393939393939393939393939393939393939393938a7e7164574a3e3124170b000e1b2734414e5a6774818d93939398897c6f6356493c2f24190d01000000000000000000000000000000000b1825323e4b5865717e868686868686857866616a6f787e83888b8e909192939291908e8b86827c746d675e574d453b31271d1207000000000000000005121f2b3744505b65717e8a949fa9aea39892867f78726e6c656b666d6e72767d849094948c7f8c99a5afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033232e39424d57616b73808c949fa8a69d928a7e71695f554b40372d22190e050000000000000000000000000000000000050b101316161c1f201e1c1713120f0b060000060c101213202020191815120d06000000000000000000000000000000000000000000000000060b10151a1d24292c33383b42464b5153586062686d72787d82878d92989da0a7a69f9c9084776a5d5144372a1e1100000a1724303d4a5763707d8a96a9b3ab9e928578695f53473a2e2114030000000000000000000000000000000000000000000813202d394653606c7985929facb1a795897c6f6256493c2f231609000916232f3c4956626f7c8995a9b3aa9e918477675d5145382c1f13060000000000000000000000000714202d3946525e687885919eabaea398887b6e6255483b2f2215080013202c3946535f6c7986929facada093867a6d6053473a2d20140c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c070604010000000000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000030f1b26323c464e53555e5d5c5b5a595857565554535d697683909c9b8e8174685b535455565758595a5b5c5d5e54514c433a2f24190d0100000006111b262f3845515d67717e8a949eaaa69e9184796d60574d42352b1d140a000000000b151e2a36424d57606d7984919ea6ab9f948a7e71685d52453d30261c1106000006131f2c3945515d676e7b85929aa4afa3998e81747373737373737373737373737373737373737373737373737373737373737373737373736e695f53473a2e21140800131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f22150900000000000000020c16202b37424d57606d7983919aa4afacacacac9f9386796c605346392d20130013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b000a1724313d4a5764707d8a99a3aa998c807366564c4135291d1104000000000000000000000000000000000b1724313e4a5764717d8a939393939786796d6c707c838b9095989b9d9e9f9f9f9e9d9b99928f8781796e695e574d43392f24180c03000000000000000613202d394653606c7883909da6b0a79f92867d726c6662605b545c6062656b707a8290959286929facafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d40332834404b545e69707d88939fa6a99f948d80736c61574d43392f251b100700000000000000000000000000000000000000000407090a0f1213120f0a0605030000000000000306071313130c0b090601000000000000000000000000000000000000000000000000000000030a0f13181d20272c3136394045464e54565e61666c70767b80858b90959ca4aa9d9084776a5d5144372a1e1100000c1926323f4c5965727f8c98a5b2a99c8f837669574d42372b1e120600000000000000000000000000000000000000000006121f2b3844505b667783909daab1a4978b7e7164584b3e3125180b000a1723303d4a5663707d8996a3b0a99c90837669554b4035291d100400000000000000000000000005111e2a36414c566a7683909da9b4aa96897c6f6356493c302316090013202c3946535f6c7986929facada093867a6d6053473a2d2019191919191919191919191919191919191919191919191919191413110d0701000000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000a15202a343c43474951504f4e4d4c4b4a4948474f5b6875828e9b9a8d8073675a4d4748494a4b4c4d4e4f50514745413a31281e1308000000000b17222d38414e58606d7984919ea6ab9f948a7d70675c51453b3023190b0200000000030c1a25313b45515c67707d8a949eaba69e91857a6d60584e42382e23170b000004101d2935404b555f69707d88939fa6ab9d938b7e716a67676767676767676767676767676767676767676767676767676767676767676767625f574d42372b1e120600131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f2215090000000000000008131e28323a47535f69737f8c95a0acb6b8b9beac9f9386796c605346392d20130013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4978a7d7164574a3e3124170b000714212d3a4754606d7a86929fa99d908376685d5245392c201307000000000000000000000000000000000a1723303d4a5663707d89969f9fa994877a6d707e8690959da09e9c9b9a9b9c9ea1a9aba39f9a938e847b6e695e554b403529201509000000000000030f1c28333f4a5463707d8995a0acab9f958b7e716b605b5453504a5053555961686d798391999299a3aeafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033343c45515c666e7b85929aa4aba1979082786d605a50453c31271d1309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070d11161c1f252a2e34383c43474c52545b6064696e747a7e838c929caa9d9084776a5d5144372a1e1100000e1b2834414e5b6774818e9aa7b3a79a8d8074675a4d4131261a0e02000000000000000000000000000000000000000000030f1c28333f4a546875818e9ba8b3a6998d8073665a4d4033271a0d000b1724313e4a5764717d8a97a4b0a89b8f8275685c4f422f24180c00000000000000000000000000010d192530424f5c6875828f9ba8b0a3968a7d7063574a3d3024170a0013202c3946535f6c7986929facada093867a6d6053473a2d26262626262626262626262626262626262626262626262626262621201d18130c040000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000000040e18222a32373b3c44434241403f3e3d3c3b414e5a6774818d9a988c7f7265594c3f3c3d3e3e3f40414243443a39352f281f160c01000000030f1b27333f49535f6a73808d96a19fa3998f82766c61554b4033291f100700000000000009141f2934404b55616c76828f99a39fa1978d80746a60544a3f34281c100300000c18242f39434d57616b73808c949ea8a59f92867c6f685d545a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a55534d453c31261a0e0200131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f221509000000000000030d1925303a44505a616e7b86929fa7afacabadb3ac9f9386796c605346392d20130013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a978a7d7164574a3e3124170b000613202c3945515d677683909ca99f92867a6d6054473a2d211409000000000000000000000000000000000a1623303d495663707c8996a3aca195887b707e8792989e9896918f8e8d8e8f91979b9fa4aca49f9691847b6e675d51453c31261a0f02000000000006121f2b3844505b6674818e9ba7b1a99d9083766d6259504a46443f4446484f565d676f7c87929fa3abb4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d40313c46505a606d78839097a2aca39991857a6e665c50483e332a1f150b00000000000000000000000000000000000000000000000000000000000004080a0a1313131312110f0b070100000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f141a1d24292c32383a41464a5053585f62676d7279808c99a69d9084776a5d5144372a1e110000101c2936434f5c6976828f9ca9b2a5998c7f7266594c3f3326190900000000000000000000000000000000000000000000000b17222d404d5a6773808d9aa6b3a89b8e8175685b4f4235281c0f000b1825313e4b5864717e8b97a4b1a89b8e8275685b4f4235281c070000000000000000000000000000081b2835414e5b6874818e9ba7b0a4978a7d7164574a3e3124170b0013202c3946535f6c7986929facada093867a6d6053473a333333333333333333333333333333333333333333333333333333332d2c29241d160d0400000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000007101820262b2e2f37363534333332313033404d596673808c99978b7e7164584b3e313031323334353636372d2c29241e160d040000000005121f2b3744505b656f7c87929393939392877c6e625a5043392e21170d00000000000000030c18232f3943505a616e7b86929393939393877c6f665c5044382b1f1206000007121d27313b454f59606c78828f96a0aaa39891847a6d665b504d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4847423c332a2015090000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f2215090000000000010b151f2a36414c56626c76828f98a3aca49f9ea1a9b39f9386796c605346392d20130013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8a7e7164574a3e3124170b0004111d2935414c5566737f8c99a9a3998a7d7164574a3e31261a0e02000000000000000000000000000000091623303c4956636f7c8996a2afa295897c7c86929996918c8784828181818285888e939aa1a9a8a0969083796d60584e43372b1f140900000000000613202d394653606c7985929eabada1978a7d70645a50443f393734383a3d444c555f6a74818e9aa7b1bdafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d403a434e58616c74808d959fa9a59f92877d6f685e544a3f362c21180d0300000000000000000000000000000000000000000000000000000000050b10141617202020201f1e1b17120c0500000000000000000000000000000000000000000000000000000000000000000000000002080d11171c1f262a2f35383d43484c52545c60646a6e747a7e838c929caa9d9084776a5d5144372a1e110000101d2a3643505d697683909ca9b1a4978a7e7164574b3e3124180b0000000000000000000000000000000000000000000000061926323f4c5965727f8c98a5b2a89c8f8275695c4f4236291c0f000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2834414e5b6774818e9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3a39352f281f160c01000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000070e151b1f21222b2a29282726252425323f4c5865727f8b98968a7d7063574a3d30242425262728292a2b21201d19130c0400000000000613202d394653606c79838686868686868680736a5f53473e30271d0f05000000000000000007121d27313e47535f6973808686868686868683796d6053463a2d2013070000010b151f2a333e44505b666d7a849198a2aaa1968f82786c60594f45404040404040404040404040404040404040404040404040404040403b3a37312a21180e030000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f221509000000000007121d27313946525e68717e8b949faaa49a939297a1ad9f9386796c605346392d20130013202c3946535f6c7986929facb3a79a8d80808080808080808080808080808080808080808080808080808080808080808080808080807c6f6255483c2f22150900010d19242f3c4956626f7c8997a2ab9a8e817467574d42372b1e12050000000000000000000000000000000916232f3c4956626f7c8995a2afa396897d839098938d847f7b777574747476787c81889197a1a9a8a0958d80736a5f53473b30251a0e02000000000916232f3c4956626f7c8997a2adab9e9285796d6053463f332d2b282c2d323a434e58626e7b88959fabb8afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d40414b555f6a717e8a929da7a89e938c7f726b60564c42382e241a0f06000000000000000000000000000000000000000000000000000000000810171c2023242d2d2d2d2b2a28231e170f06000000000000000000000000000000000000000000000000000000000000000000040a0f13191c22282b3136394045474e54565e61666d70767b80858b90959ca4aa9d9084776a5d5144372a1e110000111e2a3744515d6a7783909daab0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4b1a99c908376695d5043362a1d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4745413a31281d1307000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000000000000040a0f1315161e1d1c1b1a19181724313e4a5764717d8a9795897c6f6256493c2f231718191a1b1c1d1e1413110d080100000000000005121f2b3744505b656c7679797979797979736e64584e43352c1e150b000000000000000000010b151f2b37424d57636e7379797979797979776d665c5044382b1f1206000000030d182128333f4a545d686f7c86929fa4a89f948c80736b61574d43392f343434343434343434343434343434343434343434343434342f2e2b2620180f06000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f22150900000000020b18232f39434f59616d7a85929ea6a99f938785929eab9f9386796c605346392d20130013202c3946535f6c7986929facada0938679737373737373737373737373737373737373737373737373737373737373737373737373736f6a5f53473a2e21150800000813202d394653606c7985929eab9e918478695f53463a2d2114060000000000000000000000000000000916222f3c4955626f7c8895a2afa89c8f828f9593888079726e6969686768696a6f747d859197a2ada79f92877c6e62574d42362a1e1205000000000c1926323f4c5965727f8c98a9b3a79b8e8174665c50443828221f1c1f2028313c47535f6a7683909da9b6afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d3f45515d676f7c86929fa4aaa0968f81756d62594f443b30261c12080000000000000000000000000000000000000000000000000000000008111a22282d3031393939393837342f2821180f05000000000000000000000000000000000000000000000000000000000000070c10151b1e24292d33383b42464b5153586062686d73787d82888d92989da0a7a69f9c9084776a5d5144372a1e110000111e2b3844515e6b7784919eaaafa396897c706356493d3023160a00000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1aa9d9083776a5d5044372a1d11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d605959595959595959595959595959595959595959595959595959595959595954514b433a2f24180d010000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000000000000000306080911100f0e0d0c0b1623303d495663707c899694877b6e6154483b2e21150b0c0d0e0f1011070604010000000000000000030f1b27333f49535b60696c6c6c6c6c6c6c67645c52463c31231a0c0300000000000000000000030d1a26313c45525c63666c6c6c6c6c6c6c6a605c544a3f34281c100300000000060f17222d38424c565f6a717e8b929da7a69f93887d70695f554b40352927272727272727272727272727272727272727272727272722211e1a150e0600000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f221509000000000a141d2934404b55606b74818e97a1ada1978e8183909da99f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d676767676767676767676767676767676767676767676767676767676767676767676767625f584e43372b1f1206000006121f2b3844505b6675828e9ba8a196887b6e6155483b2e23170c0000000000000000000000000000000916222f3c4955626f7c8895a2afaa9e948f9493887e736d67615e575b5a5b5860626b6f7c85929ea6afa3998e8175695e52463a2d201408000000020f1b2835424e5b6875818e9ba8b5ab988b7e7165544a3f342817121012161f2b37434e5866727f8c99abb5afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366595049515b606d79849198a2aea29891847a6d605b51473d32291e150a0000000000000000000000000000000000000000000000000000000005101a232c33393c3d464646464543403a332a21170c01000000000000000000000000000000000000000000000000000003090e12181c1f262b3035383f44464d53555d60656a6f757a7f848a8f949a9fa2aaa29f9a948f8a8276695d5043362a1d100000121f2b3845525e6b7885919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0aa9e9184776b5e5144382b1e11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6666666666666666666666666666666666666666666666666666666666666666605d554b4135291d11040000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000000000000000000403020100000915222f3c4855626f7b889598867a6d6053473a2d201407000102030304000000000000000000000000000b17222d38414950535d606060606060605a58524a40332a20110800000000000000000000000009151f2a33404a52585a606060606060605d53504a42382e23170b00000000000006111c262f3a444e58616c74808d959fa9a49a92857b6e675d51453f342b20171a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1514120e09030000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f22150900000006111b262f3845515c67707d89939ea9a69e91857a84919daa9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a55534e463c31261b0f030000030f1c28333f4a5465717e8b98a8a8988b7e7265544a3f34281c100300000000000000000000000000000916222f3c4955626f7c8895a2afb0a69e9c958c80736c605c55524d4e4e4e4e5459606a717e8a949fabab9f92877b6e6154483b3025190e02000005111d2a36414c566a7784909daaafa499887b6f6255483c2e23170603060d1a26313c4956626f7c8999a3afafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c80736b605b5358626d75818e96a0aaa49f92867c6f675d51493f352b20170c03000000000000000000000000000000000000000000000000000000000b17222c363e44494a5353535352504b453c33281e1207000000000000000000000000000000000000000000000001040b10141a1d23282c32373a41464a5053575f61676d71777c81868c91969c9fa6a7a09d98928d88837e786d6053463a2d2013070000121f2b3845525e6b7884919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0aa9d9184776a5e5144372b1e11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada09386797272727272727272727272727272727272727272727272727272727272727272726d675d5145392c2013060000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a879a928579675d5145392c2013060000000000000000000000000000000000000006111b262f383f444650535353535353534d4c4740382e21180e00000000000000000000000000030e18212e3840474b4d535353535353535046443f3830261c1106000000000000000a141d28323c46505a606d78839097a1aba2979083796d605b51463d32291e140a0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0808060200000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f2215090000000b17222d38414e58606d7984919ea5aa9e948a7e7885919eab9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4847433c342a20150a000000000b17222d3b4854616e7b8795a0a89b8f8275665c5044382c1f120600000000000000000000000000000916222f3c4955626f7c8895a2afb8b0a89d9083786d605a514b464241414143474f58616c76828f9ca9afa3998c7f7266564c41362a1e110500000713202d3946525e687985929facac9f9386796d6053463a2d20130600000913202d3a4653606d7986929facafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0adab9e91847d726c655d606a727f8b939ea8a79d928a7e716a5f554c41372d23190e050000000000000000000000000000000000000000000000000000000004101c28333e48505557606060605e5c564e453a2f23170b00000000000000000000000000000000000000000001080d11161c1f252a2e34383c43474c52545b6063696e73797e83898e92999ea1a8a39f9b95908b85807b76716d665c5144382c1f12060000111e2b3844515e6b7784919eaab0a396897d7063564a3d3023170a00000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a99d9083766a5d5043372a1d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb2a6998c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6054473a2d2114070000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7986939184786b554b4035291d100400000000000000000000000000000000000000000a141d262d3337394346464646464646403f3c362e261c0f060000000000000000000000000000060f1c262e363b3f4046464646464646443a38342e261e140a0000000000000000020b16202a343e44515c666e7b859199a3a9a0958e81756d62584e443a30261c11060001010101010101010101010101010101010000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f2215090000040f1b27333f49535f6a73808c96a0aca2988f82757985929fac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053474040404040404040404040404040404040404040404040404040404040404040403c3a37312a22180e04000000000614202d3a46525e697784919daa9f9285796d6053463a2d20130800000000000000000000000000000916222f3c4955626f7c8895a2afb9ada1968a7d71665c5045403936303432373d46505a63707d8a97a1adab9d908377685e5246392d20140700000714212e3a4754616d7a8798a2aeab9e918478675c5145382c1f1306000006131f2c3845515c667784919daaafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0adada19691877f776d68686f7c87929fa5a99f958d80746c61584e433a2f251b110700000000000000000000000000000000000000000000000000000000000814202d3944505a61646c6c6c6c6b6860564b4034281b0f0200000000000000000000000000000000000000040c13191d20272c3036394045464e54565d61666c70757b80858b90959b9fa3a8a19e99928e89837e7a746e6a64605c544a4034281c10040000111e2a3744515d6a7784909daab0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000c1825323f4b5865727e8b98a5b1a99c8f8276695c504336291d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a89c918c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877b6e6154483b2e2115080000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d79869a9184786b554b4135291d11040000000000000000000000000000000000000000020b141b22272b2d36393939393939393433302b241c140b000000000000000000000000000000000a141c242a2f323339393939393939372d2b28231c140c02000000000000000000040e18222834404a545e69707d87929fa5a79e938b7f726a60564c42382e23170f0600000000000000000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f22150900040d1a232b3744505b656f7c87929fa8a79f92867b6e7986939fac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343434342f2e2b2620181006000000000005121e2a36424d576774808d9aaaa298897c6f6356493c2f24190d01000000000000000000000000000916222f3c4955626f7c8895a2afb8ab9e9184786c60544a3f342f2a2527272b333e4653606c7885929eabaca095877a6e6154473b2e21140800000915222f3c4855626f7b8895aab4a99d9083766a554b4034281c1004000004101c2834404b546975828f9ca8afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0adb2a9a199928c827a6f6d7a849199a3aba1979083786d605a50463c31281e130a000000000000000000000000000000000000000000000000000000000000061623303c4955616c70797979797872685c5043372a1e07000000000000000000000000000000000000010a0d161e24292c33383b42464b5153585f62686d72787d82878d92979da0a7a49f9c96918c86817c77726d67625f5853514a42392e23180c000000101d2a3643505d697683909ca9b1a5988b7e7265584b3f3225180700000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685c4f4235291c0f000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9ada39c999999999999999999999999999999999999999999999999999999999999999994877b6e6154483b2e2115080000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8794928679675d5145392c201306000000000000000000000000000000000000000000020a11171b1f202a2d2d2d2d2d2d2d2726231f19120b0200000000000000000000000000000000020a12191f2326272d2d2d2d2d2d2d2a201f1c17110a020000000000000000000000061018232e39424d57606b727f8c939ea7a59f92877c6f685e544a3f342821180d04000000000000000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f221509010c161f2a36414c56606c77839099a3aba0958c7f726d7a879aa4af9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d2727272727272727272727272727272727272727272727272727272727272722211f1b150e06000000000000020e1a25303d4a5763707d8a98a3aa998c807366564c4135291d1104000000000000000000000000000916222f3c4955626f7c8895a2afb6ac9a8d8074665b5042382e231d1a1b1b212b3844505b6674818e9ba7b1a7978a7e7164574b3e3124180700000a1623303d495663707c8996a3afa89c8f8275695c4f422e23180c000000000c18232e414e5a6774818d9aa7afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0adbbb2aba39f948f847c78828f96a1aba49992857b6e665c51483e342a1f160c0100000000000000000000000000000000000000000000000000000002080e111724313d4a5764707d8686868684786b5e5245382b18120e09030000000000000000000000000000000a131c1f282f35393d44484d52545c60646a6f747a7f848a8f939a9fa2a9a19e9a938f8a847f7a756f6b65605d55534e4644403930271c12070000000f1c2835424f5b6875818e9ba8b3a6998c807366594d402f23180c00000000000000000000000000000000000000000000010e1b2834414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9b5ada8a6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a194877b6e6154483b2e2115080000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000000000000000000403020101000915222f3c4855626f7b889598877a6d6054473a2d2114070001020303040000000000000000000000000000000000060b0f12131d202020202020201a1917130e080100000000000000000000000000000000000000080e1317191a202020202020201d1312100b06000000000000000000000000000007121c27303b454f59626d75818e95a0aaa39991847a6d665c50443e332a1f160c010000000000000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f22150907121d28313946525e68727e8b949faba3999083786d6e7a8794a1b69f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1515120f0a0400000000000000000914202d3a4753606d7a86929fa99d908376685d5245392c201307000000000000000000000000000916222f3c4955626f7c8895a2afafa49a897d7063544a3f30261c120e0a0f1c28333f4a5465717e8b98abb5a69a8d8073675a4d402e23180c00000a1724313d4a5764707d8a97a3b0a89b8e8175685b4e4235281b0700000000071a2633404d596673808c99a6afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0adb8b0aaa9a69e969186828f949fa8a69f93877d70695e544b40362c22180d04000000000000000000000000000000000000000000000000000001070c14191b2227313d4a5764707d8a93939185786b5e52453828231c1a140d070100000000000000000000000007121c252e313a4145474f54575e61666d71767c81868c91969c9fa4a79f9d97928d87827d78726d6863605953514b47433c38342e271e150b000000000d1a2734404d5a6773808d9aa6b3a89b8e817568554b4034291c100400000000000000000000000000000000000000000005121e2a36424d576976838f9ca9b2a5988c7f7265594c3f3226190c000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f94877b6e6154483b2e2115080000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000000000000000206080811100f0e0d0c0b1623303d495663707c899694887b6e6155483b2e22150b0c0d0e0f10110707050100000000000000000000000000000003050610131313131313130d0d0b07030000000000000000000000000000000000000000000002070a0c0d131313131313131107060300000000000000000000000000000000000b151e29333d47515b606d79839098a2aba1968f82786d605a50453c31281d13070000000000000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070303030303030303030303030713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f2215090b18242f39434f59616e7a85929fa6a89f92877c6f666e7b8894a1ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d090806030000000000000000000006131f2c3945515d6776838f9ca99f92867a6d6054473a2d211409000000000000000000000000000916222f3c4955626f7c8895a2afac9f93867a6d6054473a2d21150a01000b17222d3c4855626f7b8899a4afa99c8f837669554b4034281c1004000b1724313e4a5764717d8a97a4b0a79a8d8174675a4e4134271b0e010000000c1926323f4c5965727f8c98a5afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0adb0a69e9c9fa2a199928f949ea6a89e948c7f736b60574d42392e241b10060000000000000000000000000000000000000000000000000000030b12181e252a2d33373d4a5764707d8a979e9185786b5e524538342e2a251f18120c0400000000000000000000020d19232e3740434c5154596063696e73797e83888e92989ea0a8a29f9a95908b85807b76706c66615e56544f4745403a37312c28231c150c03000000000c1925323f4c5865727f8b98abb5aa9d908477675c5145382c1f13060000000000000000000000000000000000000000000714212d3a46535f697885929fabb4aa968a7d7063574a3d3024170a000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a79d95939393939393939393939393939393939393939393939393939393939393939393877b6e6154483b2e2115080000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000000000000030a0f1214151e1d1c1b1a19181824313e4b5764717e8a9795897c6f6256493c2f231718191a1b1c1d1e1413110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c17202b353f45515d676e7b86929aa4a89f948d80736c61574e433a2f2418110700000000000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114101010101010101010101010101013202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f22150a141d2935404b55616b75818e97a2aca1968d80746a626f7b8895a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d20140701010101010101010101010101010101010101010101010101010101000000000000000000000000000004101d2935404b5566727f8c99a9a3998a7d7164574a3e31261a0e020000000000000000000000000916222f3c4955626f7c8895a2afaa9e918477675d5145392c20130300000613202d3a4653606d7986939facab9e918478675c5145382c1f1306000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e010000000c1825323f4b5865727e8b98a5afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0adaa9e948f9298a2a39f9c9ea6aaa1968f82776c60594f453b30271d12090000000000000000000000000000000000000000000000000000060d151d23293036383f44464a5764707d8a979e9185786b5e5246444039363029241d160d0600000000000000000006121e2a35404951555d60656b70757b80858a90959a9fa2a8a09d98928e88837e79736e6963605b54524c48433d39352f2b261f1c18120b030000000000091623303c4956636f7c8999a4afac9f9286796d6053473a2d22170b0000000000000000000000000000000000000000000815222e3b4855616e7b8897a2adaea298887b6e6155483b2e221508000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a2958b868686868686868686868686868686868686868686868686868686868686868686867b6e6154483b2e2115080000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000000060e151a1f21222b2a29282726252425323f4c5865727f8b98968a7d7063574a3d30242425262728292a2b21201d19130c0500000000000000000000000305060e101010101010090806030000000000000000010304060606060504030100000000000000000000000000000000000000000000000000000000000000000000000000000000050e19232935404b555f69707e88939fa6a69d928a7e716a5f554b40352923190e05000000000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d211c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f2215111c262f3845515d67707d8a939ea9a59e9184796d60626f7c8895a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18242f3c4955626f7c8897a1ab9a8d817467574d42372b1e12050000000000000000000000000916222f3c4955626f7c8895a2afa89c8f827569554b4135291d1104000006131f2c3845515c677884919eabac9f9386796d6053463a2d201307000b1825313e4b5864717e8b97a4b1a79a8d8074675a4d4134271a0e010000000b1825323e4b5865717e8b98a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada99c8f82869298a3aba9aaaea39891847a6d655b50473d33291e150b0000000000000000000000000000000000000000000000000000070f181f272f343b4146495053565964707d8a979e9185786b5e5753514a46423b352f281f180f0700000000000000000a16232f3b46515b63676d72777d82878d92979d9fa7a39f9b96918b86817c76716d67615f5753504a46413a38322c29241d1a15100c07000000000000000714202d3a4753606d7a86939facaea399897d706353493f33271b0f030000000000000000000000000000000000000004111d2935414c5565717e8b98a9b3ac9f9285786d6053463a2d201307000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867979797979797979797979797979797979797979797979797979797979797979797976695e52463a2d2014070000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000000060f1820262b2e2f37363534343332313033404d596673808c99978b7e7164584b3e313031323334353636372e2d2a251e170e050000000000000000060b0f12131b1d1d1d1d1d1d1615130f0a0400020507080b0e1011121313131211100e0b08070502000000000000000000000000000000000000000000000000000000000000000000000000071118242f39434d57616c73808d949fa8a49f92867c6e675d51453f352b20170c030000000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2929292929292929292929292929292929292d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f221517222d38424e58606d7984919ea5a99e938a7d70675d626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d20140c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c070604010000000000000000000000000000000713202d394653606c7885919eaa9e918477695f53463a2d2114060000000000000000000000000916222f3c4955626f7c8895a2afa79a8d8174675a4e412f24180d01000004101c2834404b556a7683909da9afa49a887b6e6155483b2e221508000b1824313e4b5764717e8a97a4b1a79a8d8074675a4d4134271a0e010000000b1825323e4b5865717e8b98a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807d869299a3abb5ac9f92867c6f685d53493f352b21170c0300000000000000000000000000000000000000000000000000071019212a313940454c52535b60636669707d8a979e9185786b6763605c54524d454039312921191007000000000000000c1925323e4b57636d737a7f84898f92999ea1a9a19e99928f89847f7a746f6a64605c55534d46443f3836302c27201d18130f0a040000000000000000000613202c3945515d677784909daab4ab9a8d8073655b5044372b1f140a000000000000000000000000000000000000010c13202c3945515d6775828e9ba8b5a89c8f8275665c5044382b1f1206000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5e574d42362a1e12050000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000000030e18222a31373a3b44434241403f3e3d3c3b414e5a6774818d9a998c7f7266594c3f3c3d3d3e3f40414243443a3936302920170c020000000000020a11171b1f202729292929292922221f1b150e090e111414181a1c1e1f20201f1f1e1c1a181514120e0904010000000000000000000000000000000000000000000000000000000000000000000007121d28313c45505a606c78828f96a1aaa2989183796d605b51473d33291e150b0000000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d6054473a36363636363636363636363636363636363636363a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f22151c28333f4a545f6a73808d96a1aca2978e81756b6155626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d2019191919191919191919191919191919191919191919191919191413110d07010000000000000000000000000005121f2b3744505b6575818e9baca096887b6e6155483b2e23170c0000000000000000000000000916222f3c4955626f7c8895a2afa6998c807366594d4033261a07000000000c18232e424f5c6975828f9ca8b6ac95897c6f6256493c2f231609000b1724313e4a5764717d8a97a4b0a79a8d8174675a4e4134271b0e010000000c1825323f4b5865727e8b98a5afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c80737d879299a4aca6998c80736a60584e453c332a21170f05000000000000000000000000000000000000000000000000060f19222b333c434b51565e61656c6f7375777e8a979e9184787674706d66615e57514b433b332b22190f060000000000000d192633404c5966737f868b91959b9fa3a69f9c97918c86827d78726d68625f5853514b46423b38332d2a251e1b16110d0701000000000000000000000004101d2935404b556773808d9aa9b3ab9e9184786c6053463c2f261b1106000000000000000000000000000000000007131d28333f4a54606d7a86929facb1a7988b7f7265544a3f34281c1003000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60606060606060606060606060606060606060606060606060606060606060605f524d453b30251a0e020000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000000a15202a343c43474851504f4e4d4c4b4a4948474f5b6875828e9b9a8d8073675a4d4748494a4b4c4d4e4f50514746413a32291e130800000000020b141b22272b2d343636363636362f2e2b262019141a1e20212527292b2c2c2d2c2c2b29272421211e1a14110d08020000000000000000000000000000000000000000000000000000000000000000010c161f2a333e44505b666d7a849198a3aaa0958e81756d62594f453b30271c120700000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d605447434343434343434343434343434343434343434343434653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f221a242b3844505b666f7c87929fa8a69f92857a6e615956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d26262626262626262626262626262626262626262626262626262621201d18130c04000000000000000000000000030f1b27333f495364717e8b9aa4a8988b7e7265544a3f34281c100300000000000000000000000916222f3c4955626f7c8895a2afa5988b7f7265584c3f3225190c00000000071b2835424e5b6875818e9ba8b0a396897d7063564a3d3023170a000a1724303d4a5763707d8a96a3b0a89b8e8175685b4e4235281b07000000000c1926323f4c5965727f8c98a5afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c8073717e87939aa4ab9e92857c6f6a5f574d453b332921170e0500000000000000000000000000000000000000000000040d18212b343c454d555c60686e73787c7f828486929fa196898482807d79746e69605d554d453d342b21180d030000000000101d2a3743505d6a768390989da0a8a29f9a948f8a84807b75706c65605d56544e4745403936312b28221c19130f0a040100000000000000000000000000010d18242f3d495663707c8997a1adaca196897d7063584e41382d22170f06000000000000000000000000000000071118242f3844505b66717e8b98a2aeaca095887b6e6155483b2e23170b00000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60535353535353535353535353535353535353535353535353535353535353534846423b33291f1409000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c10030000000000000000000000000000000000020f1a26313c464e53555e5d5c5b5a595857565554535d697683909c9b8e8174685b535455565758595a5b5c5d5e54524c443a3025190d010000000a141d262d333739414343434343433c3b37322a2220252a2d2e313436373939393938373634312e2d2a25201d19130d070100000000000000000000000000000000000000000000000000000000000000040d182128333f4a545e686f7c86929fa5a79e938c7f726b60574d42392e23181006000000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d60544f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f53606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f221f2a36424d57606c78839099a3ab9f948b7e71685e5256626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a333333333333333333333333333333333333333333333333333333332d2c29241d160d040000000000000000000000000b17222d3b4754616e7a87939fa89b8f8275665c5044382c1f120600000000000000000000000916222f3c4955626f7c8895a2afa5988b7e7265584b3f3225180c000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a000916232f3c4956626f7c8995acb6a89b8f8275685c4f422e23180c000000000d1a2633404d596673808c99a6afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c80736c717e88939fa3a19792857c6e695f574d453b332920170e050000000000000000000000000000000000000000010c161f2a333c464e575f676d737a8084898c8f919298a3a8a197918f8d8a85817b736d675f574e463d332a1f150b0100000000101d2a3743505d6a7683909da7a09d98928d88837d79736e6963605b53524c47433c38342f2a261f1c17110d080200000000000000000000000000000000000713202d3a4653606d7985929eacb2a89c8f82756a5f53493f332721180f0802000000000000000000000003091119232935404b55606c7884919daab3a99d908477695f53463a2d1c110600000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60534746464646464646464646464646464646464646464646464646464646463b3a36302921170d02000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1003000000000000000000000000000000000006121f2b37434e585f626a69686767666564636261605c6a7784919d9c8f8275695c60616263646566676869696a615e564c41362a1d1105000006111b262f383f44464e5050505050504947433c34292c30363a3b3e41434445464646454443413e3b3a36312c29241e18130c0400000000000000000000000000000000000000000000000000000000000000060f17222d38424c56606a717e8b939da7a59f92877d70695e544a40342822180d040000000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d605c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f2228313a46525e69727f8b959faba3999082776c60564c56626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3a39352f281f160c0100000000000000000000000614202d3946525e687783909daa9f9285796d6053463a2d20130800000000000000000000000916222f3c4955626f7c8895a2afa4988b7e7165584b3e3225180b000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b000815222e3b4855616e7b889aa4afa99d9083766a544b4034281c10040000010e1b2734414e5a6774818d9aa7afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c8073666c727f8b919ca4a19791857b6e695f574d453b322920170e050000000000000000000000000000000000000008131e28313c464e5860696e7980868d9196999c9d9fa3aaaba9a19e9c9a97928d8680796e6960584e453b31271d120700000000101d2a3743505d6a7683909d9b95908b85807b76716d66615e5753504945413a37322c29231d1a140f0b06000000000000000000000000000000000000000006121f2c3844505c6673808d9aa4afaa9e94887c6f655b50443d332a2219140e09060400000100000406090e141a232b353d45515d67717e8a95a0acada2978b7e7265574d42362a1e0a0000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a393939393939393939393939393939393939393939393939393939392e2d2a251f170f0500000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000814212e3a47535f6a6e77767574737271706f6e6d6d66667885929e9d9083766b666d6e6f7070717273747576776d685e5246392d20130700000b17222d38414950535a5c5c5c5c5c5c55544e463c35393b4246474b4d4f515253535252514f4d4b4846423b39353029241d160d070000000000000000000000000000000000000000000000000000000000000006111c262f3a444e58626c74818e959fa9a39991857b6e665c51443e342a20160b0200000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a6d696969696969696969696969696969696969696969696969696969696d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f242f3a43505a616e7b86929fa7a89f92867c6e655b504956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d60534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4745413a31281d1307000000000000000000000005111e2a36414c566773808d9aaaa298897c6f6356493c2f24190d01000000000000000000000916222f3c4955626f7c8895a2afa4988b7e7165584b3e3225180b000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b000714202d3a4753606d7a86939facab9e918478665c5145382c1f1306000004111d2935404b556976828f9ca9afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366626d727f8c929ca4a19791847b6e695e574d443b322920160e040000000000000000000000000000000000010d19242f3a434e58606a6f7b838c92989ea1a9a8aaa39f9e9e9fa3aaa8a9a29f98928d837b6f6a60574d43392f24180c03000000101d2a3743505d6a768390928e89837e79746e6a64605c54524d46443f38352f2b261f1c18120e09030000000000000000000000000000000000000000000003101c28343f4a54616e7b87939fabb0a69c9083776c60584e453c342a251e1a1312100c070e070c1013131a1f262a353d47505a606d7984919ea7b1a99f9285796d6053473b31261a0e0000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d21201e1a140d050000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000815222f3b4855626e7c83838281807f7e7d7c7b7a7978777887939f9e9184787778797a7b7c7d7e7f80818283847a6d6154473a2e21140700030f1b27333f49535b6067696969696969625f584e454045474d5254585a5c5e5f5f605f5f5e5c5a5754534d4745413a352f281f191109010000000000000000000000000000000000000000000000000000000000000a141d28323c46505a606d79839097a1aba1979083786d605a50463c32281d140a00000000000000000000000000000000000000131f2c3946525f6c7985929facada093877a767676767676767676767676767676767676767676767676767676767676788693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f2935414c55616c75828f98a2aca0968c80736a5f53494956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d605959595959595959595959595959595959595959595959595959595959595954514b433a2f24180d0100000000000000000000010d1925303d495663707d8998a2aa998c807366564c4135291d1104000000000000000000000916222f3c4955626f7c8895a2afa4988b7e7165584b3e3225180b000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b0006131f2c3845515c677885919eabac9f9286796d6053463a2d20130600000613202c3945515d677784919eaaafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c8073665b636d73808d929da5a19691847b6e695e564d443a322820160d040000000000000000000000000000000004111d2935414c555f6a6f7c8590959fa2aaa69f9c98989291919298979c9fa4aaa39f9590857c6f695f554b4035291f1509000000101d2a3743505d6a76838c86817c77716d67625f5853504a46423b37332d29241e1b15100c0701000000000000000000000000000000000000000000000000000c17232e3846535f6975828e99a3afab9f948b7f726a60574e463e36302a25201f1c181b1a1b181c1f20262b31363f474f59616c74808d96a1adada2978d8073675d5145392a1f14090000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d2020202020202020202020202020202020202020202020202020201514120e0902000000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100300000000000000000000000000000000000916222f3c4955626f7c88908f8e8d8c8b8a898887868584839099a49f9287838485868788898a8b8c8d8e8f90877a6e6154473b2e2114080005121f2b3744505b656c747676767676766f6a5f574d4b5153575e616467696a6c6c6c6c6b6a696764615e5754524c45403a312b231b130a010000000000000000000000000000000000000000000000000000000000020b16202b343f45515c676e7b859299a3a99f958d80746c61584e443a2f261b1106000000000000000000000000000000000000131f2c3946525f6c7985929facb6a99c8f82828282828282828282828282828282828282828282828282828282828282828f9ca9b5ac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2f303845515d67707d8a939eaaa49a9184796d60584e414956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6666666666666666666666666666666666666666666666666666666666666666605d554b4135291d110400000000000000000000000813202d3a4653606d7985929fa99d908376685d5245392c201307000000000000000000000916222f3c4955626f7c8895a2afa5988b7f7265584c3f3225190c000000010e1b2834414e5b6774818e9aa7b0a4978a7d7164574a3e3124170b0004101c2934404b55697683909ca9afa399887b6f6255483c2d22170b00010714202d3a4753606d7a86939facafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366595b636e74808d939da5a19691847b6e685e564c443a32281f160d040000000000000000000000000000030e18222c3945515d676e7c859297a0a7a8a09e94908b8886858586878a8f93999fa7a7a09792857b6e675d51453c31261a0e0000000f1b2835424e5b6875817f7a756f6b65605d55534e46443f3836302b27221b19130f0a040000000000000000000000000000000000000000000000000000000006111c2a36424d57626e7b87929fa8b0a69f92877c6f695f585046413b36312d2c282327272723282c2d31373b42465159606b717e8a929da8b1a79f92857a6d61554b4035291d10040000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d201413131313131313131313131313131313131313131313131313080705020000000000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c100704000000000000000000000000000000000916222f3c4955626f7c88959b9a9a99989796959a93929190959faba39992909192989495969798999a9b9c94877a6e6154473b2e211408000613202d394653606c79808283838383837c6f695e56555d6065696e717476777879797978777674716e6966605d56514b433d352d251c130a000000000000000000000000000000000000000000000000000000000000040e19222834404b555e69707d87929fa5a79d928a7e716a5f564c41382d22170f050000000000000000000000000000000000131f2c3946525f6c7985929facb8ab9f948f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f949fabb7ac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c2e38424e58606d7a84919ea6a99f93887d70675c51463c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada09386797272727272727272727272727272727272727272727272727272727272727272726d675d5145392c201306000000000000000000000006131f2c3845515c6775828f9ca89f92867a6d6054473a2d211409000000000000000000000916222f3c4955626f7c8895a2afa6998c7f7366594c4033261906000000020f1b2835424e5b6875818e9ba8b0a3968a7d7063574a3d3024170a00000c18232f414d5a6774808d9aa7b5ab978b7e716453493f33271b0f0b0e121c28333f4a5463707d899aa4afafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c80736659525c606c77818e939ea6a09691847a6e685e564c443a31281f160d04000000000000000000000000000a15202b37434e58606d7a849197a2a9a79f969189837e7b797878797b7e828790959ea5a9a1979184796d60574d42372b1d120700000e1b2734404d59656f75726d6863605953514b47433c38342e2a251f1b17110d0801000000000000000000000000000000000000000000000000000000000000000e1a26313b47535f6974808d96a0abaea39991857b6e6a615a524c46423c3a38342e3434342e34383a3c42474d535b626b707d86929fa4aeaaa0958b7f72685e5243392f24180d010000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0b0a0805000000000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336291c1614100b0500000000000000000000000000000916222f3c4955626f7c8895a2a7a6a5a4a3a2aca49f9f9e9d9fa7b1aba39f9d9e9fa2aaa2a3a3a4a5a6a7a194877a6e6154473b2e2114080005121f2b3744505b656e7b858f8f8f8f8f857b6e685d60676d72777b7e80828485868685858482807e7b77726d68605d554f473f372e251c1209000000000000000000000000000000000000000000000000000000000000071018232e39434d57606b727f8c939ea8a49f92867c6f685d53493f332721170c0300000000000000000000000000000000131f2c3946525f6c7985929facb8b0a69f9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9fa6b0bbac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c343f4a54606a74808d96a1ada1978e81746b60554b403c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb2a6998c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6054473a2d211407000000000000000000000004101c2834404b5565727f8b98a8a3998a7d7064574a3d31261a0e020000000000000000000916222f3c4955626f7c8895a2afa79a8d8074675a4d412e23170c000000030f1c2936424f5c6975828f9ca8afa296897c6f6356493c302316090000071824313e4b5764717e8a97a7b1a79a8e8174655b5044372b211b171a1d242b3844505b6673808d9aacb6afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d505b656c78818e949ea6a09691837a6d685e564c433a31281f160d030000000000000000000000020f1a26313b4754606a74818e96a0a9a89f9590847d76716e6c656b696e71757c838e939ea6a9a0968d8073695f5347392e23180c00000c1825313d48535d656866615e56544f4745403937312c28231c1a140f0b060000000000000000000000000000000000000000000000000000000000000000000009141f2b37424d57606d79849199a4afaba19791847c706c615e56534d494644404141414141404546494d53575f616d727d869298a2aeaca2989083786c60564c4131281d1207000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a171714110c0500000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f4336292423201c171008000000000000000000000000000916222f3c4955626f7c88959d9c9b9a98979695949992919095a0aca399929091929994969798999a9b9c9d94877a6e6154473b2e21140800030f1b27333f49535e696f7c8692999c9790837a6d666d72797f83878b8d8f919292939292918f8d8a87837f7a736d676059514940372e241b0f0600000000000000000000000000000000000000000000000000000000000007121d27303b454f59636d75818f95a0aaa29891847a6d655b50443d33291e150b00000000000000000000000000000000131f2c3946525f6c7985929facb8b8b0aba9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9abb0b8b9ac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c3844505c666f7c87939fa9a69e92857a6d60594f43393c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb9a89c918c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877b6e6154483b2e2115080000000000000000000000000c18232e3b4855626e7b8896a1ab9a8d817467574d42372b1e12050000000000000000000916222f3c4955626f7c8895a2afa89b8f827568544a3f34281c1003000004101d2935404b556a7683909da9b4aa95887b6e6255483b2f22150800000814212e3b4754616e7b8795a0acab9e9184786c6053463e332b2722252a2f35404a54606c7884919eabb8afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d49535b666d78828f949fa6a09590837a6d685d564c433a31281f150c030000000000000000000006121f2b37434e58626f7c89939da8aca09690837a706b6561605b575e61646a6f78818e949faaa89f92867b6e62554b4034281c1004000814202c37414b53595b5954524c48433d39352f2b261f1c17110e0903000000000000000000000000000000000000000000000000000000000000000000000000030e1a26313c45515d676f7d87939fa4aea9a19691867e756e68615e575653514a4e4e4d4e4e4b515356575f62696e767f879298a2aaafa49a92867c6f665b50443a301f160c01000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d27272727272727272727272727272727272727272727272727272727272423211c171008000000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f433633302f2c28211a11080000000000000000000000000916222f3c4955626f7c8891908f8e8d8c8b8a898887868583909daa9f92878385868788898a8b8c8d8e8f9091877a6e6154473b2e21140800000b17222d38414d57606a707e87939fa0958f82786e787f858b9095979a9c9d9f9f9f9f9e9d9c9a9795908c868079706b625b514940362c21180e030000000000000000000000000000000000000000000000000000000000000b151e29333d47515b606d79839198a2aaa0968f82776c60594f453b30271d1207000000000000000000000000000000131f2c3946525f6c7985929facb8b0a8a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa0a1a6aeb8ac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c424d57606d78839099a4aa9e948a7e71685d52473d303c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb9ada39c999999999999999999999999999999999999999999999999999999999999999994877b6e6154483b2e2115080000000000000000000000000714212e3a47535f6a7884919eaa9e918477695f53463a2d2114060000000000000000000916222f3c4955626f7c8895a2afaa9d908377665c5044382c1f1206000006131f2c3845515d677885919eabaea298877a6d6154473a2e21140700000714202d3a46525e697784909dabada197897d70635a50453d37332d3136394045515c66717d8a96a1adb9afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d414a545c666d79828f949fa7a09590837a6d685d554b433931271e150c030000000000000000000814212e3a47535f6a76828f9ca5afa49a91847a6d6860595553504d5254585f666d78828f98a3aea3998d8074675c5145382c1f130600040f1a252f3941484d4e4c4746413a38322c29241d1a15100c060000000000000000000000000000000000000000000000000000000000000000000000000000000009151f2935404b55606b727f8b929da4ada9a198928a817a746e696562605c545b5a5a5a5b545c606266696e747b828b9299a2aaaea39f93887e706a5f544a3f32291e0d0400000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343431302d28221a12080000000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f433e3f3d3c38332c231a110800000000000000000000000915222f3c4855626f7c8584838281807f7e7d7c7b7a79787a8794a19f92867978797a7b7c7d7e7f8081828384867a6e6154473b2e211408000006111b262f3b454e58616c727f8b929d9f948e817b838c92979d9fa7a8a09e9c9b9a9b9c9d9fa4a7a09d98928d847d726d635b51483e332a201509000000000000000000000000000000000000000000000000000000000000030c17212b353f45515d676e7c86929fa4a89e948c7f736b60574d43392e231810070000000000000000000000000000131f2c3946525f6c7985929facb8a89e969393939393939393939393939393939393939393939393939393939393939393959ca6b1ac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255483c46535f69727f8c95a0aba2988f82766c61564c41352f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb9b5ada8a6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a194877b6e6154483b2e21150800000000000000000000000006121f2b37434e586774818e9aaba096887b6e6155483b2e23170c0000000000000000000916222f3c4955626f7c8895a2afac9f9286796d6053463a2d20130900000714202d3a4753606d7a86939facab9f928578685e5246392d201307000005111e2a36424d5666737f8c99a3afa99c8f82766c61574f46443f414142464b515a606d7883919da8b0b8afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d40424a545c676d79829095a0a7a09590837a6d675d554b433930271e150c0300000000000000000815222f3b4855626e7b88949fabac9f93877d6f685d564f4846444246484e545c666e7b86929facab9f9285796d6053463a2d201307000009131d272f373d40423f3a3936302c27201d18120f0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d18242f3a434f59626d74808d929ca3adaaa29f938e86807b76726f6d6669686767676869666d6f72777b81868f949fa3ababa39f918c7f726c61584e42382d20170d0000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d605347404040404040404040404040404040404040404040404040404040404040403e3c39332c241a100500000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f464a4c4a48443e352c231a1108000000000000000000000815212e3b47535f6a6f7877767574737271706f6e6d676e7b8894a1a39886796c6c6d6e6f7071727374757677796e685e5246392d2014070000000a141d29333c464f59626d74808d939e9d938e8690959ea2a8a19e9896918f8e8d8e8f91939a9d9fa7a29f9691877f736d635a50453c31261a0e05000000000000000000000000000000000000000000000000000000000000050f19232935414b555f6a717e8a929da6a69f93877d70695e554b40342822190e0400000000000000000000000000131f2c3946525f6c7985929facb8a2968c87868686868686868686868686868686868686868686868686868686868686868a95a1adac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f62554844505a616e7b86929fa7a79f92867b6e615a50443a302f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f94877b6e6154483b2e211508000000000000000000000000020f1a26313e4a5764717d8a99a4a8988b7e7265544a3f34281c100300000000000000000916222f3c4955626f7c8895a2afaea398887c6f6255493c31251a0d06030615222f3c4855626f7c889aa4afaa9d9083776a564c4135291d11050000020e1925303b4854616e7b87929fabab9f948a7d706a60595350494e4e4d53555d606c73808c959c9ea6b0afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4038424b555d676d7a839095a0a79f959082796d675d554b433930271e150c0200000000000006121f2b37434e586774808d9aa6b0a89b8e82756b60564c443d3937363a3c424a545f6975818e9baba7a2978a7d7064574a3d3124170a0000020b151d252c313435332e2d2a251e1b16100d070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007131d28313d47515b606c77808c919ea1a9aea59e98928d87837f7c79777674747474747677797c7f83888e92999fa6aea8a199928b7f736d635a50463c2f261c0e050000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4a49453e362c22170c00000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c4f51575957554f473e352c231a110800000000000000000006121f2b37434e585f626c6b6a696867656463626160626f7b8895a2aa93867a6d606061636465666768696a6b6c615e564c41362a1e1105000000020b17212b343e47515b606c78818f959f9d999299a0a7a49f96918b8884828181818284878b90959ea2a8a199928c7f736c61574e42372b22170b00000000000000000000000000000000000000000000000000000000000000071118242f3a434e58616c73808d949fa8a49992857b6e675c51453f342b20160b02000000000000000000000000131f2c3946525f6c7985929facada093877a797979797979797979797979797979797979797979797979797979797979788693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6255484c56616c76828f98a2aba0958c7f72695e53483e32282f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb9a79d95939393939393939393939393939393939393939393939393939393939393939393877b6e6154483b2e211508000000000000000000000000000a14212e3a4754616d7a86939fa89b8f8275665c5044382c1f120600000000000000000916222f3c4955626f7c8895a2afb4aa988b7f7265574d42362a1f161210121c2834404a5465717e8b98acb6a79b8e8174685b4e413025190d010000000914202d3a46525e6975818e99a3afa69e92857c6f6b62605b535a5b575e61676d737e8893948f949eaaafa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d403039434b555d686d7a839096a0a79f959082796d675d554b423930261e140b0200000000000815212e3b47535f6a7884919eabaca096897c6f62594f443a322d2b2a2d3038424d5763707d89999b9a99988d8073665a4d4033271a0d000000030b131a202527282621201d19130f0a04010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c161f2b353f44505b656c747f8a92979ea6acaaa29f9a93908c898684828181808181828486898c90959a9fa3ababa49f9691877e736d635b51473e342a1d140a000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a575550483e33281c1105000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c515b63666361594f473e352c231a11080000000000000000030f1b26323c464e53555f5e5d5c5b5a595857565556626f7c8995a2a194877a6e615455565758595a5b5c5d5e5f54524c443b3025190d0100000000050f19222c353f44505b666d79839096a1a39fa3aba49a938c847f7b777675747475777a7e838a9297a1a8a39f918a7e716a5f53473e33281c10040000000000000000000000000000000000000000000000000000000000000007131d28313c46505a606d78828f96a1aba1979083796d605a50463c32281d140a000000000000000000000000131f2c3946525f6c7985929facada093877a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f625548525d68717e8a949faaa4999083786d60574d42362c232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb9a2958b868686868686868686868686868686868686868686868686868686868686868686867b6e6154483b2e211508000000000000000000000000000713202d3946525d687683909da99f9285796d6053463a2d20130800000000000000000916222f3c4955626f7c8895a2afb6a99c8f8376695e53463c3128201f1c1f232c3844515c6675818e9ba8b3a9988b7f7265584c3f322519080000000005121e2a36424d57626e7c87929fa7ada19791857d746f6c6568676869696e7279808893958f828f9ca8afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d40333039434c565e686e7a849196a1a79f948f82796d675c544b423830261d140a00000000000915222f3c4855626f7c8896a1adaa9e9184776a6054473d3228201f1e2026303c4753606d79868f8e8d8c8b8b8276695c504336291d100000000002090f14181b1b191413110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d192327333f49535b606d737d858f949da0a7acaca49f9c989892918f8e8d8d8d8e8f919298999d9fa7acaca69f99938d847d716c635b51493f352c22180b02000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6767676767676767676767676767676767676767676767676767676767676767676764615a5045392d211408000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695c5b636d72706b61594f473e352c231a110800000000000000000a15202a343c4347485251504f4e4d4c4b4a49495663707c8996a3a194887b6e615548494a4b4c4d4e4f5051524746413b32291e140800000000000007101a2328333f4a545d676e7a84919eabacafa49a93888079726e696968676869686d71767e859196a1aaa39f92867c6e625a5044392d20150a00000000000000000000000000000000000000000000000000000000000000010c161f2a333e44505c666d7a849199a3a99f958e81746c62584e443a2f261c11060000000000000000000000131f2c3946525f6c7985929facada093877a6d606060606060606060606060606060606060606060606060606060606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f62554f59606d7a85929ea6a89f93877c6f665c50453b3124232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867979797979797979797979797979797979797979797979797979797979797979797976695e52463a2d2014070000000000000000000000000005111d2935414c566673808c99aaa298897c6f6356493c2f24190d01000000000000000916222f3c4955626f7c8895a2afb9ac9f93877b6e61584e433a312d2c282b2e343f4953606d7985929eabada197887c6f6255493c2f22160900000000020e1a25303b47535f6a73808d95a0a8a9a1979188817c797674747476787b7f848d939890837e8a97a3afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d403328313a434c565e686e7b849197a1a69f948f82796d665c544a42382f261c1106000000000c1925323f4c5865727f8b98a8b2a79a8d807467584e43352b20161212151f2c3845515c677481828180807f7e7d7063564a3d3023170a00000000000004080c0e0f0c07070501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071017222d384149505b636b707b828990959c9fa4acaca9aaa39f9d9c9b9a9a9a9b9c9d9fa3aaaaababa39f9b948f878079706b625a514940372e231a100600000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada09386797373737373737373737373737373737373737373737373737373737373737373737373716c6155493c3023170a000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f82766958636d727f7d706b61594f473e352c231a110800000000000000040e18222a32373b3c4544434241403f3e3d3d4a5763707d8a96a3a295887b6f6255483c3d3e3f4041424344463b3936302920170d0200000000000000081117222d38424b555e6873808c99a6b3ac9f93887e736d67615f575b5a5b565e61656c717b849198a2aea2988f82766c6155493c32271b0f0300000000000000000000000000000000000000000000000000000000000000040d182128343f4a545e686f7c87929fa5a79d938b7e716a60564c42382d22170f0600000000000000000000131f2c3946525f6c7985929facada093877a6d605453535353535353535353535353535353535353535353535353606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f625554606b74818e97a1ada1968d80746a60544a3f33291f232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5e574d42362a1e120500000000000000000000000000010d1924303c4956636f7c8998a2aa998c807366564c4135291d1104000000000000000916222f3c4955626f7c8895a2afbbafa4998d80746a5f554c433d3a383438393f44505b65717d8a97a2adab9e9285786c605346392d201306000000000009141f2b37434e58606d79839096a0a8a9a19a938e8985828181818284878c91969992867c7d8a97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d40332628313a444c565e696e7b859197a1a69f948f82786d665c544a42382d22170b000000030f1b27333f49536875818e9ba8b4aa978a7d7064574a3d3224190d0505101c2934404b55646f74757474737271706b6054483c2f221609000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111b262f383f44515961696e757d83898f939a9c9fa2aaa7a8aaa9a7a7a7a7a7a9a9a8a6a9a29e9b99928e88827c746d676059504840372e251c11080000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb3a79a8d8080808080808080808080808080808080808080808080808080808080808080808080807e7164574a3e3124170b000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695f6a727f8c867d706b61594f473e352c231a11080000000000000006101820262b2e2f3938373635343231313e4a5764717d8a97a4a295897c6f6256493c3132333435363738392e2d2a251e170e0500000000000000000006111c28343f4a54606d7a85929eabb7aa9d91847a6d665d55534d4e4e4e4c52545a61696f7c86929fa8aa9f948a7d7064584e43372b1f13060000000000000000000000000000000000000000000000000000000000000000060f17232e38424c56606a727f8b939da7a59f92867c6f685e544a3f332821180d03000000000000000000131f2c3946525f6c7985929facada093877a6d605447464646464646464646464646464646464646464646464653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f62555c666f7d88939fa9a59e9184796d60584e42382e2117232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d60606060606060606060606060606060606060606060606060606060606060605f524d453b30251a0e0200000000000000000000000000000813202d3a4653606d7985929fa99d908376685d5245392c201307000000000000000916222f3c4955626f7c8895a2afb4aba39f92877c6e675d554f4846443f44464a5059606c7883909da9b1a79a8e8174655b5044372b1f12050000000000030f1a26313c45515c676e7b8491969fa4aca49f9b97928f8e8d8e8f9196999e9892877e717e8a97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261f28323b444d575f696f7c859298a2a69e948f81786d665c544a3f33281c0f03000005121f2b3744505b657784909daaaea298877b6e6154483b2e21150800000c18232f3943535d64686968676665646360594f44382c2014070000000000000000000000000000000000000000000406071013131313131310100d0a050000000003060809121313131313130d0c0a0702000000000000000000000000000000000a141d262d3340474f575e616b70777d82878b8f9298989a9b9d9e9e9f9f9f9e9d9d9b999797928e8a86817c766f6a605d554f473e362e251c130a000000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8174675b4e4134281b0e010000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f827669626e7b869292877d706b61594f473e352c231a110800000000000000060e151b1f21222c2b2a2928272625323e4b5865717e8b98a4a396897c706356493d3025262728292a2b2c21201e19140d050000000000000000000006121f2b3844505c66727f8c97a1adb8aca0968f81786c605b514842414141464750575f6a727f8c96a1ada69d9083766a6054473b2e22150900000000000000000000000000000000000000000101010101010101010101010006111c26303a444e58626d74818e95a0a9a39891847a6d665b50443e332a1f150b010000000000000000131f2c3946525f6c7985929facada093877a6d6054473a39393939393939393939393939393939393939393a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca295887b6f6257606d7984919aa4a99e938a7d70675d51463c30261c16232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d60535353535353535353535353535353535353535353535353535353535353534846423b33291f140900000000000000000000000000000006121f2c3844505c6675828f9ba89f92867a6d6054473a2d211409000000000000000916222f3c4955626f7c8895a2afaea39992999083796d6760595553504a5053545c606b727f8b959fabaca095897c6f6353493f33271b0f030000000000000a15202934404b555e696e7b848e939a9fa3aba9a19e9c9b9a9b9c9e9f9d9590867e70717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d403326162029323b454d575f6a6f7c869298939393938e81786d665b5044382b1f120600000613202d394653606c7985929facab9f928578695e52463a2d201407000007121d2731414b53595b5c5b5a59585856544f473d33271c100400000000000000000000000000000000000001070c1013141d2020202020201d1c1a16110a03040a0f1215151f2020202020201a1916130d07000000000000000000000000000000020b141b2227353e454d525960636b70757b7e8285888b8d8f9091929292929191908e8c8a8885817e7a746f6a626058514b433d352d241c130a01000000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000060606060e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675b4e4134281b0e010000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276695f6a707e869292877d706b61594f473e352c231a0e0400000000000000040a0f1215151f1e1d1c1b1a1925323f4c5865727f8b98a5a3968a7d7063574a3d3024191a1b1c1d1e1f1414110d080200000000000000000000000713202d3a4653606d7985919ea9b3b2aca89e938d80746d625a50463d3336393e454e58606d7984919eabab9f95887c6f6255493c31251a0e02000000000000000000000000000000010507070d0d0d0d0d0d0d0d0d0d0d0d0d0d0a141e29323d46515b606d79839097a1aaa1968f82786c60594f453c31271d12070000000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca195887b6e625f69737f8c95a0aca2978e81756b61554b40342b1e1516232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d60534746464646464646464646464646464646464646464646464646464646463b3a36302921170d0200000000000000000000000000000003101c28343f4a5465727e8b98a8a3998a7d7064574a3d31261a0e020000000000000916222f3c4955626f7c8895a2afac9f928692958f827a706b6562605c545b6062666d727d86929fa7b0a69d9083776b605441382d22170b00000000000000030c18232f39434d575e696e7981878f92999b9d9e9f9f9f9e9d9b9895908a837c706c717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a172029333c454e58606a6f7d868686868686868681796c605346392d20130600000714212e3a4754616d7a8798a2aeaa9d9084776a574d42362a1e12050000010b151f2f3941484c4e4f4e4d4d4c4b4a48443d352b21160b000000000000000000000000000000000000030b12181d1f202a2d2d2d2d2d2d2a2926221c150d0e151b1f21222c2d2d2d2d2d2d2625231e19120a010000000000000000000000000000020a1117232c333b42464f54596063696e7276797c7e808283848585868585848382807d7b7975716d68625f58544e45403a312b231b120a0100000000000000000000000b1825313e4b5864717e8b97a4aca89b8e8175685b4e4235281b0f0200000000000306060c13131313131b2734414e5a6774818d9aa7aca4978b7e7164584b3e3125180b0013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69a8e8174675b4e4134281b0e010000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f82766958616c707d869292877d706b61594f473e352c20160c020000000000000000030608091211100f0e0d1926333f4c5966727f8c99a5a4978a7d7164574a3e3124170d0e0f1011130807050100000000000000000000000000091623303c4956636f7c8997a1adb2a8a19ea19d928b7f726c61584e453c322d333c44515c66727f8c99a7b1a79a8d807367574d42362a1e12050000000000000000000000000002080d1113141a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a17202b343f45515c676e7b859299a4a89f948d80736c61574d43392f2418100700000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2120202020202020202020202020202020202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca194887b6e61626e7b86929fa8a69f92857b6e61594f433a2f22190c16232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a393939393939393939393939393939393939393939393939393939392e2d2a251f170f0500000000000000000000000000000000000c17232e3b4855616e7b8896a0ab9a8d817467574d42362a1e12050000000000000916222f3c4955626f7c8895a2afa6998c7f8c94948f847d76726f6d666b666c6e72787f879298a3aea99f948a7e7164594f442f261b1106000000000000000007121d27313b454d575e676d747c82868b8e909192929291908e8b88837e786f6a64717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0e17212a333c464e58606b6f7979797979797979756c665b5044382b1f120600000815222f3b4855626e7b8895aab4a99c8f8276695c4f4330251a0e02000000030d1d262f363c4041424141403f3e3d3c38332b231a0f050000000000000000000000000000000000030d151d24292c2d363939393939393736322d271f161820262b2e2f3939393939393933322f2a241c130a0000000000000000000000000000000006111a202930363d44484f54565e6165666d6f7174757778787979787877767573716f6d6664605d56534e47433d352f281f191109000000000000000000000000000b1825313e4b5864717e8b979f9f9f9b8e8175685b4e4235281b0f02000000060b0f12131920202020201b2734414e5a6774818d9a9f9f9f978b7e7164584b3e3125180b0013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675b4e4134281b0e010000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276696464646b707d859292867d706b61594f473d32281e130800000000000000000000000006050403020d1a2633404d596673808c99a6a4978b7e7164584b3e3125180b02030405060000000000000000000000000000000005111d2935414c566773808d9aa9b2a8a0969196a19f93877e706a60574d443a312834404a54616e7b8795a0acaa9e918477695e53463a2d211407000000000000000000000000050c13191d2021272727272727272727272727272727272727272934404b555e69707d87939fa6a69f93887d70695f554b40352922190e05000000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114131313131313131313131313131313202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca194877a6e616c76828f98a3ab9f948b7e72685e52473e31281d100916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d21201e1a140d050000000000000000000000000000000000000614212d3a46535f697784919eaa9e918477695f53463a2d2114060000000000000916222f3c4955626f7c8895a2afa396897d828f97969189837f7b79787778797b7f848b9299a3aaaaa2978f82766c6155473d321d140a000000000000000000010b151f29333b454d555d606a6f757a7e8183858586858583817f7b77716d665f64717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0f18212a343c464f5960636c6c6c6c6c6c6c6c68605b544a3f33281c0f030000091623303c4956636f7c8996a2afa89b8e8275685b4f4235281c0900000000000b141d252b303335363534333231302f2c27211a11080000000000000000000000000000000000020c151f272f35383a4346464646464643423e3831281f222a31373a3c45464646464646403f3b352e251c120700000000000000000000000000000000080e171f252a33383d44484d5254545c60626567686a6b6b6c6c6c6b6a6a68666462605c5454524c47433c383229241d160d0700000000000000000000000000000b1825313e4b5864717e8b93939393938e8175685b4e4235281b0f0200020a11171c1f20262c2d2d2d2c202734414e5a6774818d93939393938b7e7164584b3e3125180b0013202c3946535f6c79869293939393939393939393939393939393939393939393939393939393939393939393939393939393938e8174675b4e4134281b0e010000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f8f8276717171717171717c859292867d706b61594f443a3024190d01000000000000000000000000000000010d1a2734404d5a6773808d9aa6a5988b7e7265584b3f3225180c0000000000000000000000000000000000000000000713202d3946525d687784919daaaca09691849197a19992867c6f695f564c43392f2e3946535e697784919daaaca096877b6e6154483b2e2115080000000000000000000000050e171e252a2d2e34343434343434343434343434343434343434342f39434d57606b737f8c939ea8a49a92857b6e675d51453f342b20170c030000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070606060606060606060606060713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca094877a6d68717e8b949faaa3999083776c60564d41352c1f160c0916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d2020202020202020202020202020202020202020202020202020201514120e09020000000000000000000000000000000000000005121e2a36424d576774818d9aaba096887b6e6155483b2e23170b0000000000000916222f3c4955626f7c8895a2afa3968a7d7b8592999e95908b888685848486888c91959fa3abaaa29892857b6e615a5045352b210b0200000000000000000000030d172129333b434b51586062686e71747678797978787674726e6964605c5464717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d060f18222b343d474f54565f606060606060605b53504a42382d22170b0000000a1723303d4a5663707d8996a3b0a79a8e8174675b4e4134281b0e0100000000020b131a202427282928272625252322201c160f080000000000000000000000000000000000000a141e27313940454750535353535353504e4a433a31212a343c434748525353535353534d4b4740372e24190d0200000000000000000000000000000000050d141a21272c33383b4246474a505355585a5c5d5e5f5f5b60666c6c6c6c6c6a5c544a4745413a37312b272018130c040000000000000000000000000000000b1825313e4b5864717e868686868686868175685b4e4235281b0f00060b141c22282b2d333939393939382b34414e5a677480868686868686867e7164584b3e3125180b0013202c3946535f6c7987868686868686868686868686868686868686868686868686868686868686868686868686868686868686868174675b4e4134281b0e010000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f90837e7d7d7d7d7d7d7d7e7f869392867d706b61564c4135291d1105000000000000000000000000000000010e1b2734414e5a6774818d9aa7a5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000714212e3a4754616d7a8796a0acaa9e91847b859298a29892857b6e685e554b42382d36424d576774818d9aa7b2a8978a7e7164574b3e3124180b00000000000000000000020c1720293036393a4040404040404040404040404040404040404040404040454f59606c77828f96a0aaa2979083796d605b51463d32291e150a0000000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca093867a6d6d7a85929ea6a89f92867c6e655b50443b30231a0d040916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d20141313131313131313131313131313131313131313131313131308070502000000000000000000000000000000000000000000020e1a26313d4a5764707d8a99a3a8988b7e7265544a3f34281c100300000000000916222f3c4955626f7c8895a2afa4978a7d717d8792989f9d9899929191919298989da0a8aba79f9892867d70695f53483e3323190f000000000000000000000000050f172129313a40454e54565e6164686a6b6c6c6c6b6a6865615f5753505864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d00061019222b353d43484952535353535353534e46443f382f261c11060000000a1724303d4a5763707d8a96a3b0a79a8d8174675a4e4134271b0e01000000000001090f14181a1b1c1b1a1a1918171614100b0500000000000000000000000000000000000006111c263039434b51535d6060606060605d5b554d433829333c464e53555f6060606060605957524940352a1e1307000000000000000000000000000000000002090e161c21272c30363a3b3f4446494b4d4f5051575f666c72797979797975665c504439352f2b26201b160d0701000000000000000000000000000000000a1724303d4956626c7179797979797979756f65594d4034271b0e090f181d262d3338393f4646464646453834404c58646e7479797979797979716c6256493d3024170a00121f2c3845525e6a757979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746f64594c4033271a0d010000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f95908a8a8a8a8a8a8a8a8a8c93999892867d70685d5246392d201307000000000000000000000000000000020e1b2835414e5b6874818e9b9f9f998c807366594d4033261a0d000000000000000000000000000000000000000000091623303c4956636f7c8996a8b2a89b8e81757c869299a19791847a6d675c544a3f33313e4b5865717e8b98a4b1a6998d8073665a4d4033271a060000000000000000000008131e29323a4146474d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d505b656d7a849198a2a9a0958e81756d62594f443b30261c110600000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca39986796d75818e97a2aca0968c80736a5f53493f32291f1108000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0b0a080500000000000000000000000000000000000000000914212d3a4754606d7a86929fa89b8f8275665c5044382b1f120600000000000916222f3c4955626f7c8895a2afa4978a7e71707d8690959d9fa39f9e9e9e9fa3aaa9a8a79f9d9590867d706b60574d42362c22110700000000000000000000000000050f171f282f353d43474c5254585b5d5e5f5f5f5e5d5b5855534d464b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0000071019232b32383b3c4646464646464646423938332d261d140a000000000a1724303d4a5763707d8a96a3b0a79a8d8174675a4e4134271b0e010000000000000003070909131211100f0e0d0a09070400000000000000000000000000000000000000091317232e38424b555d60696c6c6c6c6c6c6a665f554a3e323b454e585f626c6c6c6c6c6c6c66635b52473b2f23160a00000000000000000000000000000000000000050b10161c1f252a2d2e34383a3c3e444d525b62696e787f8686868687796d6053463a2d241e1b150f0a040000000000000000000000000000000000000815212d3945505a62646c6c6c6c6c6c6c68655d53483d3124180d1419212a2f383f44464c535353535352443f3848535c64676c6c6c6c6c6c6c64625a5045392d21150800111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c67645d53483c3024180b000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828f9393939393939393939393979fa4a39892857a6d6154473a2e211407000000000000000000000000000000020f1c2835424f5b6875828e939393938d8073675a4d4034271a0d0100000000000000000000000000000000000000000b1825323e4b5865717e8b98a4b1a6998c7f73707e87939fa0969083796d665b50443f363c4956636f7c8996abb5a89c8f8275695c4f422e23170b000000000000000000010d1925303a444c52545a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a535d686f7c86929fa4a79e938b7f726b60564c42382e23170c00000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929fac9f928679707d89939ea9a59d9184796d60584e41382d20170d00000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a171714110c050000000000000000000000000000000000000613202c3945515d677683909ca99f9285796d6053463a2d20130800000000000916222f3c4955626f7c8895a2afa4978a7e716b707c838a9095989b9d9e9f9f9f9e9d9b9895908a837b706b60594f453b31241a10000000000000000000000000000000050d161d242932373b4146474b4e505252535252504e4c4846423e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d00000007101921272c2f303939393939393939352d2b28221c140b02000000000a1723303d4a5663707d8996a3b0a79a8e8174675b4e4134281b0e010000000000040a0f131516201f1e1d1c1b1a171614100b050000000000000000000000000000000009121b2528343f4a545d676d767979797979797671665b4e423b444d575f6a6f78797979797979736d63574b3f3225190c000000000000000000000000000000000000000000050b1014191e202429323a414650565e616d727b828c929992877e71665c5044382b1f130f0a04000000000000000000000000000000000000000005111d29343e48505658606060606060605b59534b41372c200e171f252a333b424a5053595f6060605f5e504a42414a53585a60606060606060585650483e34291d1105000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060605b59534a41362b201408000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100101c2936434f5c6976828686868686868686868686868b93999992877e70685d5246392d20130700000000000000000000000000000003101c2936434f5c6976828686868686868074675a4e4134271b0e0100000000000000000000000000000000000000010e1a2734414d5a6774808d9aa7b1a4978a7e716c727f8b929d9f958f81786c605b51483e3b4754616e7a8799a4afaa9d9084776a544a3f34281c1003000000000000000005111d2a36414c565e6167676767676767676767676767676767676767676767676767676767676a717e8a929daba59f92877d6f685e544a3f34281c1003000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929fac9f9285797984919ea5a99d93897d70675c51463c2f261b0e0500000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a2d27272727272727272727272727272727272727272727272727272727272423211c171008000000000000000000000000000000000004111d2935414c5566737f8c99a9a297897c6f6356493c2f24190d01000000000916222f3c4955626f7c8895a2afa4978b7e71646a6f787e83888b8e909192929291908e8b88837e766e6960594f473d33291f120800000000000000000000000000000000040c131820272b3036393b3e4143454646454543413f3b3a363e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d00000000070f161b1f22232c2d2d2d2d2d2d2d28201f1c17110a020000000000091623303c4956636f7c8996a2afa79b8e8174685b4e4135281b060000000000070f161b1f22232c2b2a292827262322201c160f08000000000000000000000000000008111b242d373f44505c666d798286868686868683766a5d5043434c565f696f7c85868686868686807366594d4033261a0d00000000000000000000000000000000000000000000000710191f282f353e444c525a61696e767f8690949a93877e716c61544a3f34281c100100000000000000000000000000000000000000000000000c17222d363e45494b535353535353534e4d4841392f251a19202930363f454d545b60666c6c6c6c6c6a5c544a3f41484c4e535353535353534b49453e362d22170c00000915202b353f474e5253535353535359636b6c6c6c6c6b64615a534d53535353535353534d535b60656c6c6c6c6b686157535353534e4c4841382f251a0f03000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e11000f1c2835414e5a6670767979797979797979797979797e869392877e706c61564c4135291d1105000000000000000000000000000000020f1b2835414e5a657076797979797979746e64584c4033261a0d0000000000000000000000000000000000000000020f1c2835424f5b6875828e9ba8afa396897c70636d74808d939e9e938d80746d625a50463d4653606c7986939facab9e928578665c5044382b1f120600000000000000000713202d3946525e686d7373737373737373737373737373737373737373737373737373737373737374808d99a3aea39991847a6e665c5044382c1f1206000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929fab9e918578808d96a0aca1978e81746b60554b40342a1d140a0000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343431302d28221a120800000000000000000000000000000000010d19242f3c4956626f7c8997a2a9998c807366564c4135291d1104000000000916222f3c4955626f7c8895a2afa4978b7e71645f666d71777b7e8183858586858583817e7b76716c615f574f473d352b21180d00000000000000000000000000000000000001070d151b1e252a2d2e31353738393939383735322e2d313e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0000000000040a0f1315161f202020202020201b13120f0b06000000000000000915222f3c4855626f7b8895aab4a89b8f8275685c4f422d22170b0000000007101921272c2f3039383736353433302f2c27211a110800000000000000000000000007101a232d363f49525c606d78828f94939393938c807366594d434c565e686e7b85919793939992877d706356493d3023160a00000000000000000000000000000000000000000000040f19222b313a41454f565e616c717b828b92989a93887e716c615a5042382e23170b00000000000000000000000000000000000000000000000006111b242d34393d3e4646464646464642403d372f271d1e2529323b424651575f666c72797979797975665c5044383c4041464646464646463e3d39342d241b11060000040f19242d353d42454646464646525e6b757979797978706c615f57514b434646424b51575f656c71787979797873685c5046464641403c362f261d130800000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e11000d1925323d49545e66696c6c6c6c6c6c6c6c6c6c717e879392877e716c615a50443a3024190d01000000000000000000000000000000000d1925313d49545e65696c6c6c6c6c6c67645c52473c3024170b000000000000000000000000000000000000000003101c2936434f5c6976828f9ca9aea295887b6f62606c78818f959f9d928b7f726c61584e4544505b667885929fabac9f9386796d6053463a2d20130700000000000000000714212e3a4754616d7a80808080808080808080808080808080808080808080808080808080808080808086929facaba1969082786d6053463a2d201307000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faa9d91847b87929fa8a69e92857a6d61594f43392e22180b020000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d605347404040404040404040404040404040404040404040404040404040404040403e3c39332c241a1005000000000000000000000000000000000813202d394653606c7985929ea99d908376685d5245392c201306000000000916222f3c4955626f7c8895a2afa4978b7e7164545c6064696e72747678787979787675726e6964615a534d453d352b23190f060000000000000000000000000000000000000000040a0f14191e202125282a2b2c2c2c2b2a28252225313e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d000000000000000307090913131313131313130f0606030000000000000000000714212e3a4754616d7a8798a2aea99c8f837669544a3f33281c0f030000040f19222b32383b3c464544434241403d3c38332b231a0f0500000000000000000000060f19222c353e48515b636e74818e949ea69e948e81746e63574b4b555d686e7a849197a1a49f93877e716b6054483b2f221609000000000000000000000000000000000000000000000a16212b343d434b515961686d757e858f949f9f93887f716c625a50483e30261c11060000000000000000000000000000000000000000000000000009121b22292d3031393939393939393534312c2518202830353e444d525b62696e787f8686868687796d6053463a2d33343939393939393931302d29221b12090000000008121b242b313638393939394653606c7987868686847d756e69605c554f46454f545c60696e777e8586868685786b5f524539393433302b251d140b0100000000000000000000000000000c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e11000915212c38424c545a5c6060606060605a626c717e879392877e716c615a50483e32281e130800000000000000000000000000000000000915212c38424c545a5c6060606060605a58524a41362b1f1408000000000000000000000000000000000000000003101d2a3643505d697683909ca9aea194877b6e615b666d79839096a09f93877e706a60574d444a546b7884919eabafa49a867a6d6053473a2d20140700000000000000000815222f3b4855626e7b888d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d9299a3aeb2a99f94897d7063564a3d3023170a000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faa9d9083839099a3aa9f948a7e71685d52473d30271d0f06000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4a49453e362c22170c0000000000000000000000000000000006121f2b3844505b6675828e9ba89f92867a6d6054473a2d211409000000000916222f3c4955626f7c8895a2afa4978b7e7164585053575f6165686a6b6c6c6c6b6a6865615f57555046423b332b231a1108000000000000000000000000000000000000000000000002080e111414181b1d1f1f201f1f1d1b191825313e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d00000000000000000000000606060606060606020000000000000000000000000613202d394653606c7985929facaa9e918477665b5044382b1f120600000a16212b343d434849535251504f4e4d4a48443d352b21160b000000000000000000050f18222b343e47505a626d73808d939da69f948f82786d605c524a545c676d7a839096a0a49c918b7f726c61594f44382c201307000000000000000000000000000000000000000000030f1b27323d464e555d606b707a818a92979f9b918b7f726d625a50483e362c1e140a0000000000000000000000000000000000000000000000000000000911171d2124252d2d2d2d2d2d2d282724201d2429323a414650565e616d727b828c929992877e71665c5044382b27272d2d2d2d2d2d2d2524211d17110900000000000009121920262a2c2c2d2d313e4b5864717e889396918a827b736d67615953525960666d737b828b929792877e7064574a3d312d282724201a130b020000000000000000000000020507080c1926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e110005101b26303a42494e4f535353534e58626c717e879393877e716c615a50483e362c20160c02000000000000000000000000000000000004101b26303a42494e4f5353535353534e4c4741382f241a0e03000000000000000000000000000000000000000004111d2a3744505d6a7783909daaada194877a6e61545d676d7a849197a19992867c6f695f564c515e6b7784919eaab6a094877a6d6154473a2e21140700000000000000000815222f3b4855626e7b88959a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9fa3abb5bbb0a6968a7d7063574a3d3024170a000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929fac9f928790959faba2988f82766c61564c41352b1e150b00000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a575550483e33281c1105000000000000000000000000000000030f1c28333f4a5465717e8b98a7a3998a7d7064574a3d31261a0e020000000916222f3c4955626f7c8895a2afa4978b7e7164584b464d5355585b5d5e5f5f5f5e5d5b5855534d49453e36312a211a11080000000000000000000000000000000000000000000000000000020507080b0e101213131212100e0c1825313e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d000000000000000000000000000000000000000000000000000000000000000005121f2b3744505b657784909daaac9f9285796c605346392d20130600030f1b27323d464f54565f5e5d5c5b5a5956544f473d33271c100400000000000000040e17212a343d464f59616c727f8c929ca5a0959082796d665c5044505c666d79829095a0a59d928c7f736d625a50473d32271b100400000000000000000000000000000000000000000007131f2c38434e5860676d747d858e939fa29b918b7f726d625a50483f362d241a0c0200000000000000000000000000000000000000000000000000000000060c11151718202020202020201b1b191f282f353e444c525a61696e767f8690949a93877e716c61544a3f34281c1b20202020202020181715110c060000000000000000080f151a1d1f202024303d4956626c717f8b919e948f868079706b615f5d606b6f797f868f949f93887e716c6155493c30231b1a18140f08010000000000000000000003090e121415191926333f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100000a141e2830383d414346464647535f6a717e879393877e716c615a50483e362c231a0e04000000000000000000000000000000000000000a141e2830383d414346464646464641403c362f261d130800000000000000000000000000000000000000000004111e2b3744515e6a7784919daaada094877a6d6154555e686e7b859298a29892857b6e685e554b5e6a7784919daaada194877a6e6154473b2e21140800000000000000000815222f3b4855626e7b8895a1a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a7acaeb5acacaca3968a7d7063574a3d3024170a000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929faca39992999fa7a79f92867b6e615a50443a3023190c0300000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada093867a6d6767676767676767676767676767676767676767676767676767676767676767676764615a5045392d211408000000000000000000000000000000000b17222d3b4854616e7b8795a0ab9a8d817467574d42362a1e12050000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e4246484b4e505252535252504e4b4847423c39332a261f180f0800000000000000000000000000000000000000000000000000000000000000000204050606060504020b1825313e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000030f1b27333f49536875818e9ba8aea398887b6e6255483b2d22170b0407131f2c38434f5960636c6b6a696867666360594f44382c201407000000000000040d162029333c464e58616b717e88939fa4a19690837a6d675d544a525c606d78818f949fa69e938d80746d635b51483e352b21160b000000000000000000000000000000000000000000000915222e3b4854606a6f79818a91979ea39c918c7f726d625b51483f362d241b12080000000000000000000000000000000000000000000000000000000000000005080a0b131313131313130f19222b313a41454f565e616c717b828b92989a93887e716c615a5042382e23170b131313131313130b0a0805000000000000000000000004090e11121315212d3945505a626d727f8b919c98928c847d756e69686d747c838c92989c918b7f726c625a5044392d20140d0b08030000000000000000000000060e141a1e2122252526333f4c5966727f8c99a5aa9d9184776a5e5144372b1e110000020c161e262c32353639393c4855626f7b869393887e716c615a50483e362c241a11080000000000000000000000000000000000000000020c161e262c3135363939393939393433302b241d140b0100000000000000000000000000000000000000000004111e2b3744515e6a7784919daaada194877a6e61544c565f696f7c869299a19791847a6d675c545e6b7784919eaaada094877a6d6154473a2e21140700000000000000000815222f3b4855626e7b88959f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f968a7d7063574a3d3024170a000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929facaba39fa3ababa0958c7f72695f53483e32281e11070000000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facada09386797373737373737373737373737373737373737373737373737373737373737373737373716c6155493c3023170a000000000000000000000000000000000614202d3a46525e697784919daa9e918477695f53463a2d2114060000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e363a3b3f4143454546464543423f3b3a37312d28221a140e060000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0ada6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000b17222d3f4c5865727f8b98a8b2aa978a7e7164544a3f33281b13101014222f3b4854606b6f79787776757473706b6054483c2f2216090000000000030c161f28323b454e58606a707d87929aa4a19791847b6e685d554b515b636e74818e939ea69e948e81776c605b51493f362c23190f04000000000000000000000000000000000000000000000916232f3c4956626f7c848e9393939393918c7f726d625b51493f362d241b12090000000000000000000000000000000000000000000000000000000000000000000000000606060606000a16212b343d434b515961686d757e858f949f9f93887f716c625a50483e30261c110600060606060606000000000000000000000000000000000001040605111d29343e48505a626d727f8c929c9f96918a827b73717a818891959f9d928c7f736d625a50483e33281c100400000000000000000000000000060f181f262a2d2e323232333f4c5966727f8c99a5aa9d9184776a5e5144372b1e11000000040c141b212528292d2e3a47535f6a73808c887e716c625a50483e362c241a120800000000000000000000000000000000000000000000040c141b212528292d2d2d2d2d2d2726241f1a130b020000000000000000000000000000000000000000000004111d2a3744505d6a7783909daaaea194877b6e6154484d57606a707e87939fa0969082796d665b5e6b7884919eabb4aa93877a6d6054473a2d21140700000000000000000815222f3b4855626e7b88939393939393939393939393939393939393939393939393939393939393939393939393939393938a7d7063574a3d3024170a000000131f2c3946525f6c7985929facada093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929facb5afacafafa4999083786d60574d42362c20160c000000000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb3a79a8d8080808080808080808080808080808080808080808080808080808080808080808080807e7164574a3e3124170b0000000000000000000000000000000005121e2a36424d576774808d9aaaa096887b6e6155483b2e23170b0000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e312d2e32353738393939383735322e2d2b261f1c170e0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4afa295887c6f6255493c2f221609000714212d3a4754606d7a8793a0aca6998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000616222f3c4955626f7c8896a1ada79a8e8174665b5044382d241f1c1d1f27303c4956636f7d868584838281807d7063564a3d3023170a00000000020b151e28313a444d575f6a6f7c869299a3a29892857b6e695e564c505a626d73808d939da59f948f82786d655b504940372d241a110700000000000000000000000000000000000000000000010e1b2734414e5a67748186868686868686867f736d635b51493f372d241b1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b27323d464e555d606b707a818a92979f9b918b7f726d625a50483e362c1e140a00000000000000000000000000000000000000000000000000000000000c17222d363f48515b636d737f8c929ca09e948f867f7d848d939aa09d938d80736d635b51483e362c22170b00000000000000000000000000030e18212a31363a3b3f3f3f3f3f4c5966727f8c99a5aa9d9184776a5e5144372b1e1100000000020a1015191c1c1f2b37434e58636d73807e716c625a50483e362c241a1208000000000000000000000000000000000000000000000000020a1015191b1c2020202020201b1a17140e0801000000000000000000000000000000000000000000000003101d2a3643505d697683909ca9aea295887b6f625548454e58616c727f8c929d9f948e81786c605b657885929eabaea29886796d6053463a2d20130700000000000000000815222f3b4855626e7b8686868686868686868686868686868686868686868686868686868686868686868686868686868686867d7063574a3d3024170a000000131f2c3946525f6c7985929facaca093877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693a0acac9f9386796c605346392d201300131f2c3946525f6c7985929facb8bbb9b2a89f93877c6f665c50453b31241a0e04000000000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8174675b4e4134281b0e01000000000000000000000000000000020e1a25303d4a5763707d8a98a3a8988b7e7265544a3f34281c100300000916222f3c4955626f7c8895a2afa4978b7e7164584b3e31252225282a2b2c2c2c2b2a282522211e1a15110c050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4aca295887c6f6255493c2f221609000714212d3a4754606d7a87939f9f9f998c807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000815212e3b47535f6a7884919eabab9e9185786c6053493f352f2c28292c2f39424f5966727f8c91908f8e8d8b7e7265584b3f3225180c000000000a141d273039434c565e696e7c859298a2a39992867c6f695f564d4f59626c727f8c929ca5a0959082796d665c53493f372e251b12080000000000000000000000000000000000000000000000010d1a2733404c58646e747979797979797979736d635b51493f372d251b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000007131f2c38434e5860676d747d858e939fa29b918b7f726d625a50483f362d241a0c02000000000000000000000000000000000000000000000000000000000006101b242d363f49515b636d73808d929da49e98928c8a91969fa49e938e81746e645b51493f362d241a10050000000000000000000000000009141f2a333b4246484c4c4c4c4c4c5966727f8c99a5aa9d9184776a5e5144372b1e1100000000000005090d0f0f1a26313c46525b646e73716d625a50483e362d241a120800000000000000000000000000000000000000000000000000000004090d0f101313131313130e0d0b080300000000000000000000000000000000000000000000000000020f1c2935424f5c6875828f9ba8afa296897c6f6356493d46505a626d74808d939e9e938d80736d606c7986929facab9f928578665c5044382c1f120600000000000000000814212e3a47535f6a76797979797979797979797979797979797979797979797979797979797979797979797979797979797979706b6155483c2f231609000000131f2c3946525f6c7985929f9f9f9f93877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d7986939f9f9f9f9386796c605346392d201300131f2c3946525f6c7985929facacacacada1968d80746a60544a3f33291f120900000000000000000916232f3c4956626f7c8995a2ac9f9386796c605346392d20130013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675b4e4134281b0e01000000000000000000000000000000000914202d3a4753606d7a86929fa89b8f8275665c5044382b1f120600000916222f3c4955626f7c8895a2afa4978b7e7164584b3e312518181b1d1f1f201f1f1d1b181514120e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b979f9f9f95887c6f6255493c2f221609000714212d3a4754606d7a8793939393938c807366594d4033261a0d00000000000000000000000000000000000000000000000000000000000000000006131f2b37434e586774808d9aa6ada1978a7d70655b5045413a383435393b424b54606b7783909d9d9c9b95887b6e6155483b2e22150800000006111b262f39424b555e686e7b849197a2a49a92877d706a60574d4f59616c717e88939fa4a19690837a6d675d544a41382d251c1309000000000000000000000000000000000000000000000000000b1824303c48535c64676c6c6c6c6c6c6c6c66635b51493f372d251b130900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915222e3b4854606a6f79818a91979ea39c918c7f726d625b51483f362d241b12080000000000000000000000000000000000000000000000000000000000000009121b242d373f49525b636e74808d929da5a39f99979ea1a69e948e81786c605c524940372d241b110800000000000000000000000000020e1a26313b454d53555858585858585966727f8c99a5aa9d9184776a5e5144372b1e11000000000000000000000a15202a344049525c646765625a50483f362d241b1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3e48515b606c78818f959f9d928b7f726c6d7a8799a3afaa9e9184776b544a3f34281c1003000000000000000006121e2b37424e575f6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6361594f44382c201407000000131f2c3946525f6c7986929393939393877a6d6054473a2d2114070000000000000000000000000713202d3a4653606d798693939393939386796c605346392d201300131f2c3946525f6c7985929f9f9f9f9fa59e9184796d60584e42382e21170d0000000000000000000916232f3c4956626f7c89959f9f9f9386796c605346392d20130013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69a8e8174675b4e4134281b0e010000000000000000000000000000000006131f2c3945515d6776828f9ca99f9285796d6053463a2d20130800000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180c0e101212131312100f0c08080602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b9393939393887c6f6255493c2f221609000714212d3a4754606d7a86868686868686807366594d4033261a0d000000000000000000000000000000000000000000000000000000000000000000030f1b26323c4855626e7b88949eaca99d9083786c605a524c4645404045474c545c66707d8995a0aaa99d918477695f53463a2d2114070000000b17222d38414a545d676d7a839196a1a49f93887e716b60584e4e58606b707e87929aa4a19791847b6e685d554b42392f261b130a00000000000000000000000000000000000000000000000000000814202b36414a53585a60606060606060605957514940372e251b13090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000916232f3c4956626f7c848e9393939393918c7f726d625b51493f362d241b120900000000000000000000000000000000000000000000000000000000000000000009121b252d374049525c646e74808d939da59f9f9f9fa79f948f82786d665b504a40372e251b1209000000000000000000000000000005121e2a36424d575f616565656565656566727f8c99a5aa9d9184776a5e5144372b1e1100000000000000000000030e18222e37404a52585a585650483f362d241b120900000000000000000000000000000000000000000000000000000000000000000000000000010507071313131313131313080705020000000000000000000000000000000000000c1926333f4c5966727f8c99a5b2a5998c7f7266594c3f363f44505b666d79839096a09f93877e706f7c8995abb5a99c8f8376695c50432e23170c000000000000000000020e1a26313c454e535560606060606060606060606060606060606060606060606060606060606060606060606060606060606057554f473e33281c1004000000131f2c3946525f6c7986868686868686867a6d6054473a2d2114070000000000000000000000000713202d3a4653606d788686868686868686796c605346392d201300131f2c3946525f6c798692939393939393938a7d70675d51463d30261c0f060000000000000000000916232f3c4956626f7c89939393939386796c605346392d20130013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675b4e4134281b0e010000000000000000000000000000000004101d2935404b5566727f8c99a9a297897c6f6356493c2f24190d01000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b0204050606060504020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e868686868686867c6f6255493c2f221609000713202c3945525d687679797979797979736d63574b3f3225190c000000000000000000000000000000000000000000000000000000000000000000000a15212e3a47535f6a76828f9aa4ab9f958c7f726c605d5653514b4b5153565e666d7983909da7ada2978b7f7265574d42372b1e12050000030f1b27333f49535c666d79839095a0a59c928b7f726c61594f4d575f6a6f7d869299a3a29892857b6e695e564c433930271d140a010000000000000000000000000000000000000000000000000000030f1a252f3841484c4e53535353535353534c4b4640372e251c1309010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e1b2734414e5a67748186868686868686867f736d635b51493f372d241b1209000000000000000000000000000000000000000000000000000000000000000000000009131c252e37404a525c606c77818e93939393939393959082796d665c544a3f382e251c13090000000000000000000000000000000714212d3a46535f696e7272727272727272727f8c99a5aa9d9184776a5e5144372b1e11000000000000000000000006101c252e3840474c4d4b4a453f362d241b120900000000000000000000000000000000000000000000000000000000000000000000000002080d11131420202020202020201514120e0902000000000000000000000000000000000a1724313d4a5764707d8a97a9b2a89b8e817568564c4136333f4a545d676d7a849197a19992867c717e8a97a4b1a79a8e8174675b4e4134281b06000000000000000000000915202a333c4247485353535353535353535353535353535353535353535353535353535353535353535353535353535353534a48443e352c21160b00000000121f2b3844515d6974797979797979797976685d5245392c20130700000000000000000000000006121f2c3844505c66767979797979797979766c5f5346392d201300131f2c3946525f6c7986868686868686868681756c61554b40342b1e150a000000000000000000000916232f3c4956626f7c86868686868686796c605346392d20130013202c3946535f6c79869293939393939393939393939393939393939393939393939393939393939393939393939393939393938e8174675b4e4134281b0e0100000000000000000000000000000000000c18242f3c4955626f7c8897a1a9998c807366564c4135291d1104000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724303d4956626c7179797979797979766a5f53473b2e2115080004111d2935414c565d6c6c6c6c6c6c6c6c66635b52473b2f23160a0000000000000000000000000000000000000000000000000000000000000000000006121f2b37434e58626f7c87939fa8a79f93887e746d6863605c54555d6063686e78818e95a0aca69f9285796d6053473c31261a0e02000005121f2b3744505b656d78828f959fa59d938c80736d625a504c565f696f7c859298a3a39892867c6f695f564d443a31271e150b020000000000000000000000000000000000000000000000000000000008131d262f363c40414646464646464646403e3b352e251c130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1a2733404c58646e747979797979797979736d635b51493f372d251b1209000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e384044505b656c7881868686868686868683796d675d544a42382d261c130a010000000000000000000000000000000815222e3b4855616e7b7f7f7f7f7f7f7f7f7f818f9ba8aa9d9184776a5e5144372b1e110000000000000000000000000a131c262e363c3f403e3d3a342d241b1209000000000000000000000000000000000000000000000000000000000000000000000000050c13191d20212d2d2d2d2d2d2d2d21201e1a140d050000000000000000000000000000000815222e3b4855616e7b8896a1adaa9d908477685e5246392d38424b555e686e7b859298a29892857b808d9aa6b4aa988b7f7265584c3f3225190c00000000000000000000030e18212a31373a3b4646464646464646464646464646464646464646464646464646464646464646464646464646464646463d3c38332c231a100500000000101c2935414d5862696c6c6c6c6c6c6c6c6c5d564c4135291d110400000000000000000000000003101c28343f4a545c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e1200121f2b3844515d6974797979797979797979756f65594f433a2f22190c03000000000000000000000815222e3b4754606a6f79797979797979766c5f5346392d20130013202c3946535f6c7987868686868686868686868686868686868686868686868686868686868686868686868686868686868686868174675b4e4134281b0e0100000000000000000000000000000000000713202d394653606c7885919ea99c908376685d5245392c201306000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212d3945505a62646c6c6c6c6c6c6c625f584e43372b1f130600010d19242f3a444c525f606060606060605957524940352a1e130700000000000000000000000000000000000000000000000000000000000000000000020f1a26313c4754606a74818e96a0a9a49a9387807a74706d666a6a676d70747a828e939ea7a89f948b7e72675d5145392a1f140900000815212d3945505a606c77818e949fa69e938e81746e635b5146525e686e7b859197a2a39992867d706a5f574d443b32281f150c030000000000000000000000000000000000000000000000000000000000010b141d252b303334393939393939393933322f2a231c130a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1824303c48535c64676c6c6c6c6c6c6c6c66635b51493f372d251b13090000000000000000000000000000000000000000000000000000000000000000000000000000010a131c2627333f49535b666c757979797979797979776d675d554b42392f261c140a01000000000000000000000000000000000b1724313e4a5764717d8a8b8b8b8b8b8b8b8b8f939eaaaa9d9184776a5e5144372b1e11000000000000000000000000010b141c242b30333432312e29221b1209000000000000000000000000000000000000000000000000000000000000000000000000050e161e252a2d2e39393939393939392e2d2a251f170f0500000000000000000000000000000714212d3a46535f697884919eabac9f93877a6d6154473c322f39434c565f696f7d86929aa197918483909daaaea298897c6f6356493c302316090000000000000000000000060f1820262b2e2f393939393939393939393939393939393939393939393939393939393939393939393939393939393939302f2c28211a110800000000000d1925303b4650585d5f606060606060605f524c443a2f24190d01000000000000000000000000000c17232e38424a505f60606060606060605f5a52493e33271b0f00101c2935414d5862696c6c6c6c6c6c6c6c6c68655d53473e31281d1007000000000000000000000006131f2b38434e5860626c6c6c6c6c6c6c6c645a4f43372b1e1200121f2c3845525e6a757979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746f64594c4033271a0d01000000000000000000000000000000000005121f2b3744505b6575818e9bac9f92867a6d6054473a2d211407000916222f3c4955626f7c8895a2aca4978b7e7164584b3e3125180b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111d29343e485056586060606060606055534e463c32261b0f03000008131e28323a414553535353535353534d4b4740372e24190d0200000000000000000000000000000000000000000000000000000000000000000000000a15202b37434e58606d7a849197a2a9a499938d85807d79787777787a7c81868f949ea5a9a1969082776c60554b403529180e0300000a1724303d4956626c74808d939ea69f948f81786d605c52494754616e7a849197a1a49a92877e706b60584e453c322920160d0300000000000000000000000000000000000000000000000000000000000000020b131a202427272d2d2d2d2d2d2d2d2625231e19120a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000814202b36414a53585a60606060606060605957514940372e251b130900000000000000000000000000000000000000000000000000000000000000000000000000000000010a1417222d38414a545b60686c6c6c6c6c6c6c6c6a605d554c433930271d140a0200000000000000000000000000000000000b1724313e4a5764717d8a97989898989898989b9ea6b0aa9d9184776a5e5144372b1e1100000000000000000000000000020b12191f2326272524211d181109000000000000000000000000000000000000000000000000000000000000000000000000020c1620283036394646464646464646463b3a36302921170d020000000000000000000000000005121e2a36424d576875818e9baaafa49a8b7e7164584e43372b313a444d57606b717e88939fa096919095a0abac9f9285796d6053463a2d201307000000000000000000000000060e151a1e21222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423201c16100800000000000008141f2a343e464d5152535353535353535345413a32281e1308000000000000000000000000000006111c2630383f44535353535353535353534f4940372c21160a000d1925303b4650585d5f60606060606060605b59534b42352c1f160c000000000000000000000000030f1b27323d464e5456606060606060605f5a52493e33271b0f00111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c67645d53483c3024180b000000000000000000000000000000000000030f1b27333f495364717e8a9aa4a3998a7d7064574a3d3124170a000916222f3c4955626f7c88959f9f9f978b7e7164584b3e3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17222d363e45494b535353535353534947433c342a20150a000000010c1620282f35394646464646464646403f3b352e251c1207000000000000000000000000000000000000000000000000000000000000000000000000030f1b27323c45515d676e7c859297a0a7a49f97928d89868584848586898d92989fa6a79f9791847b6e655b50433a2f2418060000000b1825313e4b5864717e8b929da5a0958f82796d665c504a43505d6a76839096a0a99f93887e716c61594f463c332a20170e0400000000000000000000000000000000000000000000000000000000000000000001080f14181a1b2020202020202020191916120d070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1a252f3841484c4e53535353535353534c4b4640372e251c13090100000000000000000000000000000000000000000000000000000000000000000000000000000000000006111b262f38424a50535b60606060606060605d54514c433a31271e150b020000000000000000000000000000000000000b1724313e4a5764717d8a979f9f9f9f9f9f9f9f9f9f9f9f9d9184776a5e5144372b1e11000000000000000000000000000001080e1317191a181715110c060000000000000000000000000000000000000000000000000000000000000000000000000008131e28323a41465353535353535353534846423b33291f140900000000000000000000000000020e1a26313e4a5764717e8a98a2aeac9c8f82766a5f53473f352f323c454f59616c727f8c929da09d9da0a7b1aa9c8f8275665c5145382c1f13060000000000000000000000000003090e121415202020202020202020202020202020202020202020202020202020202020202020202020202020202020171614100b0500000000000000020d18222c343b414446464646464646464639352f2820160c010000000000000000000000000000000a151e262e343846464646464646464646433e372e251b10050008141f2a343e464d515253535353535353534f4d48423930231a0d04000000000000000000000000000a16202b343d43474953535353535353534f4940372c21160a000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060605b59534a41362b201408000000000000000000000000000000000000000b17222d3a4754616d7a87939393938d8174675a4e4134271b0e000916222f3c4955626f7c8893939393938b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111b242d34393d3e464646464646463c3b37322a22180e0400000000040d161e24292c393939393939393933322f2a241c130a00000000000000000000000000000000000000000000000000000000000000000000000000000a15202935414c555f6a6f7c8590959fa3a9a19e9a96979291909192999a9fa2aaa29f9590857b6e695e53493f31281d13070000000d1a2633404d596673808c99a4aa9d91847a6d675c544a3f45525e6b7885919ea8a5998c7f726c625a50473d342a21180e0500000000000000000000000000000000000000000000000000000000000000000000000003080b0d0e13131313131313130d0c0a06020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131d262f363c40414646464646464646403e3b352e251c130a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262f383f44464e5353535353535353504745413a31281f150c03000000000000000000000000000000000000000b1724313e4a5764717e8a93939393939393939393939393939184776a5e5144372b1e110000000000000000000000000000000003070b0d0d0b0b09050100000000000000000000000000000000000000000000000000000000000000000000000000010d1925303a444c525f60606060606060605f524d453b30251a0e02000000000000000000000000000914202d3a4753606d7985929fabab9f94887c6f625b5145403937333d46505a626d74808d939ea7aaabb1aea2988b7e7164544b4034281c1004000000000000000000000000000000020608081313131313131313131313131313131313131313131313131313131313131313131313131313131313130a0907040000000000000000000006101a222a3035383939393939393939392c29241e160d0400000000000000000000000000000000030c151c23282c3939393939393939393937332c251c13090000020d18222c343b414446464646464646464642413d3730271e11080000000000000000000000000000040f19222b32383b3c4646464646464646433e372e251b1005000915202b353f474e5253535353535353535353535353535353535353535353535353535353535353535353535353535353535353534e4c4841382f251a0f03000000000000000000000000000000000000000613202d3946525e687783868686868684776b5e5144382b1e11000916222f3c4955626f7c868686868686867e7164584b3e3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b22292d3031393939393939392f2e2b2620181006000000000000040c13191d202d2d2d2d2d2d2d2d2625231e19120a010000000000000000000000000000000000000000000000000000000000000000000000000000040d19242f3a434e58606a6f7b838c92989ea1a9a7a9a29f9d9d9e9fa3aba9a19e98928d837b6e695f574d41382d1f160c010000000d1a2633404d596673808c99a3ac9f92867c6f695f564c4345525e6b7885919ea6a89c8f82786d605c52493f362c2319100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b141d252b303334393939393939393933322f2a231c130a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d262d333839424646464646464646443a39352f281f160d0300000000000000000000000000000000000000000b1724313e4a5764717e8686868686868686868686868686868684776a5e5144372b1e1100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111d2a36414c565e6c6c6c6c6c6c6c6c6c6c5e574d42362a1e12050000000000000000000000000006131f2c3945515d6774818d99a3afa69c8f82766d625a514b474242414148515b606c78818f959fabb8b4aa9f92857a6d6054473a2e23180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810181f25292b2c2d2d2d2d2d2d2d2d201d19130c04000000000000000000000000000000000000030a11171c1f2d2d2d2d2d2d2d2d2d2d2b27211b130a0100000006101a222a3035383939393939393939393534312c251e150c0000000000000000000000000000000007101920272b2e2f393939393939393937332c251c13090000040f19242d353d4245464646464646464646464646464646464646464646464646464646464646464646464646464646464646464641403c362f261d1308000000000000000000000000000000000000000005111e2a36414c5667717779797979797772675c4f43372a1d11000815212e3b47535f6a7679797979797979716c6256493d3024170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000911171d2124252d2d2d2d2d2d2d22211f1b150e06000000000000000001080d111314202020202020201a1916130d07000000000000000000000000000000000000000000000000000000000000000000000000000000000008131e28313c464e5860696e7980868d9197999c9d9fa3aaaaa9a19e9c9a97928d8680796e695f574d453b2f261b0d04000000000a1623303d495663707d87929aa4a29891857b6e685e554b424e5b6874818e949fa79e948e81746e635b51483e352b22180f060000000000000000000000000000000000000000000000000000000000000000000000000000030607090b0d0f1111121313121211100f0d0a08070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b131a202427272d2d2d2d2d2d2d2d2625231e19120a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c22282b2d353939393939393939372d2c29241e160d040000000000000000000000000000000000000000000a1723303c4955616c71797979797979797979797979797979797771675b4f43362a1d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f1013130f0e0c09040000000000000713202d3946525e6876797979797979797976695e52463a2d2014070000000000000000000000000004101d2935404b55616e7b87929fa9ab9f948b7f726c605d55534d4e4e4e4b51535b666d7983909da9b6aea2988d8073675d5145392c1d1207000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d14191c1f1f202020202020201413110d0801000000000000000000000000000000000000000000060c1012202020202020202020201e1b1610090100000000000810181f25292b2c2d2d2d2d2d2d2d2d282825201b140c030000000000000000000000000000000000070f161b1f22232d2d2d2d2d2d2d2d2b27211b130a0100000008121b242b31363839393939393939393939393939393939393939393939393939393939393939393939393939393939393939393433302b251d140b010000000000000000000000000000000000000000010d1925303a44555f676a6c6c6c6c6c6b6760564b3f33271b0e0006131f2b37434e585f626c6c6c6c6c6c6c64625a5045392d21150800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c11151718202020202020201615130f0a04000000000000000000000001040707131313131313130d0c0a0702000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c161f2a333d464e575f676d737b8085898c8f919298a3a8a196918f8d8985807b736d675e574d453c33291d140a00000000000916222f3b4854606b717e88939fa4a19791847a6d675d544a4653606d78828f959fa69d938d80736d625a50473d342a21180e050000000000000000000000000000000000000000000000000000000000000000000104060b10121315171a1c1d1e1f1f201f1f1e1d1b19171514120e0906030000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080f14181a1b2020202020202020191916120d070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171c1f20282d2d2d2d2d2d2d2d2a21201d19130c04000000000000000000000000000000000000000000000814212d3945505a61646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a675f564b3f33271b0e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1c1d20201c1b1915100902000000000714212e3a4754616d7a86868686868686867b6e6154483b2e21150800000000000000000000000000000c18242f3946535f6974808d96a1aba69f92877e736d67615f575b5a5b555d60636a6f7a83909daab6ab9f92857a6d61554b42382d2217110800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d101213131313131313130707040100000000000000000000000000000000000000000000000000030613131313131313131313120f0a050000000000000000060d14191c1f1f20202020202020201c1b19150f090200000000000000000000000000000000000000040a0f13151620202020202020201e1b16100901000000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d282724201a130b020000000000000000000000000000000000000000000008131e2932434d555b5d60606060605e5c564e44392e23170b00030f1b26323c464e535560606060606060585650483e34291d110500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005080a0b1313131313131309080603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d18212b343d454d555d60696e73787c7f828486929fa196898482807d79746e69605c554d453c332a21170b0200000000000713202c38444f59616c727f8c929da5a0969083796d665c5044515c666d79839096a0a59c928b7f726c61594f463c332920170d0400000000000000000000000000000000000000000000000000000000000001070d1113171c1f20222426292a2b2b2c2c2c2b2b2a28262422211e1a1312100c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000003080b0d0e13131313131313130d0c0a06020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f12131b20202020202020201d1413110d0801000000000000000000000000000000000000000000000004111c28333e48505557606060606060606060606060606060605e5b564d44392e23170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d151c2226292a2d2d292825211b140c030000000714212e3a4754616d7a87939393939393877b6e6154483b2e211508000000000000000000000000000007121d2a36424d57606d7a849199a3aba39992878079736e696968676869676d70757c8490959fabb3ab9e91847a6e675d544a3f3328231a100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d10121313131313131313130f0e0c09040000000000000000000000000000000000000000000000030608091313131313131313120f0a050000000000000000080f151a1d1f20202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b1a18140f08010000000000000000000000000000000000000000000000020d1720313b434a4f515353535353514f4b443c32281d120600000a15202a343c434749535353535353534b49453e362d22170c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010407070b0d0f111213131212100e0c080705020000000000000000000000000000000000000000000000000000000000060f19222b333c434b51565e61666c6f7375777e8a979e9184787673706d66615e56514b433b332a21180f0500000000000003101b27323d47505a626d73808d939ea69f958f82786d605b524a545d676d7a849197a1a49f93887e716b60584e453b32291f160c0300000000000000000000000000000000000000000000000000000003090e13181d2023282b2d2f3133353737383939393837373533312e2d2a26201f1c17110d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306060f1313131313131313110706040100000000000000000000000000000000000000000000000000000c17222c363e45494a53535353535353535353535353535353514f4b443b32281d12060000000000000000000000000000000000000000000000000000000000000000000000000000000000030d161f272d32353639393534312c261e150c0200000714212e3a4754616d7a87949f9f9f9f94877b6e6154483b2e2115080000000000000000000000000000010e1a26313b45525d686f7d879299a3aaa399938d847f7b787675747475777a7d828991969fa7aca6a8a1969083796d665b50443f362c22190f05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507080b0e111112131312110f0c0908060300000000000000000406070b0f1213131211100e0c0b0906010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090e111213131313131313131313131313131313131313131313131313131313131313131313131313131313131313130e0d0b08030000000000000000000000000000000000000000000000000000050e1f2931393f4244464646464644433f39322a20160c010000040e18222a32373b3c464646464646463e3d39342d241b110600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010406070a0d10111213131211100d0a07060400000000030505060606060606000000000000000000000000000000000000000000000000000002080d111314171a1c1e1f1f201f1f1d1b181514120e090400000000000000000000000000000000000000000000000000000000071019212a313940454d52545b60636669707d8a979e9185786b6763605c54524d454039302921180f0600000000000000000b16212b353e48515b606c77818e949fa79e948e81746d635a504b555e686e7b859198a2a49a92877d706a5f574d443a31281e150b02000000000000000000000000000000000000000000000000040a0f151a1d24292c2e34383a3c3e404244444546464545444342403d3b3a36312d2c28231c19130d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000040607090c0e1011121313131211100f0d0b080705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101a242c33393c3e4646464646464646464646464646464644433f39322920160b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2831383e4243464642413d3730271e140900000714212e3a4754616d7a8794a0acaca194877b6e6154483b2e21150800000000000000000000000000000009141f2935414c56606b717e879298a0a8a49f97918c8885838181818283868a8f939da0a8a39f999b9e9f958f81786c605b51483e342b21170d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e121415181b1d1e1f201f1f1d1b191515120f0a0401000000070c101313181c1e1f201f1e1d1b181815120d0600000000000000000004090e111213131313131313131313131313131313131313131313131313131211100e0c0a07060400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d171f272e33363739393939393837332e2820180e040000000006101820262b2e2f3939393939393931302d29221b120900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080d111314171a1d1e1f1f201f1e1c1a171413100c07010c0f1112131313131313090907030000000000000000000000000000000000000000050b1013191d20212427292b2b2c2c2c2b2a282522211e1a14100c07010000000000000000000000000000000000000000000000000000070f181f272f353b42464a5053565964707d8a979e9185786b5e5653504a46423b342e271e170f06000000000000000000040f19232c363f44505b656d78828f95a0a69d938c80736c62594f4c565f696f7c869299a3a39992867c6f695f564c433a30271d140a0000000000000000000000000000000000000000000000070c151b20262b2f35393a3f4446484a4d4f5051525253525251504e4c4a4846423d3a38342e29251e19140d050000000000000000000000000000000000000000000000000000000000000000000000000004070c10121316191b1d1e1f1f201f1f1e1d1b19171414110e0806030000000000000000000000000000000000000000000000000004090e1112131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130b0a080400000000000000000008121a22282d3031393939393939393939393939393939393736332e2820170e04000000000000000000000000000000000000000000000000000000000000000000000000000000000005111c27313a434a4e5053534f4d49423930261b1004000714212e3a4754616d7a8794a0adaea194877b6e6154483b2e211508000000000000000000000000000000030d19242f3a444f59616c717e8691969fa2a9a19e9997918f8e8d8e8f9092999b9ea5a69f99928d8e939e9e938d80746d625a50463d33291f140900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f141a1e212125282a2b2c2c2c2b2a282622211f1b15110d08030b12181c1f2025292b2c2c2c2b2a272524221d18110901000000000000080f151a1d1f202020202020202020202020202020202020202020202020201f1f1e1d1b19161413100c07040100000000000000000000000000000000000000000000000407090a13131313131313131313131313131313131313131313131313131313131313131313131313131313130b0a080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d151c2227292a2d2d2d2d2d2b2a27231d160e06000000000000060e151b1f21222d2d2d2d2d2d2d2524211d171109000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e13191d20212427292b2b2c2c2c2b292724201f1c18120e181c1e1f2020202020201615130f0a0400000000000000000000000000000000040a0f171c1e24292c2d3133363738393939383735322e2d2a261f1d18120b060000000000000000000000000000000000000000000000000000060d151d24293036383f44464a5764707d8a979e9185786b5e5246443f38363028231d150c05000000000000000000000007111a2427333f49535c666d79839096a1a59c928b7e716b61584e4d575f6a707d879299a4a29891857b6e685e554b42392f261b11060000000000000000000000000000000000000000030b121820262b31373a4145474a50535557595c5d5e5e5f5f5f5e5e5d5b595755534d4946443f3835302a251e170e0802000000000000000000000000000000000000000000000000000000000000000001070c1013181c1f20232527292b2b2c2d2c2c2b2a28262421201e1915120f0a0300000000000000000000000000000000000000000000080f151a1d1f20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020171714110c0500000000000000000810171c2123242d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b2a27231d160e050000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16222d38434c545a5d60605c59544b42372c211509000714212e3a4754616d7a8794a0adaea194877b6e6154483b2e2115080000000000000000000000000000000008131e28323d47505a616c717c848c92989d9fa4a9a19e9c9b9a9b9c9d9fa3a9a29f9a94908780818e949f9d928b7f726c61584e453b31251a0e020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c161b1f252a2d2e31343738393939383735322f2e2b26201d19130c151d23282c2d32353839393838363432312e29231b1309000000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2c2b29282623201f1d1813110d080100000000000000000000000000000000000000050b101416172020202020202020202020202020202020202020202020202020202020202020202020202020202020171714110c05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b11161a1d1e20202020201e1d1b17120c040000000000000000040a0f13151620202020202020181715110c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e141a1e24292c2d3033363738393939383634302d2c29231d1a24282b2c2d2d2d2d2d2d23221f1b160f070000000000000000000000000000070f151b22282d3035393a3e404244454646454543413f3b3a36312c29241d17110a0200000000000000000000000000000000000000000000000000030b12181f252a2d33383d4a5764707d8a979e9185786b5e524538342e2a251f18120b0300000000000000000000000000091217222d38414b545d676e7a849197a1a49f92877d706a60574d4e58606b717e87939fa4a19791847a6d675d544a41382d22171209000000000000000000000000000000000000070c151d232831373c42474b5154545c60626466686a6a6b6c6c6c6b6a6a686664615f575653504a46413a3630292019130d05000000000000000000000000000000000000000000000000000000000003090e12181d1f23282c2d3032343638383939393838373533312e2d2a25211f1b150f0b060000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c1710080000000000000000050c11141717202020202020202020202020202020201e1d1b17120b04000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1a26323e4a545e66696c6c68655d54493d3125190c000714212e3a4754616d7a8794a0a2a2a194877b6e6154483b2e21150800000000000000000000000000000000010c16202b343e48505a616a6f797f858b90939a9a9c9d9e9f9f9f9e9d9c9a9897928d88837c7378828f95a09f93877e706a60574d42362a1e1205000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a111720272b31363a3b3e4144444546464544423f3c3b37322c29241e191e272e34383a3e42454646454443413f3d3a342d251b110600000008121b242b31363839393939393939393939393939393939393939393939393939393837363432302d2c2924201d19130e0902000000000000000000000000000000000810161c2023232d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c17100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a0e1011131313131311110e0b0601000000000000000000000003060809131313131313130b0a0805000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070f181f262a2f35393a3d404344454646454443403d3a38342f2a252f3437383939393939392f2e2c272119100700000000000000000000000009101920272b33393a4145474a4d4f515252535252504e4b4846423b39352f27221b140b050000000000000000000000000000000000000000000000000001070c14191c2228313d4a5764707d8a93939185786b5e52453828231c19140c070000000000000000000000000000000006111b262f39424c555e686e7b859298a2a39992867c6f695f564c4f59616c727f8b929ca5a0969083796d665c53493f3327241a1007000000000000000000000000000000000810191e272e343c43474d53555d6064666d6f7173757777787979787877767573706e696763605c54524c46413b322a251e170e06000000000000000000000000000000000000000000000000000001070c141a1d24292c2e34383a3c3f4143444546464645444342403e3b3936302e2b261f1c17110a020000000000000000000000000000000008121b242b3136383939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393931302d28221a120800000000000000000004080a0b1313131313131313131313131313131311100e0b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1c2935424e5a6670767979756f65594d4134281b0e000714212e3a4754616d7a87949595959594877b6e6154483b2e2115080000000000000000000000000000000000040d19222d363e48505860676d737a7f83878a8d8f90929292929190908e8b8885807c766f6a6d7a8390969a9992867c6f695e53463a2d2114070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151c232832373b4246484b4e505152535252504e4c4847433c39352f28222b30394045464b4f5152535251504e4b4a463f372d23180d0100040f19242d353d42454646464646464646464646464646464646464646464646464646454443413f3d3a38352f2c29241e1a140c06000000000000000000000000000008111a21272c2f30393939393939393939393939393939393939393939393939393939393939393939393939393939393931302d28221a120800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b1218212a31363a4145474a4d505152525352514f4d4a4745403936313a4044454646464646463c3b38322b22190f04000000000000000000020a131b222b32373e44494c5254575a5c5e5e5f5f5f5e5d5b5855534d47454039332d261d170e06000000000000000000000000000000000000000000000000000002090e111724313d4a5764707d8686868684786b5e5245382b17110e09020000000000000000000000000000000000000a141d27303a434c565f696f7c869299a3a29892857b6e685e554b505a626d73808d939da69f958f82786d655b50443f362c22190f04000000000000000000000000000009111a222a303940454e53575f62676d7175797b7d8082838485858685858483817f7d7b7874706d66615e56524c443e36302920180f07000000000000000000000000000000000000000000000000030b12181f252a2f35393a404446494c4e5051525253525251504e4c4a4746413c3a37312b28221c140b070000000000000000000000000000040f19242d353d4245464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646463e3c39332c241a1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768286868175685c4f4235291c0f000714212e3a4754616d7a87888888888888877b6e6154483b2e21150800000000000000000000000000000000000007101b242d363e464e555c60676d72767b7e80828485858685848483817e7c79746f6a625f686e7b848d8d8d8d8d857b6e6154483b2e21150800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d151e262e343d43474d5354585b5d5e5f5f5f5e5d5b5955534e4745413a3129343c424b5153585c5e5f5f5f5e5d5a585651493f34291d1206000915202b353f474e5253535353535353535353535353535353535353535353535353525251504e4c494745403a39352f2a251f17110a03000000000000000000000005101a232c33383c3d46464646464646464646464646464646464646464646464646464646464646464646464646464646463e3c39332c241a100500000000000004090e111213131313131313131306040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090e111213131313131313131306040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151c2328333b42464c5254575a5c5e5e5f5f5f5e5c5a5753514b46423b454c50525353535353534948433d342b21160a0000000000000000000a141c252d343d43475055565d606466696a6b6c6c6c6b6a6865615f5753514b443f382f292018100600000000000000000000000000000000000000000000000000000000061623303c4955616c70797979797872685c5043372a1e06000000000000000000000000000000000000000000020b151e28313b444d57606a707d87929fa3a19791847a6e675d544a515b636e74818e949ea79f948e81776c605b51483e342b21160a0000000000000000000000000009121b232c343c424b51585f62696e747a7d8185888a8c8f9091919292929191908e8c8a8884807d79736d68615e565046413a322a2119100700000000000000000000000000000000000000000000060d151d24293136394045474a515356585a5c5e5e5f605f5f5e5d5b595754524c4847433c38332d261d18120b030000000000000000000000000915202b353f474e52535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534a49453e362c22170c00000000000000000000000000000000000000010406070a0c0e101112131313121211100e0c0a070604010000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000713202d3a4653606d787c7c7c7c7c7c7c7c786d6053463a2d2013070000000000000000000000000000000000000009121b242d343d434b51555d6065696e717375777879797978777674716f6d66625f58565e696f7c8181818181807f7265584b3f3225180c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151f2730383f444e54575e6164676a6b6c6c6c6b6a6865625f5854524c433f353c464e545c6065686b6c6c6b6b696765625b51463a2e221509000e1a26313d4751595e5f60606060606060606060606060606060606060606060605f5f5f5e5c5b595653514b4745413a363028231c150c05000000000000000000000b16212c353d44484a53535353535353535353535353535353535353535353535353535353535353535353535353535353534a49453e362c22170c0000000000080f151a1d1f20202020202020202013100c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1d1f20202020202020202013100c070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151e272e343f454d53565d606366696a6b6c6c6c6b696763605c55534d444f575c5f60606060606056544e463d32271b0f030000000000000009121c262e373f464e545a6164686d7173757778797978787674726e6965605d555049413a322a221810060000000000000000000000000000000000000000000000000000000814202d3944505a61646c6c6c6c6b6860564b4034281b0f00000000000000000000000000000000000000000000030c161f29323c454e58616b717e8b919ca4a0969083796d665c5349525c606d78828f959fa69e938d80736d625a50473d32271b0f03000000000000000000000009121b242d353e464e545c606a6f757b81868a8e929797999b9d9d9e9f9f9f9e9d9d9b999796918d8985807a746e68615a524c443c332b2219100700000000000000000000000000000000000000000910181f272f353b42464b5153545c60636567696b6b6c6c6c6b6b6a686664615e5655534e46443f382f28231d150c0500000000000000000000000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060575550483e33281c11040000000000000000000000000000000104080d11131417191b1d1e1f1f20201f1e1e1d1b19161413100d0704000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f0006121f2c3844505c666d6f6f6f6f6f6f6f6f6d665c5144382c1f1206000000000000000000000000000000000000000009121b222b313940454b5154575e616467696a6b6c6c6c6b6a69676562605c54534e4d575f6a6f747474747474726d62564a3d3124180b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d273139424a50586062696e71747777787979787775726f6a66605d56504540454e5860666d717578797978777674726d62564a3d3124180b00111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a69676563605d5554524c46423b342e261e170f06000000000000000004101c27333d474f55566060606060606060606060606060606060606060606060606060606060606060606060606060606060575550483e33281c110400000009121920262a2c2c2d2d2d2d2d2d2d2d1f1c18120b030000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2d2d1f1c18120b0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121c273039404451575f61686d7073767778797978777673706d67615e57505761686b6c6c6c6c6c6c6260584e43382c1f130700000000000006101b242e384049515860626c70757a7d808284858586858583817e7b77726d67605b534c443c342a22180e05000000000000000000000000000000000000000000000000000004101c28333e48505557606060605e5c564e453a2f23170b0000000000000000000000000000000000000000000000040d17202a333d464f59626c737f8c929da5a0958f82786d655b5044505c666d79839095a0a59d928c7f726c61594f43382c1f13070000000000000000000007101b242d363e474f585f666d737c82878e92989b9ea2a9a6a8aaa8a7a6a6a6a7a8a9a8a6a8a19e9a97928c86807a716c615e564d453c342b22190e0500000000000000000000000000000000000009121b222a313940454d53555d6065666d6f72747677787979797877767573716e6867625f5853504a423d342e271e170e0500000000000000000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d2114080000000000000000000000000002080d1113191d2021232628292b2c2c2c2c2c2b2b2a28252320201d1813100c0700000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f0003101c28343f4a545c606262626262626262605c544a4034281c10040000000000000000000000000000000000000000000910191f272f343a4145474d5254575a5c5d5f5f5f5f5e5d5d5b585553514a4743454e585f6267676767676765625b51463a2e2215090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c18242f39434b545c606a6f757b7e8183848586858583817f7c78726d68625a514b4d57606a6f797e82848586858483817f7265584b3f3225180c00121f2c3845525e6a7579797979797979797979797979797979797979797979797979797877767472706d6765605d56524d443f38302921180f06000000000000000714202c38444f5961636c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d211408000008121b242b3136383939393939393939392c29231d150d03000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242b3136383939393939393939392c29231d150d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18232e39424a515b63696e747a7d808384858586858482807d79746e69605b536873787979797979796f6a6054483b2e2215090000000000030e18222d36404a525b626a6f767d82868a8d8f919192929291908e8b88847e79716c655e564e463c342a20170c0300000000000000000000000000000000000000000000000000000b17222c363e44494a5353535352504b453c33281e1207000000000000000000000000000000000000000000000000050e18212b343e47505a636d74808d939ea69f948e81776c6053464a545d676d7a839196a1a49f93887e716b6054483b2f221509000000000000000000050e19222d363e485059616a6f7980878f93999fa3aaabaaaaa29f9d9b9a9a999a9a9b9d9fa2aaa9aba9a19e98928d857e756d685f574e463c342a20170c030000000000000000000000000000000009121b242c343c434b51575e61676d7175797c7f81838485858685858483817f7d7a77736f6a64605b544f454039302920170f05000000000000000000121f2c3845525e6a7579797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979716c6155493c3023170a000000000000000000000001080d13191d2024292c2d303335363738393939393837363432302d2c29241f1c18120b060000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f00000c17232e38424a5053555555555555555553514a42392e23180c0000000000000000000000000000000000000000000000070d151d23292f35393b4246474a4d4f51525253525151504e4b4946444039373c464e53555a5a5a5a5a5a585651493f34291d120600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141e2935404b555d666d747c82878b8e909192929291908e8c88847f7a716d605d55535f696f7c848b8f9192929291908d86796c605346392d20130013202c3946535f6c798786868686868686868686868686868686868686868686868685858483817f7c7976726d68615e57504a423b332a22180f050000000000000916232f3c4855616b707979797979797979797979797979797979797979797979797979797979797979797979797979797979716c6155493c3023170a00040f19242d353d424546464646464646464638342f271f150b01000000000000000000000000000000000000000000000000000000000000000000000000000000040f19242d353d424546464646464646464638342f271f150b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c2834404a545c606d727b81868a8d8f9191929292918f8d8a85807b726c655c6b78858686868686867c6f6256493c2f23160900000000000a15202a343e48525c636d727c838a8f9299999c9d9e9f9f9f9e9d9b9895908b857e776d685f584e463c32291e150a000000000000000000000000000000000000000000000000000005101a232c33393c3d464646464543403a332a21170c0100000000000000000000000000000000000000000000000000060f19222c353f48515b606c78818f94939393938c7f7366594c424b555d686e7b84919793939a92867c6f6356493c302316090000000000000000020d17202b343e48505a616b707c838c92999fa4abaca7a09d999892908f8d8d8d8d8d8f909298989c9fa4abaaa29f97928a827a6e6960584e463c32291e150b00000000000000000000000000000008121b242d363e464e555d60696e74797e8285898b8d8f91919293929291908e8c8a8784807c76716c666059514b433b332921170e05000000000000000013202c3946535f6c79878686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867e7164574a3e3124170b00000000000000000000040c13191e24292c2f35393a3d3f4143444546464645454443413f3d3a39352f2c28231d17110a02000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000006111c2630383f444649494949494949494644403930271c1207000000000000000000000000000000000000000000000000030b12181d24292c30363a3b3e40424445464646454443413e3c3a38342e2b343c4347484e4e4e4e4e4e4b4a463f372d23180c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c26303845515d676d7880898f93999a9d9e9f9f9f9e9d9b9896918c857e756d675d58626e7b8691969b9e9f9f9e9e9c9386796c605346392d20130013202c3946535f6c79869293939393939393939393939393939393939393939399929292918f8e8c8986827e7a746e69605c544d453c342a21170c0200000000000a1723303d4a5663707d86868686868686868686868686868686868686868686868686868686868686868686868686868686867e7164574a3e3124170b000915202b353f474e5253535353535353535345403931271d12070000000000000000000000000000000000000000000000000000000000000000000000000000000915202b353f474e5253535353535353535345403931271d12070000000000000000000000000000000000000000000000000000000000000000000000000000000000030e18212c3844515c666d757f878d9298999c9d9e9f9f9f9e9c9a98928d867f776d666679869293939393887b6e6255483b2f22150800000000030f1b26313c46505a636e737f8790949c9fa3aba8a5a3a1a1a1a3a5a7a7a09d97928b827a6f6a5f584e443b30261c1106000000000000000000000000000000000000000000000000000008111a22282d3031393939393837342f2821180f0500000000000000000000000000000000000000000000000000000007101a232d364044505b666d79828686868686868275695c4f42434c565e696f7c858686868686867f7265584c3f3225190c000000000000000009141f29323d46505a626c717d8690959fa3ababa49f9b95908c898584828180808081828385888b8f93999fa2aaa9a19e938f847b6f6a60584e443b30271d12070000000000000000000000000006101a242d363f4850585f676d737b80858b8f9298989a9c9e9e9f9f9f9e9e9d9b999795908d88837e786f6b605c554d453b332920170c030000000000000013202c3946535f6c798692939393939393939393939393939393939393939393939393939393939393939393939393939393939393938a7e7164574a3e3124170b000000000000000000070d161e24293035393a4145474a4c4e505152525353525151504e4c494745403a38342e27221b140b060000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f00000c17232e38424a5053555555555555555553514a42392e23180c0000000000000000000000000000000000000000000000000001070c13181d20252a2d2e313436373839393938373634322f2d2c2823222a31373a3c4141414141413f3d3a342d251b110600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e3842505a606d79828d929b9fa4ababa39f9d9c9b9c9d9fa19e97928b82796d685f6a76828f98a1a8aaa39f9995949386796c605346392d20130013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9f9e9d9c9a9899928f8b86817b736d665e574e463c33291e140a00000000000a1723303d4a5663707d899393939393939393939393939393939393939393939393939393939393939393939393939393938a7d7164574a3e3124170b000e1a26313d4751595e5f606060606060605f514b43392f23180c0000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26313d4751595e5f606060606060605f514b43392f23180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000915202c38434f59606d78818c92999fa2aaa9a8aaa29f9e9e9e9fa29f98928c81786d6d798699a39f9f94877a6e6154473b2e2114080000000006121f2b37434e58626c73808b92999fa6aca49f9c989695949596989c9fa4a9a19e948f847c6f6a5f564d42382e23170c0300000000000000000000000000000000000000000000000000000810171c2023242d2d2d2d2b2a28231e170f06000000000000000000000000000000000000000000000000000000000008111b2428333f4a545c676d767979797979797570655a4d413a444d575f6a6f78797979797979726d62564a3e3124180b00000000000000030d1925303b444e58626c717e879298a0a7afa79f99938e88837f7c79777574737373747577797c7f83878d92989ea5ada59e9691857c6f6a5f564c42392e23180c030000000000000000000000030c18222c363f48505a616a6f7980868d92979c9fa2aaa7a9a8a7a6a6a6a7a8a9a8a6a7a09d9a94908a837c746d675e574d453b32291e150a0000000000000013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b00000000000000000810181f282f353a4145474c525456595b5c5e5f5f5f5f5f5e5e5d5b585653514b46454039332d261d180f0700000000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f0003101c28343f4a545c606262626262626262605c544a4034281c1004000000000000000000000000000000000000000000000000000001070d11141a1e20212427292a2c2c2c2c2b2a2a282522201f1c181820262b2e2f34343434343432312e29231b1309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54616c74818e949da4aca7a09d9992908f8f8f9192999a9e9f948f837a6d666f7c88949faaaea398928c88878886796c605346392d20130013202c3946535f6c7986929facacacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a7a8a9a7aba39f9c98928d867f786e695f584e453b30261c1106000000000a1723303d4a5663707d89969f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b00111d2a36424e59636a6c6c6c6c6c6c6c6c6c5c554b4034291c10040000000000000000000000000000000000000000000000000000000000000000000000000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c5c554b4034291c1004000000000000000000000000000000000000000000000000000000000000000000000000000000020e1a26313b4854606b74808d939fa3ababa49f9b979892919192939a989d9f938f82786d7a8794abb4a094877a6d6154473a2e211407000000000815212e3a47535f6a717e8b929fa3aba69f9a938f8c89888788898c90939a9ea6a69f9691857c6f685e544a3f34281f1409000000000000000000000000000000000000000000000000000000050b10141617202020201f1e1b17120c0500000000000000000000000000000000000000000000000000000000000000091217222d38424b555c60696c6c6c6c6c6c69655e54493d323b454e585f626c6c6c6c6c6c6c65625b51463a2e221509000000000000010b151f2a36424d56606a717e889299a2aaafa49c959087817c77726f6d6668676766676768666c6f72767b80868e939fa3aaa8a09792867c6f685e544b40342820150900000000000000000000000b151e2a343e48505a626c717c848c92989fa2a9aca8a8a09e9c9a9a999a9a9b9d9fa3ababaaa69f9c95908781796e695e574d443b30261c110600000000000013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4978a7d7164574a3e3124170b0000000000000008111a222a313a41454c5254565d60636668696a6b6c6c6c6c6b6a69676563605d5553514b443f382f2a21191107000000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f0006121f2c3844505c666d6f6f6f6f6f6f6f6f6d665c5144382c1f1206000000000000000000000000000000000000000000000000000000000104090e111414171a1c1e1f1f201f1e1e1d1b18161312100c0e151b1f21222727272727272524221d18110900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2b3844505c66717e8b939ea6aea59d95908a86838282838486898d92979f959083786d73808d99a6b0a89f9286807c7a7b7d7063574a3d3024170a0013202c3946535f6c7986929facb9ada39b9898989898989898989898989898989899999a9c9ea1a8a9acaaa29f98928c837b6e6a5f574d42382e23170b010000000a1723303d4a5663707d8996a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1978a7d7164574a3e3124170b00121f2c3845525e6a75797979797979797976675c5145382c1f13060000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525e6a75797979797979797976675c5145382c1f130600000000000000000000000000000000000000000000000000000000000000000000000000000006121e2b37424e57636f7c87939fa5afa9a199938f8a878584848586888c90959e948d80747b8794a1ada093877a6d6054473a2d2114070000000713202c38444f59626f7c86929fa4afa49c948f87827f7c7b7a7b7c7f83878f949fa3a8a19791857a6e665c50443b31261a0e030000000000000000000000000000000000000000000000000000000004080a0a1313131312110f0b070100000000000000000000000000000000000000000000000000000000000000000006111c262f39434b51535d6060606060605c5a544c423729333c464e53555f606060606060585651493f34291e120600000000000007121d27313946525e696f7c86929aa3ababa39f928d837c756f6a6662605c545a5a5a5a5a545b606265696e747b818a9298a2a9a9a19891847a6e665c51453c31261a0e0500000000000000000007121d27303c46505a626c717e8691969fa2aaaba39f9b9796918f8e8d8d8d8d8f9092999a9ea1a9aba79f9a938d837b6e695e564c42382e23170c04000000000013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a978a7d7164574a3e3124170b00000000000007101a242c343c434c51565d6065686d707274767778797979787877767472706d6764605c555049413c332b231910070000000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000713202d3a4653606d787c7c7c7c7c7c7c7c786d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000020507080b0d0f11121313131211100e0b0907060400040a0f1215151b1b1b1b1b1b181815120c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7884919ea5afa69d938e837d797776757677797c80858c9298958e81747683909ca9aca0958a7e736f6e6e706b6155483c2f2316090013202c3946535f6c7986929facb9a79b918b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8d8d8f9196979c9fa3abaaa29f9590847c6e695e544a3f34281d13070000000a1723303d4a5663707d899494949494949494949494949494949494949494949494949494949494949494949494949494948a7d7164574a3e3124170b0013202c3946535f6c798786868686868686796d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c798786868686868686796d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000814212e3a47535f6a76828f9aa4afaba1979287827d7a79787778797b7f838a9196928a7e7b8895a1ada093867a6d6053473a2d2014070000000916222f3b4854606b76828f98a2aea49c928c827b7672706e6e6e7072767c828b9299a3a9a1979082786d60574d42362a20150a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d273139404547505353535353534f4d49423930212a343c434748525353535353534c4a463f372d23180d010000000000000c18232f3943505a616e7b859198a3acaca399928b80786f6a625f585653504a4e4d4d4d4e4a505355575e61696e757e869297a2aaaaa1969082786d60574e42372b21170b0000000000000000000c18232e39424e58616c717f8a9298a0a8aba49f99928e8a8784828180808081828486898d92979ea1a8aca49f9590847b6e685e544a3f342820150a000000000013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8a7e7164574a3e3124170b0000000000040e19222c363e464e555d60686d72767a7d7f8183848585868685848483817f7c7a75706d67605b534e463d352b22190d0400000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87888888888888877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000000000000000000000001030405060606050403010000000000000000030608090e0e0e0e0e0e0c0b09060100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8a96a0acac9f948e8179716d67696869676d70747a7f869095938a7e7885929fabaa9d9184776c6261616361594f44382c2014070013202c3946535f6c7986929facb2a5988b7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80808284878b8f92999fa7aea79f9691847b6e665c50443a2f24180d0100000a1723303d4a5663707d87878787878787878787878787878787878787878787878787878787878787878787878787878787877e7164574a3e3124170b0013202c3946535f6c7986929393939393867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929393939393867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000815222f3b4855626e7b88949facaea39992857d75716e686b6b666d6e72767d84909492857d8996a3aca09386796d6053463a2d201307000005111e2a36424d5663707d89949faaa79d928c80766e69656362616263656a6f767f879299a4a99f948c7f73695f53463c31261a0f010000000000000000000005080a0b1313131313131313131313131313131313131313131313131313131313131313131313130f0f0d09040000000000000000000000000000000000000000020b151f272f34383a4346464646464642413d3730271e222a31373a3c454646464646463f3e3a342d251b110600000000000004101c2934404b55616c76828f97a1aaafa49a92877e736d665f58534e4946443f41404040413f4446484d53565e616c717c859298a2aca89f948d80736a5f53473e33281c10040000000000000004101c2834404b545f6a717e87939fa2aaa9a199938e86827e7a777574737373747577797c80858b91969da5afa79f9691847a6e665c50443c32261b0f040000000013202c3946535f6c7986929facb3a79a8d80808080808080808080808080808080808080808080808080808080808080808080808080807c6f6255483c2f22150900000000020c16202b343e4850585f676d737a7f8386898c8e8f9192929292929191908e8b8986827d79716c655f584f473d342b20160c01000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87949595959594877b6e6154483b2e211508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005121e2a36424d576875818e9ba8afa49a8f82786d66605d555c555c6063676d727b838f9391857b8797a2ada79a8d8074675a545557554f473e33281c10040013202c3946535f6c7986929facada093867972727272727272727272727272727272737475787a7e828790959da4aea9a1969083786d60554b4135291d110400000713202d3a4653606d787a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a796d6053463a2d2013070013202c3946535f6c7986929f9f9f9f93867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929f9f9f9f93867a6d6053473a2d2014070606060606060606060504020000000000000000000000000000000000000000000000000000000d192633404c5966737f8c99a6b0ac9f92877c6f6b64615e56545c6062656c707a8290949083909daaaca09386796d6053463a2d20130700000714202d3a46525e6976828f9ca6aca0958d80736d625f575655545556585f626d727e87939fa6a69f92867b6e61584e43372b1e13080000000000000000060c111517182020202020202020202020202020202020202020202020202020202020202020202020201c1b191510090200000000000000000000000000000000000000030d151d23292c2d363939393939393635312c261e151820262b2e2f3939393939393932312e29231b13090000000000000006131f2c3845515c67707d8a949fa9b0a69f93887e716c605c544e47433c3a38342e3433342d3338393c42464d525a616a6f7c86929aa4afa69f92877b6e62594f44392d20150a0000000000000006131f2c3845515c666f7c869299a4aea8a0979187817b75716d6869676766676768676d7073797e848e939fa4aca8a0969083786d60584e43372b20150a0000000013202c3946535f6c7986929facada0938679737373737373737373737373737373737373737373737373737373737373737373737373736f6a5f53473a2e2115080000000008131e28323d46505a616a6f7a80868b909399999b9c9d9e9f9f9f9f9e9d9c9a9898928e8a847e786e6a60594f463d32281e1308000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0a2a2a194877b6e6154483b2e2115080000000000000000000000000000000000000000000000000000000000020608080b0e10121213131211100e0b0807050200000000000000000000000000000000000000000000000000000000000000000000000000020507080a0d0f1111121313131211100e0c0906050300000000000000000000000000000000000000000714202d3a46525e697885919eabac9f93877c6f665c54514b4f4b5153555d60696e79818f949083909da9b3a4988b7e7165584b484a48443e352c21160b000013202c3946535f6c7986929facada093867a6d656565656565656565656565656566666769686d71767c838d929da5afa89f958c7f72675d5145392c201307000006131f2c3845515c666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d675c5145382c1f13060013202c3946535f6c7986929facaca093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facaca093867a6d6053473a2d20141313131313131313131212110f0d0a07060401000000000000000000000000000000000000000005111e2a36424d576976838f9ca9b1a79a8d80736a605954524c4a5053555a61676d798290959095a0abaca09386796d6053463a2d20130700000814212e3b4754616e7b87939e9fa39d9083786d605b534d49484748494e535b626c727f8c949faba3988f82756a5f53473a2f24190d010000000000000911171d2124252d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d292825211b140c0300000000000000000000000000000000000000030b12181c1f202a2d2d2d2d2d2d292825211b140c0e151b1f21222c2d2d2d2d2d2d2524221e1811090100000000000003101c28343f4a54606d7984919ea6b0aa9e948c7f736c625a504a423c37322d2c282327272722282b2d31363b42465058606a707e88939fa8aea3998f82766c6155493c31261b0f00000000000004111d2935414b55606d79839098a3aba9a09691857d746e6964615d565b5a5a5a5a555c6063666d7179818b939aa4afa89f958c80736a5f54473d32271b0f0100000013202c3946535f6c7986929facada093867a6d676767676767676767676767676767676767676767676767676767676767676767676767625f584e43372b1f1206000000010d1924303a444e58616c707c848d92989c9fa4a49f9e9c9a9a99999a9a9b9d9fa3a29f9b96918b837c706b60584e443a2f24190d020000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0adaea194877b6e6154483b2e21150800000000000000000000000000000000000000000000000000000104090e121415181b1d1e1f20201f1e1d1a181514120e090401000000000000000000000000000000000000000000000000000000000000000105080e11141417191c1d1e1f20201f1f1e1c1b181513120f0b060000000000000000000000000000000000000815212e3b4854616e7b8797a1adaa9d9083776a5f544b4540424045474b51575f676d78828f9590959fabb0a3968a7d7063574a3d3d3c38332c231a1005000013202c3946535f6c7986929facada093867a6d6058585858585858585858585858595a5a565d60646a6f78808d939eaab1a79e92857a6d6054473a2f24180d010004101c2834404b545c606161616161616161616161616161616161616161616161616161616161616161616161616161616161605c554b4034281c10040013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20202020202020202020201f1f1e1c1a171413110d08040000000000000000000000000000000000000714202d3a46525e697885929fabaca095877b6e61584f4746413f44464850555d676e7b85929da0a7b1aca09386796d6053463a2d20130700000c1926323f4c5965727f8c8f91929996897d70665c5047423d3b3b3b3d4347515a606c77828f99a3aa9f93877c6f62564c4135291d1104000000000009121b22292d30313939393939393939393939393939393939393939393939393939393939393939393939393635312c261e150c020000000000000000000000000000000000000001070c1013141d2020202020201c1b1915100902030a0f1215151f202020202020191815120d06000000000000000006121f2b3844505c66727f8c96a0acaea2988f82776c605a50443f38302b26201f1c171a1a1a171c1f20252a30363e464e58616c73808d96a1acab9f948a7d7064584e43372b1d120700000000000613202c3945515d67737f8c95a0aaada19791847b706b615e5754524c4e4d4d4d4e4b5153545c60676d747f88939fa5afa79f92877c6f62584e43372b1d120700000013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a55534e463c31261b0f0300000005111d2935414c56606a707e8691969fa2a49f9b9993918f8e8d8d8c8d8d8f9092989a9fa2a19e9590867d706a60564c4135291e13080000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0adaea194877b6e6154483b2e21150800000000000000000000000000000000000000000000000001080d11151a1e212225282a2b2c2c2c2b2b2a272421211e1a14100d070100000000000000000000000000000000000000000000000000000002080d1114191e20212426292a2b2c2c2d2c2c2b29272522201f1b17110f0a040000000000000000000000000000000916222f3c4955626f7c8895a9b3a79a8d817467584e4239352f34383a40454d555c666d7a85919d9fa7b1afa396897c706356493d302f2c28211a110800000013202c3946535f6c7986929facada093867a6d60534c4c4c4c4c4c4c4c4c4c4c4c4c4d4d4c5254585f666c78818e98a2aeada2978b7e7265554b4035291d100400000c18232e39424b51535454545454545454545454545454545454585c5c5c5c5c58545454545454545454545454545454545453514b43392e23180c000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d2d2d2d2d2d2c2b2a28262421201d1913100c07000000000000000000000000000000000814212e3b4754616e7b8798a2aeaa9d908377695e53463d393634383a3e434c555e69717e8b97a1adb9aca09386796d6053463a2d20130700000a1723303d4a5663707d80828486888a84776b60544a3f37312f2e2f31373f44505b656e7b87929faca49a8e8174685d5245392c2013080000000006111b242d34393d3e46464646464646464646464646464646464646464646464646464646464646464646464642413d3730271e140900000000000000000000000000000000000000000000040607101313131313130f0f0d09040000000003060809121313131313130c0b0906010000000000000000000713202d3a4653606d7884919ea8b2a99f92867b6e655b50483e342e261e1b1312100c060d060b0f12131a1f252a343d46505a606d7984919ea8b0a69c8f83766a5f5347392e23180c00000000000714212d3a4754606d7a85929fa7b0a69e92857b6e696059524d47464141404040414045464b51555d606d727f8b939ea9afa3998f82766a605447392f24180c00000013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4847433c342a20150a000000000713202d3946525d686f7c869298a0a7a099938f8a868482818080808081828486898d92989da59f9892867c6f685d52453a3024190d0100000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0acaca194877b6e6154483b2e2115080000000000000000000000000000000000000000000000070c13191d20262b2e2f3234363839393938373634312e2d2a25201d18120c0400000000000000000000000000000000000000000000000002090e13191e20252a2d2e30333537383839393938373634322f2d2b27221b1b16100b04000000000000000000000000000a1723303d4a5663707d8996a3b0a6998c7f7366594c402f2924292c2f353b434b545d68707d8a959fabb7afa396897c706356493d3023201c1610080000000013202c3946535f6c7986929facada093867a6d6053473f3f3f3f3f3f3f3f3f3f3f3f40414145474e545b666d7a85929fabb3a99c908376675d5145392c201306000007121d2730394045464747474747474747474747474747505a6264686868686865625b5147474747474747474747474747474645403930271d1207000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a3939393939393939393939393938373533312d2c29241f1c18120c060000000000000000000000000000091623303c4956636f7c8996aab4a79a8e817467574d42342d2a282b2d313a434d57606d7985929eabb8aca09386796d6053463a2d20130700000916222f3c4854606b70737577797b7d7d7063594f42382e26222122262b333f49535f6974818e9aa6ac9f92867a6d6054473a2f24190d010000000c17222d363e45494b5353535353535353535353535353535353535353535353535353535353535353535353534f4d49423930261b10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111e2a36414c5664707d8a96a1adada1978c7f72695e53493f3628231c140c0a060300000000000306090e1419222b343e45515d67717e8a96a0acab9f94887c6f62544b4034281c100400000006131f2b37434e5866727f8c97a2adaa9e948a7d70695f574f46423b3935303433342e34383a40454b515b626d74818e97a1adab9e94897c6f62554b4035291d1004000013202c3946535f6c7986929facada093867a6d6053474040404040404040404040404040404040404040404040404040404040404040403c3a37312a22180e0400000005121e2a36424d57616d7a859298a3a69f959087827d7a77767474737373747577797d80868e929ba3a29891847a6d60564c4135291d110400000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87949f9f9f9f94877b6e6154483b2e211508000000000000000000000000000000000000000000030b12181e24292c31373a3b3e414345454646454443413e3b3a36312c29241d160d0802000000000000000000000000000000000000000000070c141a1e252a2d3036393b3d4042444445464646454443413f3c3937332d2b27201b160d070100000000000000000000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f2e23181c1f24293139424c56616c7683909da9b3afa396897c706356493d302316100b05000000000013202c3946535f6c7986929facada093867a6d6053473a3232323232323232323233332f35393c424a545e68737f8c99a9b2ac9f9286796d6053473a2d2014070000000b151e272e34383a3b3b3b3b3b3b3b3b3b3b3b3b3b4956626c717575757575726d62564a3b3b3b3b3b3b3b3b3b3b3b3b3b3a38342e271e150b00000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053474646464646464646464646464645454442403d3a39352f2c28231d17110a030000000000000000000000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f31261e1c1f2028313b45515c6673808d99aab4aca09386796d6053463a2d20130700000714202c38444f5960636669666d6f71706b6054473d30262c2c2c2b2a222d38414d57626e7b88949faba3988b7e7265554c4135291d1104000005111d29343e485056586060606060606060606060606060606060606060606060606060606060606060606060605c5a544c42372c21150900000000000002070a0c0d131313131313120908060300000000060b0e10111313131313130f07060300000000000000000000000000000000000000000000000714202d3946525e6876828f9ca8b2ab9e9185796d60574d41382d2417110a02000000000000000000000002091019222935404b55606c7884919dabb0a69a8e8174665c5145382c1f13060000000815222e3b4754606a7884919ea9b1a79c8f82756c61574d453d36302d292427272723282c2e343a4145515b606d7a85929eaab0a69b8e8275675d5145392c1f1306000013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343434342f2e2b2620181006000000000714212d3a46535f6974808d97a1a99f948f837c75706d686967676666676768666d70747a818b919ba5a1968d8074685d5245392c20130700000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87939393939393877b6e6154483b2e2115080000000000000000000000000000000000000000060c151d23282f35393c4247484b4e50515253535251504d4b4846423b39352f281f19130c04000000000000000000000000000000000000030b12181f252a3036393b4146474a4c4f50515253535252514f4e4b4846443f3837322c272118130c04000000000000000000000a1723303d4a5663707d8996abb5a6998d807366544a403428211e1a181f27303a44505a64707d8a97a2adafa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a2d252525252525252525262724292c2f38424c56626f7b8896a1adaea399897c6f6256493c2f231609000000030c151d23282c2d2e2e2e2e2e2e2e2e2e2e2e313e4b5864717e82828282827f7265584c3f322e2e2e2e2e2e2e2e2e2e2e2d2c28231d150c0300000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d605353535353535353535353535353535252514f4d4a4745413a38342e28231c150c0700000000000000000000000b1824313e4b5764717e8a97a4b0a4978a7d7164574a3e3124171012161f2834404b54626f7c8998a3aeaca09386796d6053463a2d201307000004101c27333d474f54565a545c6062646360594f44353638393939383734312f3c47535f6a76838f9ca9aa9c908376675d5145392c20130600000815212d3945505a62646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c69655e54493d3125190d0000000000070d1316191a2020202020201f1515120f0a04040b11171a1d1e2020202020201c1312100b060000000000000000000000000000000000000000000814212e3b4754616e7a87939facafa3998c7f72675d51453b2f261b1206000000000000000000000000000000071018242f3944505b66727e8b99a3aeac9f9285796d6053463a2d2013080000000916222f3c4955626f7c8896a1acaca095897c6f625a50453b332a25201d191a1a1a181c1f23282f353f45515d67727f8b98a2aeac9f9286796d6053473a2d201406000013202c3946535f6c7986929facada093867a6d6053473a2d2727272727272727272727272727272727272727272727272727272727272722211f1b150e0600000000000815222e3b4855616e7b86929fa9a1978f82796e6a64615d565b5a5a595a5a545c6063686d747f8b939ea89f92867a6d6054473a2d21140700000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a86868686868686867b6e6154483b2e211508000000000000000000000000000000000000000810181e272e343a4145474d5355585b5d5e5f5f5f5e5e5d5a5754534d474540393129251e160e0500000000000000000000000000000000050c151c232830363a4146474d525457595c5d5e5f5f605f5f5e5c5a585553504947433d383229241d160d060000000000000000000915222f3c4855626f7b8899a3afa89b8f8275665c51443a322d2b2627272628323e4653606d7985929fabafa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201919191919191919191a191d20262f3a47535f6a7885919eabb5ab978b7e7164584b3e3125180b00000000030b12181c1f20212121212121212121212734404d5a6773808d8f8f8f8e8174685b4e41352821212121212121212121201f1c18120b030000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d606060606060606060606060606060605f5e5d5b595754514c46454039342e261e191009000000000000000000000b1825313e4b5864717e8b97a4b0a396897d7063564a3d3023170a060d18232e3a4653606d7986929facaca09386796d6053463a2d2013070000000b16212b353d44484a4d4b5153555756544f473e4143454646464543413e3a39424e5765727e8b98a7ac9f92867a6d6054473a2d21140600000a1724303d4956626c717979797979797979797979797979797979797979797979797979797979797979797979797570655a4d4135281b0f000000010a12191e2325262d2d2d2d2d2d2c22211f1b150e0e161d22272a2a2d2d2d2d2d2d29201f1c17110a02000000000000000000000000000000000000030f1b27333f495364717e8b9aa4afac9f92867a6e61554b4033291d140a000000000000000000000000000000000007121d28333f4a54616d7a86929facaea298897d706356493d2f24190d0100000d1a2633404d596673808c99a8b2aa9d9083776a6054483e332a211a14110d080d070c1013181d242935414c55606d7985929fabaea2988a7d7164574a3e2e23170b000013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1515120f0a04000000000004101c2934404b556673808c99a2a99e91857a6d675f5854524c4e4d4d4d4d4e4b5153565d606d75818e9ba9a2988b7e7164584b3e3125180b00000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000713202d3946525e6876797979797979797976695e52463a2d20140700000000000000000000000000000000000009121a222a303940454c5254575f626567696b6c6c6c6b6a696764615e5753514b433e35302820170e050000000000000000000000000000050e171e272e343b42464c5254565e616366686a6b6b6c6c6c6b6a69676562605b53544e48443d352f281f180f0600000000000000000714202d3a4753606d7a86929facab9e9285796d60564c443d3a373134333332323845515c6675828f9ca8afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140c0c0c0c0c0c0c0c080d11141d2b37434e58697683909ca9b2a5988c7f7265594c3f3226190c000000000000070c1013131414141414141414141a2734404d5a6773808d9a9b9b8e8174685b4e4135281b1414141414141414141313100c0700000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a686664605d5553514b443f38302b221b120a0100000000000000000b1825323e4b5865717e8b98a4afa296897c6f6356493c302316090007131f2c3845515c667683909da9aca09386796d6053463a2d201307000000050f1a232b33383c3d40404546484a494845474a4d505152535252504e4b4746414754616e7a8795a0aca3998a7d7064574a3d2e23170b00000b1825313e4b5864717e8686868686868686868686868686868686868686868686868686868686868686868686868275695c4f4236291c0f0000000a131c242a2f3233393939393939392f2e2b2620181720272e333637393939393939352d2b28231c140c02000000000000000000000000000000000005121f2b3744505b6575818e9bacb6a99c8f8276685e5243392f21170b020000000000000000000000000000000000010b17222d3846525d6875828f9ca8b4aa9a8d807367564c4135291d11040005111e2a36424d576976838f9ca9b5ab998c7f7366584e43362c21180f0905010000000004070c1319242f3a45515d6774818e9aa7b4aa9b8e817468544a3f34281c10030013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d090806030000000000000006131f2c3845515c6777848f929797988b7f72685d554e4746414141404040414045464c525b626f7c8897a2aa9b8e8174685b4e4135281b0e02000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f0005111d2a36414c565e6c6c6c6c6c6c6c6c6c6c5e574d42362a1e1205000000000000000000000000000000000009121a242c343c434b51565d6066696e7174767878797978777674716e6965605d555046413a322920170e05000000000000000000000000050e172029303940444d52565e6165686e70737577777879797978777674726f6c65626058544f45413a312a21180f060000000000000006131f2c3945515d677783909dabada1978a7e71685e564f484742424140403f3f3f404b546673808c99a6afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000001040b1b2631424f5c6875828f9ba8b2a6998c7f7366594c403326190d000000000000000004060708080808080808080d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0808080808080808070604000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867979797979797979797979797979797979797878777573706d6764605c54504a423d342d241c130a01000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090004101c2834404b546875828f9ba8aca09386796d6053463a2d2013070000000008111a21272c2f302e34383a3c43474b5154575a5c5e5f5f5f5e5d5a5854524c48525e687784919daaab9a8d807467544a3f34281c1003000b1825313e4b5864717e8b939393939393939393939393939393939393939393939393939393939393939393938f8275695c4f4236291c0f000007121c252e353b3f40464646464646453c3a37312a22202932393f4344464646464646423a38342e261e140a00000000000000000000000000000000000613202d394653606c7885929eabb3a9988b7f7265564c4131271d0f050000000000000000000000000000000000000006111c2935414c5665727f8b98aab4aa9d918477685d5245392c201306000714202d3a46525e697885929eabafa399897c6f6256493d32231a0f060000000000000000000108131e2935404b5564707d8a97a9b3aa9d908377665c5044382b1f12060013202c3946535f6c7986929facada093867a6d6053473a2d2014070101010101010101010101010101010101010101010101010101010100000000000000000000000714202d3a4753606d79808285878a8c86796d60564c433c393530343333342e34383a4147535f6a7885929fa99d9083766a5d5043372a1d1004000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f00010d1925303a444c525f60606060606060605f524d453b30251a0e020000000000000000000000000000000007111a242c363e464e555c60686d72777b7e818384858686858483807e7b76716d67615a524c443b332920170b0200000000000000000000040d172029323b424a51575e61686d72777a7d7f82838485868685858482817e7b78746f6a636059514b433b332a21180d0400000000000004101d2935404b5566737f8c99a3aea99e91847a6d68615955534d4f4e4d4c4c4c4b4b4c5865727f8b98a5afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000001040a1b2835424e5b6875818e9ba8b2a5988b7f7265584c3f3225190c000000000000000000000000000000000000010d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facb9a2958b86868686868686868686868686868686868685858482807d7a76716d66605c544e463f372e251c1309000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000c18232e414e5b6874818e9ba7aca09386796d6053463a2d2013070000000000080f161c2022232a313a41454e53555d606467696b6c6c6c6b6a6764615d56544f566774818d9aa7a99c908376665c5044382b1f1206000b1825313e4b5864717e8b979f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9c8f8275695c4f4236291c0f00020d19242e3740474b4d535353535353524847433c342a21323b444a4f515353535353534f46443f3830261c1106000000000000000000000000000000000815222e3b4855616e7b8897a1adada197887b6e6255483b3022150b0000000000000000000000000000000000000000000d1924303c4855626f7b8898a2aeaca095877a6d6054473a2d211407000814212e3b4754616e7b8797a2adac9f92867a6d6053473a2d2014070000000000000000000000010d18242f3b4754616e7a8797a1adac9f9286796d6053463a2d2013070013202c3946535f6c7986929facada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000000000006131f2c3845515c676d7376787b7d807f73675d51443a312d29242727262723282c3037434e586a7784919daa9e9184776b5e5144382b1e1105000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000008131e28323a41465353535353535353534846423b33291f140900000000000000000000000000000000050e19232c363e4850585f676d737a7f84888b8e90919292929191908d8a87837e79716c615e564d453b32291d140a000000000000000000010c161f29323b444c545c60696e757a7f83878a8c8f90919292939292918f8d8b8885817c76706b605d554d453c332a20160c010000000000000c18242f3b4854616e7b86929fa8ada19690827a706b65615f575c5a5a5959585858585865717e8b98a4afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140a0a0a0a0a0a0a0b070d10141b2a36414c566976828f9ca9b4aa978a7e7164574b3e3124180b000000000000000000000000000000000000010d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140b0b0b0b0b0b0b0b0b0a0a0907060401000000000000000000000000000000000000000000000013202c3946535f6c7986929facb9a79d959393939393939393939393939393939399939291908e8c8a86837e79726d666058514940372e251b10070000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090000071a2734404d5a6773808d9aa6aca09386796d6053463a2d201307000000000000050b1019232b343c434c52585f62676d71747678797979787674716d686360595865717e8b98a4ac9f9285796d6053463a2d201307000b1825313e4b5864717e8b97a4a5a5a5a5a5a5a5a5a5a5a5a7a9aeacacacafa9a7a5a5a5a5a5a5a5a5a5a5a59c8f8275695c4f4236291c0f0007131e2a3540495257596060606060605f55534e463c332939444d555b5d6060606060605c53504a42382e2317130a0000000000000000000000000000000a1724303d4a5763707d8a96a9b3ab9e928578695f53473a2e2114030000000000000000000000000000000000000000000813202d394653606c7985929facb1a795897c6f6256493c2f231609000916232f3c4956626f7c8995a9b3aa9e918477675d5145382c1f13060000000000000000000000000714202d3946525e687885919eabaea398887b6e6255483b2f2215080013202c3946535f6c7986929facada093867a6d6053473a2d20140c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c07060401000000000000000000000004101c2934404b555c606769696e7073736d63554b403228201d191a1a1e21262b30363e46525e697885919eab9e9184786b5e5145382b1e1205000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f00000c17232e38424a5053555555555555555553514a42392e23180c000000000000000000000000000000020d17202b353e48505a616a6f797f868c9195989a9c9e9f9f9f9e9d9c9a9795908b857e766d685e574d443b2f261b1106000000000000000007121d28313b444d565e666d727b81868c909596999b9d9e9e9f9f9f9e9d9c9a9897918d89837d746d675f574d453c32281e13080000000000000714202d3a46525e6974808d96a1a9a89f9590847d77726e696a6867666665656565646465717e8b98a4afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2016161616161616171718181d20262d3946525e687784909daaaea298897c6f6356493c30231609000000000000000000000000000000000000010d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20181818181818181818171716151413110d080705020000000000000000000000000000000000000013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa49f9f9e9d9b9999928f8b857f786f6a625b514940372d22190c0300000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000050e19222b353d464e565d606a6f747a7d8083848586858583817e7a76706b625f626f7c8995aaaea298887b6e6255483b2f221508000b1825313e4b5864717e8b979898989898989898989898989a9da4aebaafa59d9a9898989898989898989898988f8275695c4f4236291c0f000a16232f3b47525b63666c6c6c6c6c6c6c625f584e453b323f4a555f676a6c6c6c6c6c6c68605c544a3f3428251c120900000000000000000000000000000c1926323f4c5965727f8c98a5b2a99c8f837669574d42372b1e120600000000000000000000000000000000000000000006121f2b3844505b667783909daab1a4978b7e7164584b3e3125180b000a1723303d4a5663707d8996a3b0a99c90837669554b4035291d100400000000000000000000000005111e2a36414c566a7683909da9b4aa96897c6f6356493c302316090013202c3946535f6c7986929facada093867a6d6053473a2d2019191919191919191919191919191919191919191919191919191413110d0701000000000000000000000c18232f39434b51535a575e61646666635b5143392f20191d2021262b2e31373a41464f59616e7b8796a1aa9d9083776a5d5044372a1d1104000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f0003101c28343f4a545c606262626262626262605c544a4034281c1004000000000000000000000000000008141e29323d47505a616c717c848c92989da0a7a7a7a4a3a2a1a2a4a6a7a79f9d97918a827a6e695e564c41382d22170b01000000000000010d18242f39434d565e686e787f868e92999da0a7a6a8a7a5a4a3a3a4a5a7a9a7a9a19e9a94908981796e695f574d443a2f24190d04000000000005121e2a36424d57606d79849197a1a9a79f969189837f7b78767574737372727271717171717e8b98a4afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a2d232323232323232324242524292c2f38404b55616e7a86939facac9f9285796d6053463a2d201307000000000000000004060708080808080808080d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0808080808080808070604000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d242424242424242424242424232221201d191514120e0903000000000000000000000000000000000013202c3946535f6c7986929facb9b3a9a19e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9fa2aaa2a5a8aba39f9c97928c837c726d635b51493f342b1e150b00000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000020c17202b343d474f585f686d747c81868a8d8f9192929291908d8b86827d766f6a616d7a8798a2aeaa968a7d7063574a3d3024170a000b1825313e4b5864717e8b8b8b8b8b8b8b8b8b8b8b8b8b8b8d929da9b5a99d938e8b8b8b8b8b8b8b8b8b8b8b8b8b8275695c4f4236291c0f000c1925323f4b57636d73797979797979786f6a5f574d443a434f5b677177797979797979756d665c504440372d241b1108000000000000000000000000000e1b2834414e5b6774818e9aa7b3a79a8d8074675a4d4131261a0e02000000000000000000000000000000000000000000030f1c28333f4a546875818e9ba8b3a6998d8073665a4d4033271a0d000b1724313e4a5764717d8a97a4b0a89b8f8275685c4f422f24180c00000000000000000000000000010d192530424f5c6875828f9ba8b0a3968a7d7063574a3d3024170a0013202c3946535f6c7986929facada093867a6d6053473a2d26262626262626262626262626262626262626262626262626262621201d18130c0400000000000000000007121d2731394045474d4d535457595957514940312720252a2d2e31373a3c42464c5259616b73808d99a9aa9b8e8175685b4f4235281c0f02000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f0006121f2c3844505c666d6f6f6f6f6f6f6f6f6d665c5144382c1f120600000000000000000000000000020b1925303b444f59616c717e8691969fa2aaa9a19e9b9796959595979a9ea1a8a9a19e948f837b6e685e53493f33271e130800000000000004101d2935404b555e696e7a838c92989fa3ababa39f9d9a9897969697989a9d9fa3ababa69f9c938e847b6e695f564c41352921160a0000000000020e1a25303b45515d676f7c8591979ea5a8a09e95908b8885838281807f7f7f7e7e7e7e7d7d808d9aa7afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473a3030303030303030303031312f35393c4149515d67727e8b99a4afa79c8f8275665c5145382c1f1306000000000000070c1013131414141414141414141a2734404d5a6773808d9aa69b8e8174685b4e4135281b1414141414141414141313100c0700000000000013202c3946535f6c7986929facada093867a6d6053473a31313131313131313131313131302f2d2c292422211e1a14100b0600000000000000000000000000000013202c3946535f6c7986929facb9ada1979292929292929292929292929292929292989495989b9fa3aaa9a19e9591877f736d635b51463c30271d1207000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000008131e29323d464f59606a6f7a81878e92989a9c9e9f9f9f9e9d9a99928f89837c726d687885929faba5988b7f7265584c3f3225190c000815222f3b4855626e7c7f7f7f7f7f7f7f7f7f7f7f7f7f7f808d9aa7b4a79a8e807f7f7f7f7f7f7f7f7f7f7f7f7f7d7063574a3d3024170a000d1a2633404d59667380868686868686857c6f695e564c4344515d6a778386868686868682786d605c52493f362d231a1107000000000000000000000000101c2936434f5c6976828f9ca9b2a5998c7f7266594c3f3326190900000000000000000000000000000000000000000000000b17222d404d5a6773808d9aa6b3a89b8e8175685b4f4235281c0f000b1825313e4b5864717e8b97a4b1a89b8e8275685b4f4235281c070000000000000000000000000000081b2835414e5b6874818e9ba7b0a4978a7d7164574a3e3124170b0013202c3946535f6c7986929facada093867a6d6053473a333333333333333333333333333333333333333333333333333333332d2c29241d160d040000000000000000010b151f272f34383a404246484a4d4c4b464037292c2d3036393a3e4247484d53565e616b707d87929faca2988b7e7265584b3f3225180c00000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000713202d3a4653606d787c7c7c7c7c7c7c7c786d6053463a2d201307000000000000000000000000000a141d2a36414c56606b717e879298a0a8a8a19e97928e8b898888898a8d91969ea1a8a69f9591847a6e655b50443a2f24190d0000000000050f1a232c3945515d676e7b8490959fa2aaa9a19e9992908d8b8a89898a8b8d9092999ea1a9aba59e9691847b6e685d52453d32271b0f03000000000009141f2935414b555f6a6f7c858f939c9fa4a79f9d989892908f8d8d8c8c8b8b8b8b8a8a8a8d929da9afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6053473d3d3d3d3d3d3d3d3d3d3d3e3e3f4045474e535b606d7984919eababa0958a7d7164544b4034281c100400000000030b12181c1f20212121212121212121212734404d5a6773808d9aa69b8e8174685b4e41352821212121212121212121201f1c18120b030000000013202c3946535f6c7986929facada093867a6d6053473e3e3e3e3e3e3e3e3e3e3e3e3e3d3d3c3a39352f2e2d2a261f1c17110a020000000000000000000000000013202c3946535f6c7986929facb8ab9e9285858585858585858585858585858585858687898b8e92989fa2aaa7a099928b7f736d62584e43392e23180c000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000010d1925303a444e58606b707c848e939a9fa2aaa9a8a4aba39fa3aba39f9c9490877f746d7784919daaa69a8d8073675a4d4034271a0d000814212e3a47535f6a6e72727272727272727272727272727d8a96a3b0a3978a7d72727272727272727272727272706b6155483c2f231609000a1623303d495663707d87929a93939791847b6e685e554b424d5a6774808d93939393938e81746e635b51483f352c231910060000000000000000000000101d2a3643505d697683909ca9b1a4978a7e7164574b3e3124180b0000000000000000000000000000000000000000000000061926323f4c5965727f8c98a5b2a89c8f8275695c4f4236291c0f000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2834414e5b6774818e9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3a39352f281f160c010000000000000000030d151d23292c2d31363a3b3d40403e3b352f35393a3d4146474a4d5355575f61686d747d869299a3a79f92867a6d6154473a2e21140700000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87888888888888877b6e6154483b2e21150800000000000000000000000006111b262f3846525e68707d879299a3aaa49d96918a85817e7d7b7b7c7d80848a91969fa7a7a0968f82776c60564c4135291c1106000000000b16212c38444f59606d798390969fa7aea59d97918c8683817e7d7d7d7d7e8083868c91979ea5ada8a09691847a6d60594f43382c1f14090000000000020d18242f3a434e585f6a6f7a82898f93999c9fa2aaa29f9d9b9a999998989898979797979a9da4aeafa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d605349494949494949494949494a4a4b4c4b5153585f656c74808d96a1aca4999083786c605346392e23180c00000000030c151d23282c2d2e2e2e2e2e2e2e2e2e2e2e34404d5a6773808d9aa69b8e8174685b4e41352e2e2e2e2e2e2e2e2e2e2e2d2c28231d150c0300000013202c3946535f6c7986929facada093867a6d60534b4b4b4b4b4b4b4b4b4b4b4b4b4a4a49484745413f3b3a36312b28231c140c0701000000000000000000000013202c3946535f6c7986929facada093867978787878787878787878787878787878797a7c7f82868c92989fa7aba39f918b7f726a60554b4034281d12070000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000005111d2a36414c56606a707d8691969fa4acaaa29f9b979599929994979a9e9f99928c81787683909ca9a79b8e8174685b4e4135281b0e0006121e2b37424e575f6265656565656565656565656565707d8a96a3b0a3978a7d706565656565656565656565656361594f44382c201407000916222f3b4854606b717e88939fa4a19691847a6d675d544a4653606c78818e949fa69d938d80736d635a50473e352b22180f0600000000000000000000111e2a3744515d6a7783909daab0a3968a7d7063574a3d3024170a00000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4b1a99c908376695d5043362a1d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4745413a31281d1307000000000000000000030b12181c1f20252a2d2e3133332f34383a4045474a4c525457575f6265696e737a81889298a2a8a0958d8073685d5246392d20130700000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87949595959594877b6e6154483b2e2115080000000000000000000000000b17222d38414f59616e7a859299a3aba49c928d847e787471706f6e6f7173787d8490959fa8a89f948c7f72685d5245382d22170b00000004101c27333c4854606b74818e95a0a8ada39c938e857f7b777472717070717274777a7f858e939ca4ada9a0968e81746b6054483b31251a0e02000000000007131d28313c464e585f686d757c82878b8f929897999a9b9c9d9d9d9e9e9e9e9f9f9f9fa3abacb5afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d6056565656565656565656565657575859555d60646a6f77808d929da8a59f93877d70655b5044372b1d1207000000000b151e272e34383a3b3b3b3b3b3b3b3b3b3b3b3b404d5a6773808d9aa69b8e8174685b4e413b3b3b3b3b3b3b3b3b3b3b3b3a38342e271e150b00000013202c3946535f6c7986929facada093867a6d6057575757575757575757575757575757565554514c4c4846423b38342e261e18120b030000000000000000000013202c3946535f6c7986929facada093867a6d6b6b6b6b6b6b6b6b6b6b6b6b6b6b666d6d6f72757a808590959fa6aea49f92877c6f675c5145392e23180c0000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000040f19232d3946525e686f7c869298a1a8aba39f98928e8a88878686888a8e92979f9f938d8075828f9ba8a89c8f8275695c4f4236291c0f00020e1a26313c454e535558585858585858585858585863707d8a96a3b0a3978a7d7064585858585858585858585857554f473e33281c1004000713202c38444f59616c727f8b929ca5a0969083796d665c5349505b666d78828f959fa59c928c7f726c625a50473d342a21180e05000000000000000000111e2b3844515e6b7784919eaaafa396897c706356493d3023160a00000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1aa9d9083776a5d5044372a1d11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d605959595959595959595959595959595959595959595959595959595959595954514b433a2f24180d0100000000000000000001070c1013141a1e2124293036394045474b515357565e616467696e72767b80858d939aa2a79f969183796d60564c4135291d110500000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0a2a2a194877b6e6154483b2e2115080000000000000000000000030f1b27333f4953616b75828f97a1aba49c918c8079716c66646362626264666c707a839096a0aca69f92857a6d60544a3f33281c0f0300000714202c38444f5963707d89939ea7aea49c918c817a726e686765646363646567686e737a818c919ca5afa89e93897c6f63574d42362a1e12050000000000010c161f2a343c464e565e616b6f757b7f8285888a8c8d8f8f9090919191919292929292999ba3acafa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867a6d636363636363636363636363636364646668676d71757c828d929da4a49f938c7f726b6053493f33271b0b0000000007121d273039404546474747474747474747474747474d5a6773808d9aa69b8e8174685b4e474747474747474747474747474645403930271d1207000013202c3946535f6c7986929facada093867a6d64646464646464646464646464646464646362605d555855534d46443f383029231d150d0500000000000000000013202c3946535f6c7986929facada093867a6d605f5f5f5f5f5f5f5f5f5f5f5f5f5c60616265686d737b838f949fa7afa3999183796d60544b4034281c100400000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000a16212c38444f59616d7a849198a2aaaaa299928d85817d7b7a79797b7d81858b92979d928a7e818e9ba7a99d9083766a5d5043372a1d1000000915202a333c4247484c4c4c4c4c4c4c4c4c4c4c5763707d8a96a3b0a3978a7d7064574c4c4c4c4c4c4c4c4c4c4a48443e352c21160b000004101c27323d47505a626d73808c929da59f958f82786d655b504a545c666d79839096a0a49c918b7e716c61594f463c332a20170d040000000000000000121f2b3845525e6b7885919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0aa9e9184776b5e5144382b1e11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6666666666666666666666666666666666666666666666666666666666666666605d554b4135291d1104000000000000000000000000040610181f272f353b41464b5153555d606467686d7174777b7f83888d92989fa4a39f9590847b6e675d51443a3024190d0100000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0adaea194877b6e6154483b2e211508000000000000000000000005121f2b3744505b65707d8a939ea9a79d928c7f746d67605b5456555556545b60686d7984919da6aea2988c7f72665b5044382b1f120600000916222f3c4854606b7783909da5afa89d928c7f746d68615e56585756565758565e61686d747f8c939da9afa59c8f8276695e53463a2d211407000000000000040d18222a343c444c52596063696e7276797b7d7f81828383848484848585858585868b909ba7afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facada093867970707070707070707070707070707071717274767a7d82878f949da4a099938c80746d63594f41382d22170b000000000c18232e39424b515354545454545454545454545454545a6773808d9aa69b8e8174685b545454545454545454545454545453514b43392e23180c000013202c3946535f6c7986929facada0938679717171717171717171717171717171717170706f6d676865615f5753504a423d342f271f170e05000000000000000013202c3946535f6c7986929facada093867a6d605352525252525252525252524a50535456565e61696e78828f95a0acaba0958b7f72665c5145382c1f130600000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000030f1b27323c4855606b75818e96a1aaaaa2989287807a75716e6d676d6e7074797f858f949e9185818e9ba8aa9d9084776a5d5144372a1e110000030e18212a31373a3b3f3f3f3f3f3f3f3f3f3f4a5763707d8a96a3b0a3978a7d7064574a3f3f3f3f3f3f3f3f3f3d3c38332c231a10050000000b16212b353e48515b636e74808e939ea69f948e81776c605b514b545d676d7a849196a1a39f92877e706b60584e453b322920160d0300000000000000121f2b3845525e6b7884919eabafa296897c6f6356493c3023160900000000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0aa9d9184776a5e5144372b1e11000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada09386797272727272727272727272727272727272727272727272727272727272727272726d675d5145392c201306000000000000000000000000071019222a313940454d52555c6064676d7074777a7d8184888c90959a9fa2a39f98928c837b6e695e554b4032281e13080000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0adaea194877b6e6154483b2e21150800000000000000000000000613202d394653606c7883909da6aca0958d80736d605c55504a4a4848494a50565d676f7d89949facaa9e9185786c605346392d2013060004101c2834404b5463707d8995a0acaca0968d80736d605d56524d4b4a4a4a4a4b4c52565d606d74818e97a2adab9f94877b6e6154483b2e211507000000000000050e171e252a323a41464f54575e6165666d6f717374757676777777787878787879797e8b98a4afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facb0a396897d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d7d7e7f8183868a8e93999f9f9d9590877f746e645b51473d2f261b110600000004101c2834404b545c606161616161616161616161616161616773808d9aa69b8e817468616161616161616161616161616161605c554b4034281c10040013202c3946535f6c7986929facb1a4978b7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7d7d7c7b7a7875726e6964605c544f454039312920170e050000000000000013202c3946535f6c7986929facada093867a6d605347454545454545454545453f444647494c52575f666d7a83919da6b0a79e9184796d6053463a2d20130900000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000007131f2c38444f5963707d89939ea8aea29892867d746d686462605d606164676d727a828e93979185929facaa9e9184776b5e5144382b1e11000000060f1820262b2e2f3232323232323232323d4a5763707d8a96a3b0a3978a7d7064574a3d3232323232323232302f2c28211a110800000000050f19232c363f49525c606c78818f949fa69e938d80746d635a504b555e686e7b849197a2a39992867d706a5f574d443b32281f150c03000000000000111e2b3844515e6b7784919eaab0a396897d7063564a3d3023170a00000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a99d9083766a5d5043372a1d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb2a6998c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6054473a2d2114070000000000000000000000061019232b343c434b51565e61676d71757a7d8084868a8d9196989d9fa7aba399928e867f796e695e574d43392f20160c020000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0acaca194877b6e6154483b2e2115080000000000000000000005111e2a36424d5763707d8a95a0aca69d9083786d605b514b443f3d3c3b3c3f444c55606b7683909c9f9e9d97897c6f6256493c2f2316090006131f2c3845515c6675818e9ba7b1a99e9184796d605b524c46413f3e3d3d3e3f41464c525b606d7a85929fabb0a6988c7f7265594c3f2f24180d0100000000020c1720293036393a3e3f44484d5354545c606264666768696a6a6a6b6b6b6b6c6c6c717e8b98a4afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facb9a5998f8989898989898989898989898989898a8a8b8c8e9092989b9e9c9995908a837d726d645c53493f352b1d140a0000000006131f2c3845515c666d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e73808d9aa69b8e81746e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d675c5145382c1f13060013202c3946535f6c7986929facb9a69a908b8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a89888784827f7b76716d666059514b433a322920160c0300000000000013202c3946535f6c7986929facada093867a6d6053473a38383838383838382e34383a3a3c41464d545d686f7c89949eaaada1968a7d7064574a3d31251a0e02000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000915222f3b4854606b7683909da5afa69f92867d706b605d565554515355555d60686d78818e94989298a2aeab9e9184786b5e5145382b1e1200000000060e151a1e21222525252525252525303d4a5763707d8a96a3b0a3978a7d7064574a3d31252525252525252423201c16100800000000000007111a242d374044505b666d79828f95a0a59d928c7f726c625a504c565e696e7c859298a2a39892867c6f695f564d443a31271e150b020000000000111e2a3744515d6a7784909daab0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000c1825323f4b5865727e8b98a5b1a99c8f8276695c504336291d10000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a89c918c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877b6e6154483b2e21150800000000000000000000030c18222b353d464e555d60686e73797e82868a8d90939a9a9ea0a8a9abb1ac9f9287817b736d665e574d453b31271d0e04000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87949f9f9f9f94877b6e6154483b2e211508000000000000000000000714202d3a46525e6976828f9ca7ab9f94897d70665c50454039332d2f2f2d333a434f5964717e8b989291908f8c7f7366594c403326190d000713202d3a4653606d7985929facada1978a7e71675d5145413a36303130303130363a4145525d68737f8c99a9b3a89c8f827569554b4035291d10040000000008131e29323a4146474b4c4d4e4f51524a50535557595a5c5c5d5d5e5e5e5e5f5f5f65717e8b98a4afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facb9aba199969696969696969696969696969696969797999b9d9f9e96918f8c88837e78706b625b534a41372e23190b02000000000713202d3a4653606d797a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a808d9aa79b8e817a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a796d6053463a2d2013070013202c3946535f6c7986929facb9aca29a97979797979797979797979797979797979797969596918f8b88837e78706b605c554c443a32281e150a00000000000013202c3946535f6c7986929facada093867a6d6053473a2d2c2c2c2c2c2c2c23282b2d2e30363b424c56606b75828f9cabb2a89b8e817568574d42362a1e1205000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700030f1c28333f4a54636f7c89959fabab9f948b7e716a6059524c48474546484b51565e666d788290989fa2aab4ab9e9185786b5e5245382b1f12000000000003090e1214151919191919191924303d4a5763707d8a96a3b0a3978a7d7064574a3d3124191919191919171614100b05000000000000000008121b2528333f4a545c676d79839096a0a49c918b7e716c61594f4d575f6a6f7d869299a3a29891857b6e685e564c433930261d140a0000000000101d2a3643505d697683909ca9b1a5988b7e7265584b3f3225180700000000000000000000000000000000000000000000000d1a2633404d596673808c99a6b3a89b8f8275685c4f4235291c0f000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9ada39c999999999999999999999999999999999999999999999999999999999999999994877b6e6154483b2e211508000000000000000000000b151e2a343d474f585f676d737b80858a8f92989a9d9fa4a39f9fa4aba4a7a79a8d807b756f6a605c544a42382e23170c03000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87939393939393877b6e6154483b2e211508000000000000000205070814212e3b4754616e7b87939facaa9c9083766b60544a3f342f282222222228313d4855616e7b878685848483817f7265584b3f3225180c00091623303c4956636f7c8998a2a5a69e9285796d60554b40352f2a2524232324252a2f35414c56626f7c8897a1adab9e918578675d5145392c201306000000010d1925303a444c525457595a5b5c5d5e5b5953484a4c4e4f5050515151515252525965727f8c98a5afa396897c706356493d3023160a0000000000000013202c3946535f6c7986929facb9b3aba5a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a4a4a5a7a99e948f84827f7b76716c656059514941382f251c110700000000000a1723303d4a5663707d87878787878787878787878787878787878d929da99e938e87878787878787878787878787878787877e7164574a3e3124170b0013202c3946535f6c7986929facb9b4aca6a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a3a3a8a19e9b9894908a847d746d675e564c443a30261c1106000000000013202c3946535f6c7986929facada093867a6d6053473a2d201f1f1f1f1f1f171c1f2021252a303a434f5964707d8a99a3afab9e928578695e53463a2d211407000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070006121f2b3844505b6674818e9ba7b1a79c8f82766c62584f45413b3a393a3b40454c545c666e7b86929facb4b7ab9e9184786b5e5145382b1e1200000000000000020608080c0c0c0c0c0c1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170c0c0c0c0c0a0907040000000000000000000000091317222d38424b555d676d7a849197a1a39f92877e706b60584e4e58606a707d87929aa4a19791847a6e685d554b42382f261b1106000000000f1c2835424f5b6875818e9ba8b3a6998c807366594d402f23180c00000000000000000000000000000000000000000000010e1b2834414e5b6774818e9aa7b4a79a8e8174675b4e4134281b0e000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9b5ada8a6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a194877b6e6154483b2e21150800000000000000000007121c27303c464f59606a6f7980868d92979c9fa3a8a09e9a9992939995989b9f9d928d87827c736d665c544a3f34281e150a000000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a86868686868686867b6e6154483b2e211508000000000002080e1114141d2935404b5565727f8c99a4aea2988a7e7164594f42382e231d17191917212d3a46535f69767b7a7978777675726d62564a3d3124180b000c1926333f4c5966727f8c969798999a8d8174665c5143392f241e1917171717191e24303a4653606c7985929eabada197867a6d6053473a2d20140700000005111d2a36414c565e6164656768696a6b68655d534840414243434444444545454d596673808c99a6afa295897c6f6256493c2f2316090000000000000013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9fa0a1a2a4a6aaa89c8f827e7a736e6964605b534f473f372f261d130a0000000000000a1723303d4a5663707d89949494949494949494949494949494949a9da4aea59e9b949494949494949494949494949494948a7d7164574a3e3124170b0013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa0a0a1a2a5a8aba8a69f9c95918981796d685e564c42382e23170c030000000013202c3946535f6c7986929facada093867a6d6053473a2d201412121212060b10121314191e28313d4754606d7a86929facada297877b6e6154483b2e211508000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000613202d394653606c7985929eabaca095897c6f635a50463d35302d2c2d2f353a424a545e6973808d9aa4afb7aa9e9184776b5e5144382b1e11000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000000006111c262f39434c555e686e7b859197a2a39992867d6f6a5f574d4e58616b717e88939fa4a09690837a6d675d544a41382d22170b060000000d1a2734404d5a6773808d9aa6b3a89b8e817568554b4034291c100400000000000000000000000000000000000000000005121e2a36424d576976838f9ca9b2a5988c7f7265594c3f3226190c000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f94877b6e6154483b2e2115080000000000000000000c18232e39424e58606b6f7c848c92989fa2a7a09d9996918d8a868687888b8e92989f9a948f8780786d665c50443e30261c11060000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000713202d3946525e6876797979797979797976695e52463a2d20140700000000050d14191e2021252c3845515d6776838f9cabac9f9285796d6053463d3026252525252525252a36424d575f696e6d676b6a696865625b51463a2e221509000e1b2835414e5b68748188898a8b8d8e8b7e7164544b4031271d130e080a0a080e131f2b3744505b657683909da9b3a994887b6e6155483b2e2215080000000713202d3946525e686d71727374767778756f65594d3d323536373737383835404b556774818e9aa7b2a995887b6e6255483b2f2215080000000000000013202c3946535f6c7986929facb9a79d95939393939393939393939393939393949597999d9f9e948f8a85807b726d605c544a42392e2318140b010000000000000a1723303d4a5663707d8996a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a7a9aeb6afaaa8a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1978a7d7164574a3e3124170b0013202c3946535f6c7986929facb9a79d959393939393939393939393939393939393949496989b9fa2a9aba7a09d938e837a6d685e544a3f342820150a0000000013202c3946535f6c7986929facada093867a6d6053473a2d2014070505050000030607080c16202c3945515d677783909daab3a9968a7d7063574a3d3024170a000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000916232f3c4956626f7c8997a2adaa9d9083776b6054483f34292421202024293039424d57616e7b87939facb7aa9d9184776a5e5144372b1e11000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000000000000000a141d27303a434c565f696f7c859298a3a39892857c6f695e564c4f59616c727f8b929ca5a0959082796d665c53493f332722170c0000000c1925323f4c5865727f8b98abb5aa9d908477675c5145382c1f13060000000000000000000000000000000000000000000714212d3a46535f697885929fabb4aa968a7d7063574a3d3024170a000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a79d95939393939393939393939393939393939393939393939393939393939393939393877b6e6154483b2e211508000000000000000004101c2834404a545f6a6f7d8691969fa2a69e9c95908c8884807d7a797a7c7e81858c92989e99938c81786d605a5042382e23170c0000000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f0005111d2a36414c565e6c6c6c6c6c6c6c6c6c6c5e574d42362a1e1205000000050e171f252a2d2e32323a4753606d7986929faca89b8e8275675c51453832323232323232323230313b454d575e61605d555d5c5b585651493f34291d1206000714212d3a4754606d7a7b7c7d7f8081827b6e6155483b2e22150b0100000000030f1b27333f49536975828f9ca8aea295887b6f6255483c2f2215090000000714212e3a4754616d7a7e7f8081828485817568584e43372e2c2823282c2f3945515d677783909daaada196877a6d6054473a2d2114070000000000000013202c3946535f6c7986929facb9a2958b86868686868686868686868686868787888a8d90959a9f9c98928d867e756d665c544a40342820160a000000000000000a1723303d4a5663707d89969f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa6a8aeb6afa9a79f9f9f9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b0013202c3946535f6c7986929facb9a2958b86868686868686868686868686868686868788898c8e92979da0a8aca59d9590837a6d665c50443c31261a0f0300000013202c3946535f6c7986929facada093867a6d6053473a2d20140700000000000000000004111d2935414c556975828f9ca8b1a4988b7e7165584b3e3225180b000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000c1925323f4c5865727f8b98a9b3ab998c7f7266594f43362d2219141313181e27303b46525e697683909da9b6aa9d9083776a5d5044372a1d11000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000000000020b151e28313a444d575f6a6f7d869299a3a29791847b6e685e554b505a626d73808d939da59f948f82786d655b50443e34281d11050000091623303c4956636f7c8999a4afac9f9286796d6053473a2d22170b0000000000000000000000000000000000000000000815222e3b4855616e7b8897a2adaea298887b6e6155483b2e221508000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a2958b868686868686868686868686868686868686868686868686868686868686868686867b6e6154483b2e211508000000000000000006121f2c3844515c666f7c859298a0a8a19e948f89847f7b7774706d6c6d6f7174797f869195a09f938e81746c61544a3f34281c100300000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f00010d1925303a444c525f60606060606060605f524d453b30251a0e020000020d1720293036393b3f3f3f495663707c8998a3aeaa988b7e7265554b403f3f3f3f3f3f3f3f3f3f3d3c383b454d535453514b51504f4b4a463f372d23180d01000613202c3945515d676d6e7071727374756e695f53463a2d2114030101000205080f17222d424f5b6875828e9ba8b5ab95887b6e6255483b2f2215080000000815212e3b4854616e7b878c8d8e8f909184786a6054473f3a38342e34383a404b55606d7a86929facab9e918578675d5145392c2013060000000000000013202c3946535f6c7986929facada0938679797979797979797979797979797a7a7b7e8083888d9299a19f98928b81786d665c51443d32271b0f030000000000000a1723303d4a5663707d89939393939393939393939393939393939a9da4aea59d9b939393939393939393939393939393938a7d7164574a3e3124170b0013202c3946535f6c7986929facada0938679797979797979797979797979797979797a7b7c7f81858b91969fa4aca79f959082786d60584e43372b1f140900000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000010d19242f414e5b6874818e9ba7b2a5988c7f7265594c3f3226190c000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000e1b2834414e5b6774818e9aa7afa399897c6f6356493d32231b100806070c151e2a36424d576774808d9aa7b3a99c8f8276695c4f4336291c10000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000030c161f29323b454e58606b707e87929fa3a19691847a6d675d5145515b636e74818e939ea69e948e81776c605a5045392d21150800000714202d3a4753606d7a86939facaea399897d706353493f33271b0f030000000000000000000000000000000000000004111d2935414c5565717e8b98a9b3ac9f9285786d6053463a2d201307000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867979797979797979797979797979797979797979797979797979797979797979797976695e52463a2d20140700000000000000000713202d3a4653606d78839197a2a8a097928a827c77726e6967636060616265676d727b839196a19d938a7d70665c5044382c1f120600000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000008131e28323a41465353535353535353534846423b33291f140900000008141f29323b4146474c4c4c4c5966727f8c99aaaea398887b6f62554c4c4c4c4c4c4c4c4c4c4c4c4948443d3b4246484745404443423f3d3a342d251b1106000004111d2935414c555d6062636465666869615f574d42362a1e120d0d0e090e121419212b37434e58697683909ca9aea399877a6d6154473a2e2114070000000714212d3a46535e697884919a9b9c9d96897c6f625a504a464440434044464b515c67717e8b98a3aeaa9b8f827568554b4135291d11040000000000000013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c666c6d6e6f7173777b80879196a1a29f938e81786d60584e43382b20150a0000000000000a1723303d4a5663707d86868686868686868686868686868686868d929da89d938e86868686868686868686868686868686867e7164574a3e3124170b0013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c666d6d6e6f7275797e848d939aa4afa79f948d80736a5f53473b31261a0e02000013202c3946535f6c7986929facada093867a6d6053473a2d20140700000000000000000000081b2734414e5a6774818d9aa7b2a6998c7f7366594c403326190d000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700101d293643505c6976838f9ca9ac9f92867a6d6053473a2d201407000000030c1a25303f4b5865727e8b98a5b1a89b8e8275685b4f4235281c0f000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000000000000000000040d172029333c464f59616c717e8b919ca4a0969083796d60534749525c606d78818f949fa69e938d80736c6156493d3024170a00000613202c3945515d677784909daab4ab9a8d8073655b5044372b1f140a000000000000000000000000000000000000010c13202c3945515d6775828e9ba8b5a89c8f8275665c5044382b1f1206000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5e574d42362a1e12050000000000000006131f2b37434e5865727f8c95a0a9a09691857d766f6b66625f575753535455555d60696e7a84919ea59e9184786d6053463a2d20130800000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f000006111c2630383f444649494949494949494644403930271c12070000020e1925303b444d5254585858585b6875828e9ba8ac9f9286796d605858585858585858585858585856544f473d363a3b3a39352f363532312e29231b1309000000010d19242f3a434c5154555657585a5b5c55534d453b31261a1a1a1a1b1b1a1e21252a333b4754606a7884919eabac9f9286796c605346392d20130600000005121e2a36424d576774818e9aa6a9a89b8e81756c605c5453514a504a5153555d606d7983919daaaea2988b7e7165584b3e2f24180d010000000000000013202c3946535f6c7986929facada093867a6d606060606060606060605b606061626466696e747c849196a1a59e938d80736a6054473c31261a0f0200000000000916232f3c4855616b707979797979797979797979797979797979808d9aa69b8e817979797979797979797979797979797979716c6155493c3023170a0013202c3946535f6c7986929facada093867a6d606060606060606060606060605c6061616365676d71798088939fa5afa69f92877c6f62574d42362a1e1205000013202c3946535f6c7986929facada093867a6d6053473a2d20140700000000000000000004101c2834404a546875828e9ba8b2a5988c7f7265594c3f3226190c000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700111e2b3744515e6a7784919daaab9e918578675d5145392c1f130600000000091724313e4a5764717d8a97a4b0a79a8d8174675a4e4134271b0e000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000000000000000050e17212a343d474f59626c727f8c929da89f958e8175685b4e4244505c666d79828f95a0a59d928b7e7164584b3e3125180b000004101d2935404b556773808d9aa9b3ab9e9184786c6053463c2f261b1106000000000000000000000000000000000007131d28333f4a54606d7a86929facb1a7988b7f7265544a3f34281c1003000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60606060606060606060606060606060606060606060606060606060606060605f524d453b30251a0e02000000000000000815222e3b47545f6a7784919ea7a39891847b706b63605955534d4a474647484b51575e68707d8a96a1a1968a7e7164574b3e2f24190d01000000000000000000000000000000000003101d2a3643505d697683908f8275685c4f4235291c0f00000c17232e38424a5053555555555555555553514a42392e23180c000005111e2a36414d565e6165656565656a7784909daaaa9d9083776665656565656565656565656565656360594f44382d2e2d2c292429282524221d181109010000000008131e28313a41454748494a4c4d4e4f4846423b332923272727272728252a2d30363c454e58626f7c8896a1adab9c908376655b5044372b1f1205000000020e1a25313c4855626f7c88949faaaa9e938a7e726d6662605c545d545c6062676d75808d95a0aca99f92867a6d6154473a2e211407000000000000000013202c3946535f6c7986929facada093867a6d6053535353535353534a505354545557575f616a6f7b84919ea7a59f92877c6f62584e43372b1f120600000000000714202c38444f5961636c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c73808d9aa69b8e81746c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d2114080013202c3946535f6c7986929facada093867a6d6053535353535353535353534a5153545556555d60676d747f8c939daaaea3998e8275695f53463a2d211407000013202c3946535f6c7986929facada093867a6d6053473a2d2014070606000104060708090b141f2c3844515c667683909ca9b1a4988b7e7165584b3e3225180b000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700121f2b3845525e6b7885919eabaa9d9084776a554b4035291d1004000000000b1824313e4b5764717e8a97a4b1a5998c7f7266594c3f3326190c000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000000060f18222b353e47505a636d74808d9aa7a79d9083766a5d50433f4a545c676d7a84909daaa4998c807366594d4033261a0d0000010d18242f3d495663707c8997a1adaca196897d7063584e41382d22170f06000000000000000000000000000000071118242f3844505b66717e8b98a2aeaca095887b6e6155483b2e23170b00000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60535353535353535353535353535353535353535353535353535353535353534846423b33291f140900000000000000000916222f3c4955626f7c8896a0ac9f92867c6e696159544f4847423d3a393a3c40454d56606c7884919ea89b8f827568554c4135291d1104000000000000000000000000000000000408101d2a3643505d697683908f8275685c4f4235291c0f0003101c28343f4a545c606262626262626262605c544a4034281c1004000714202d3946525e686e7272727272727985929faca89b8e8275727272727272727272727272727272706b6054483c3126201f1d181d1c181815120d06000000000000010c161f282f35393a3b3d3e3f4041423b3a36312c2f3034343434343531363a3b41464e57606a74808d9aa8aea3998c7f726653493f33271b0f03000000000915212e3b47535f6a76828f98a2aea59f92877f78726f6d666a696a666d6f7379818d929da7aca2978d8074685d5246392d201307000000000000000013202c3946535f6c7986929facada093867a6d6053474646464646463f44464747484b4d53585f69707d8a959faba3998f82766a5f53473a2e211408000000000004101c27333d474f55566060606060606060606060606060606773808d9aa69b8e817468606060606060606060606060606060575550483e33281c11040013202c3946535f6c7986929facada093867a6d6053474646464646464646464044464748494b51555d606d74818e98a2aeab9f93877b6e6155483b2f24180d010013202c3946535f6c7986929facada093867a6d6053473a2d2014131313070d10131414151a1d27303a4653606d7985929fabb2a896897c706356493d3023160a000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700121f2c3945525f6c7885929faba99c908376695d50432f24180c00000000000c1825323f4b5865727e8b98a5b5ab978a7e7164574a3e3124170b000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000000000000000000000007101a232d373f44505c666d7983909da9a59d9083766a5d5043434c565e696f7c85929faca3998c807366594d4033261a0d0000000713202d3a4653606d7985929eacb2a89c8f82756a5f53493f332721180f0802000000000000000000000003091119232935404b55606c7884919daab3a99d908477695f53463a2d1c110600000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60534746464646464646464646464646464646464646464646464646464646463b3a36302921170d0200000000000000000b1825323e4b5865717e8b98a8a79a8d81746a5f574f48443d3a37312d2d2e2f353b44505b6574818e9ba79e928578675d5145392c2013060000000000000000000000000000050c1114171d2a3643505d697683908f8275685c4f4235291c0f0006121f2c3844505c666d6f6f6f6f6f6f6f6f6d665c5144382c1f1206000814212e3b4754616e7a7f7f7f7f7f7f7f8c98a2aea99c8f827f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7d7063574e42372b1e13100c070f0c0b0906010000000000000000040d161e24292c2d2f3031323335362e2d2a32383b3d404040404141424246484c525860696f7c87929faca99f92867b6e6155483b2d22170b000000000006121f2b37434e58626f7c86929fa4aca399928b837f7b797777767777797c80858e939da4aea49a92857a6d61564c4135291d1105000000000000000013202c3946535f6c7986929facada093867a6d6053473a393939392d3338393a3b3c3e42464e57616c7683909da9ab9f94887b6e6255483b2f2215060000000000000b16212c353d44484a53535353535353535353535353535a6773808d9aa69b8e8174685b53535353535353535353535353534a49453e362c22170c000013202c3946535f6c7986929facada093867a6d6053473a393939393939392e34383a3a3b3c40454b515b616d7a86929facafa4998c7f7366554b4035291d10040013202c3946535f6c7986929facada093867a6d6053473a2d202020202020181d20202122252a2f39434d57636f7c8998a2aeaca196877b6e6154473b2e211408000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700121f2c3945525f6c7885929faba99c908376695d50432f24180d01000000000c1926333f4c5966727f8c99a5afa399887c6f6255493c2f221609000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000000000000000060f19222c363f49525c606d78828f959fa69d938c807366594d424b555e686e7b859198a2a49a92867d706356493d3023160a00000006121f2c3844505c6673808d9aa4afaa9e94887c6f655b50443d332a2219140e09060400000100000406090e141a232b353d45515d67717e8a95a0acada2978b7e7265574d42362a1e0a0000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a393939393939393939393939393939393939393939393939393939392e2d2a251f170f050000000000000000000d192633404c5966737f8c99a6a3968a7d7063584e453e38322e2b262020212429333f49536673808d99a6a197877a6d6054473a2d211407000000000000000000000000000810171c2123242a3643505d697683908f8275685c4f4235291c0f000713202d3a4653606d787c7c7c7c7c7c7c7c786d6053463a2d201307000714202d3a4753606d7a868b8b8b8b8b8c919caab4ab9f948f8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b84776a5f53473a2e2114080000020000000000000000000000000000040c13191d202122232425272829222b353d4448494d4d4d4d4e4e4f4d5354565e616a6f7b849199a3aba1978d8174695f53463a2d1b11060000000000030f1b26323c47535f6a717e8b939aa2aaa39f95918c8886848483838485898c92979ea5aaa39f93887d70685e52443a3024190d01000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d22282b2d2d2e2f31363c45505a65727f8c98a5b0a6998c7f7366594c402d22170b00000000000005101a232c33383c3d464646464646464646464646464d5a6773808d9aa69b8e8174685b4e464646464646464646464646463e3c39332c241a1005000013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d23282c2d2e2e2f35394046525e6873808d99a9b3ab9d908377675d5145392c2013060013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d24292c2d2e2f30363b424b555f6974818e9aaab4ab9e918478695e52463a2d201407000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700121f2b3845525e6b7885919eabaa9d9084776a554b4035291d1004000000030f1b27333f49536773808d9aa6ac9f92867a6d6053473a2d201407000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000000000000000000050e18212b343e48515b636e74818e949ea79e948e81746e63574b4a545d676d7a849197a1a49f93887e716b6054483b2f22160900000003101c28343f4a54616e7b87939fabb0a69c9083776c60584e453c342a251e1a1312100c070e070c1013131a1f262a353d47505a606d7984919ea7b1a99f9285796d6053473b31261a0e0000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d21201e1a140d05000000000000000000000d1a2633404d596673808c99a6a295887c6f6255493c332c27211e1d2024292d333b434e586774818d9aa7a994887b6e6155483b2e22150800000000000000000000000008121a22282d3031323643505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87888888888888877b6e6154483b2e211508000613202c3945515d6775828f98989898999ca3adbcb0a69f9c98989898989898989898989898989896887b6e6255483b3025190e02000000000000000000000000000000000001080d111314151617191a1b1c27323d474f54565a5a5a5a5a5b5c575e6164686d747c859196a0aaa39992857a6e61574d42362a1e0a000000000000000a15202b37434e58616c727f8892989fa3a7a09d99999291909090919298999ea2a9a69f98928b7f726c61564c4132281e130800000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d202020171c1f20212122262a333e4955626f7c8895a2afa99c8f82766953493f33271b0f0300000000000008111a21272c2f30393939393939393939393939404d5a6773808d9aa69b8e8174685b4e4139393939393939393939393931302d28221a120800000013202c3946535f6c7986929facada093867a6d6053473a2d202020202020181c1f20212224292f35414c56626f7c8897a2adac9f9286796d6053473a2d2014070013202c3946535f6c7986929facada093867a6d6053473a393939393939392f35393a3b3b3d42464d545c676e7b87929facb1a79a8d817467574d42362a1e1105000b1825323e4b5865717e8b98a4aca295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700111e2b3744515e6a7784919daaab9e918578675d5145392c20130600000005121f2b3744505b6576838f9ca9aa9d908477675c5145382c1f1306000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000040d17202a333d47505a626d73808c939da69f958f82786d605b5244505c666d79839096a0a59c928b7f726c61594f44382c201307000000000c17232e3846535f6975828e99a3afab9f948b7f726a60574e463e36302a25201f1c181b1a1b181c1f20262b31363f474f59616c74808d96a1adada2978d8073675d5145392a1f14090000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d2020202020202020202020202020202020202020202020202020201514120e090200000000000000000000000c1925323f4c5865727f8b98a9a396897c706356493d332b262324292c2f35383f444d56606a7683909da9a399877a6e6154473b2e211408000000000000000000000008121a242c33393c3e3f3e43505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a87949595959594877b6e6154483b2e2115080004101d2935404b5565717e8b99a49f9fa5a7adb5bbb2aaa4a19f9f9f9f9f9f9f9f9f9f9f9f9f9fa8998c7f7266564d41362a1e11050000000000000000000000000000000000000001040607080a0b0c0d13202c38444f596063676767676768686a696e71757a81879197a0a8a19892877d6f685e52453b31261a0e00000000000000040f1a26313c46505a636d727e868e92999da0a8aba39f9e9d9c9d9e9fa2aaaaa29f9b948f867e726d62594f443a3020160c0200000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2014130b0f12131414151a212e3b4754616e7a8794a1adab9e928578655b5044372b1f1205000000000000000810161c2023232d2d2d2d2d2d2d2d2d2d2d34404d5a6773808d9aa69b8e8174685b4e41352d2d2d2d2d2d2d2d2d2d2d2423211c1710080000000013202c3946535f6c7986929facada093867a6d6053473a2d2014131313130c1012131415181d25303a4653606c7985929fabafa399897c6f6256493c2f2316090013202c3946535f6c7986929facada093867a6d60534746464646464646464640454747484a4d52575e666d79829099a3afab9f95897c6f6356493c30251a0e02000b1825323e4b5865717e8b989f9f9f95897c6f6256493c2f23160900000d1a2733404d5a6673808d999f9f9f9386796d6053463a2d20130700101d293643505c6976838f9ca9ac9f92867a6d6053473a2d20140a0000000613202d394653606c7985929fabac9b8e817468554b4034291c1004000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000000000030c161f29323c464f59616c727f8b929ca5a0969083796d665c5049525c606d78828f959fa69e938d80736d625a50473d32271b10030000000006111c2a36424d57626e7b87929fa8b0a69f92877c6f695f585046413b36312d2c282327272723282c2d31373b42465159606b717e8a929da8b1a79f92857a6d61554b4035291d10040000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d2014131313131313131313131313131313131313131313131313130807050200000000000000000000000000091623303c4956636f7c8997a1a5988b7e7265594f453d3731302f35393a40454950565e686f7c89959fac9f9286796d6053463a2d2013070000000000000000000008121a242c363e45494a4c4a46505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0a2a2a194877b6e6154483b2e21150800010d18242f3a4754616d7a86939393939a9da5afb5aaa0989593939393939393939393939393939393908376685e5246392d2014070000000000000000000000000000000000000000000000000000000916222f3b4854606b707373737374747576787b7e82868e9299a1a39f9791867e716b60564d4133291f140900000000000000000a15202a343e48515b636c717b81878c919597999c9d9e9e9f9f9f9e9d9b9998928e89827b716c625b51473e32281e0e040000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140c0c0c0c0c0c090e13202d3a4653606d798693a0acac9f9286796c605346392d2013060000000000000000050b10141617202020202020202020202734404d5a6773808d9aa69b8e8174685b4e41352820202020202020202020171714110c05000000000013202c3946535f6c7986929facada093867a6d6053473a2d2014070606000004060707070c131f2b3844505b667683909ca9b5ab978a7e7164574b3e3124180b0013202c3946535f6c7986929facada093867a6d6053535353535353535353534b5153545557575e61696e78818e949fabafa59d9083776b6054483b2f1f140900000b1825323e4b5865717e8b9393939393897c6f6256493c2f23160900000d1a2733404d5a6673808d939393939386796d6053463a2d201307000e1b2834414e5b6774818e9aa7afa399897c706356493d30261c110a080a111c28343f4a54626f7c8898a2aea49a8a7e7164574b3e2f23180c00000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000000000000020b151e28313b444e58606b707e87929fa4a19791847a6d675d544a515b636e74818e949ea79e948e81776c605b51483e352b21160b0000000000000e1a26313b47535f6974808d96a0abaea39991857b6e6a615a524c46423c3a38342e3434342e34383a3c42474d535b626b707d86929fa4aeaaa0958b7f72685e5243392f24180d010000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0b0a080500000000000000000000000713202d3a4653606d7985929ea99c8f82766b60574f47433e3d3d4045474b51535b60686e7a84919ea7a99d908376665c5145382c1f130600000000000000000008121a242c363e48505557585651505d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0adaea194877b6e6154483b2e21150800000713202d3946525e687682868686868e929da9b0a4988e888686868686868686868686868686868686887b6e6154473b2e2114080000000000000000000000000000000000000000000000000000000a1623303d495663707d808080808181828385878b8f92999fa09e99928d857c716c61594f443b3021180d030000000000000000030e18222d363f49515a61696e747b8084888b8d8f90919292929291908e8c8985817c766e69615a51493f352c20160c000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20191919191919191a1a1c222d3a4754606d7a8793a0adafa399877a6d6054473a2d211407000000000000000000000407090a1313131313131313131a2734404d5a6773808d9aa69b8e8174685b4e4135281b1313131313131313130b0a08040000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000030f1c28333f4a546875828f9ba8b2a5988b7f7265584c3f3225190c0013202c3946535f6c7986929facada093867a6d606060606060606060606060555d6061626466696e737b828e939ea6b0a79e938a7d7063594f44382c200d0200000b1825323e4b5865717e868686868686867c6f6256493c2f23160b0301071a2733404d5a66738086868686868686786d6053463a2d201307000c1825323f4b5865727e8b98a9b2ab998c7f7266594f42382e231a1615141c232c3844505c6673808d9aaaac9f93877a6d6154473a2e21140700000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000a141d27303a434d565f6a6f7d869299a3a29892857b6e685e554b505a626d73808c939da69f958f82786d655b50493f362c23190f0400000000000009141f2b37424d57606d79849199a4afaba19791847c706c615e56534d494644404141414141404546494d53575f616d727d869298a2aeaca2989083786c60564c4131281d1207000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a171714110c0500000000000000000006121f2b3844505c6673808c96a19f94897d70696059534e4b49494b5153555d60656c717a839096a0aca2978c7f7265544b4034281c1004000000000000000008121a242c363e48505a616465625b515d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0adaea194877b6e6154483b2e211508000005111e2a36414c5666707679797979818e9aa7aea195887c79797979797979797979797979797979797976685e5246392d2014070000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c8d8d8d8d8e8f909298979c9c9a9896918d86807a6f6a615a50473d32291f0f060000000000000000000006101b242e373f4850575e61696e73777b7e80828484858686858583827f7d79756f6b625f5750483f372d231a0e04000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d252525252525252626262b2d333c4855616e7b8894a1aeaea399867a6d6053473a2d201407000000000000000000000000000006060606060606060d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0606060606060606000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000b17222d414e5b6774818e9aa7b2a5998c7f7266594c3f3326190c0013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c676d6e6e7073767b80858f949ea5afa8a0958e81756b6155473d32271b0f0000000b1724313d4a56626c71797979797979796f6a6054473b2e231c150c0b121826323f4b58636e737979797979797976665c5044382c1f1206000916222f3c4955626f7c8897a1adaa9d9184776b60544a3f342b26232222262e35414c56606d7985919eabaa9d908376685e5246392d20130700000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000000000006111c262f39434c565e696e7c859298a3a39992867c6f695f564c4f59616c727f8b929ca5a0969083796d665c53493f372d241a110700000000000000030e1a26313c45515d676f7d87939fa4aea9a19691867e756e68615e575653514a4e4e4d4e4e4b515356575f62696e767f879298a2aaafa49a92867c6f665b50443a301f160c01000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a2d27272727272727272727272727272727272727272727272727272727272423211c171008000000000000000003101c28343f4a54606d7a849199a49e91847b6f6b625f58585656555d6064676d71787e859095a0a8a49e92857a6d6154473a2e23180c000000000000000008121a242c363e48505a616c71726d625b5d697683908f8275685c4f4235291c0f000714212e3a4754616d7a8794a0acaca194877b6e6154483b2e2115080000010d1925303a44545e66696c6c6c75818e9ba8ada194877a6e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b5e564d41362a1e11050000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c999a9a9a9b9b9d9fa29f94908d8b8884807b746d68605850483e352b20170d00000000000000000000000915202b353f474e524d52575f62666a6e71737577787879797978777573706d67636059534d46423c332a1f140900000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a323232323232323233333137383f444f5964717e8b97a4b1ac9f928679675d5145392c1f1306000000000000000000000000000000000000000000010d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140700000000000000000000061b2834414e5b6774818e9aa7b2a6998c7f7366594c403326190d0013202c3946535f6c7986929facada09386797979797979797979797979797979797a7a7b7d8082868c92979fa6afa79f969183796d60594f44352b21160b0000000915212e3a45505a62656c6c6c6c6c6c6c6260584e443d342e271e18151d2329333c47525c63666c6c6c6c6c6c6c6c5c544a3f34281c1003000613202d394653606c7884919eabaca095897d70665c50443f37312f2e2f30383f46525e68717e8b97a1ada3988b7e7265564c41362a1e110500000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000091217222d38424b555d686e7b849197a2a39f92877d706a60574d4e58606b707e87929fa4a19791847a6d675d544a41382d251b120800000000000000000009151f2935404b55606b727f8b929da4ada9a198928a817a746e696562605c545b5a5a5a5b545c606266696e747b828b9299a2aaaea39f93887e706a5f544a3f32291e0d0400000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343431302d28221a120800000000000000000b17232e3845525d68707d87939aa19691847d746f6a6764636366676d70757a7e838b9297a0a7a49c928b7e71685d5246392d1d12070000000000000008121a242c363e48505a616c717e7f726d6257697683908f8275685c4f4235291c0f000714212e3a4754616d7a87949f9f9f9f94877b6e6154483b2e211508000008131e28323a4146545a5d60606875828f9ba8ada093877a6d606060606060606060606060606060606054524d443b3025190e020000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c99a5a6a7a7a8a9aba99c9083807e7c77736e69615e564e463e362c23190e0500000000000000000000010e1a26313d4751595e5f6060605e575f626466696a6b6b6c6c6c6b6a686663605d6060606055534d453c31261a0e02000000000000000000000013202c3946535f6c7986929facada093867a6d6053473f3f3f3f3f3f3f3f3f3f404142464a5057606b75828f9ca8b5aa9d9184776a554b4035291d1004000000000000000000000000000000000000000000010d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140700000000000000000205101c2834404b556875828f9ba8b2a5988b7f7265584c3f3225190c0013202c3946535f6c7986929facb9a2958b868686868686868686868686868686868687888a8c8f92999fa2a9aba39f9590847b6e675d51473e3323190f0400000005111d29343f4850565860606060606060605e56544f444039302a211f272f343e454d53555d60606060606060605f504a42382e23170c000005121f2b3744505b6574808d9aa6b0a89d9083786d605a5047433d3c3b3c3d424a505b616d7a85929ea9ab9f92867a6d6154473a3025190d0100000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000007101b2428333f4a545c676d7a839096a1a49c918b7e716b61584e4d565f6a6f7d869299a3a29891857b6e685e554b42382f261b130900000000000000000000030d18242f3a434f59626d74808d929ca3adaaa29f938e86807b76726f6d6669686767676869666d6f72777b81868f949fa3ababa39f918c7f726c61584e42382d20170d0000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d605347404040404040404040404040404040404040404040404040404040404040403e3c39332c241a10050000000000000006111c2935414c56606b717e8892989f969188817c777471707073767a7d81858b91959ea1a9a29f928d80736c61564c4135291d0b0000000000000008121a242c363e48505a616c717e878b7f72695e697683908f8275685c4f4235291c0f000714212e3a4754616d7a87939393939393877b6e6154483b2e21150800010d1925303a444c52545757575c6875828f9ba8aca09386796d60575757575757575757575757575755544e46413b32291f1408000000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c999f9fa0a1a2a4a6aa9e9185817e7a746e69605c554d443d342c241a1107000000000000000000000004111d2a36424e59636a6c6c6c6c6b636059585a5c5d5e5f5f5f5f5e5d5b575f626a6c6c6c6c6c5f574d42372b1e1205000000000000000000000013202c3946535f6c7986929facada093867a6d60534c4c4c4c4c4c4c4c4c4c4c4d4e4d53545b6069707d88939facb3a99b8e8174685b4e412f24180c00000000000000000000000000000000000000000000010d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140c0c0c0c0c0c0c0c090e1116202c3845515c677683909ca9b6ac978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a79d959393939393939393939393939393939393949597999c9fa3abaca49f99928d837b6e695e554c41352c21110700000000010c18222d363f454a4b5359636a6c6c6c6c6b636059514a423c332a2a3139404550575f626a6c6c6c6c6c5f574d53443f3830261c11060000030f1b27333f4953626f7c88949eabab9f958c7f726c625a534e4a4948484a4e545c606d75818e97a1ada3998d8074685d524639291e13080000000000000000000002070a0c0d0908060a1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000000040f19222d363e44505b666d79828f95a0a59d928c7f726c62594f4c565e696e7c859298a2a39892867c6f695e564c433930261d140a01000000000000000000000007131d28313d47515b606c77808c919ea1a9aea59e98928d87837f7c79777674747474747677797c7f83888e92999fa6aea8a199928b7f736d635a50463c2f261c0e050000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4a49453e362c22170c00000000000000000d19242f3a444f59626c717e868f949c9a938e8883807e7c7c7f83868a8e92989da0a7a39f97928a80736e645a50443a3024190d00000000000008121a242c363e48505a616c717e879292867b6e61697683908f8275685c4f4235291c0f000714212e3a4754616d7a86868686868686867b6e6154483b2e2115080005111d2a36414c565e61646464646875828e9ba8aca09386796d6464646464646464646464646464646260584e43372b20170d02000000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c939393939495979a9d9f97918e8b85817b736d675e564d453b30271d1207000000000000000000000006121f2c3845525e6a757979797978706b605c544d5151525353524b515a61696e777979797976695f53463a2d211407000000000000000000000013202c3946535f6c7986929facada093867a6d60585858585858585858585859595a575f61666c717b84919aa4afada2978a7e7164574b3e3124180700000000000000000000000000000000000000000000010d1a2734404d5a6773808d9aa69b8e8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201919191919191919191a191e2028323a4653606d7986929facafa49a897c6f6356493c302316090013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa0a1a1a3a6a8a6a8a09e9a938f8780796e695e574d433a2f231a1000000000000006111b242d343a3d3e525e6a757979797978706b605c544d453f36333c434b515a61696e777979797976695f53463a342e261e150a000000000b17222d3847535f6a75828f99a3afa79f92877e716c625f5857565555575860666d737f8c939ea9a89f92867b6e61564c413529170d02000000000000000000070d131619191515120f1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000a16212b343e48515b606c78818e949fa69e938d80746d635a504b555d686e7b849197a2a49992867d706a5f574d443a31281e150b02000000000000000000000000010c161f2b353f44505b656c747f8a92979ea6acaaa29f9a93908c898684828181808181828486898c90959a9fa3ababa49f9691877e736d635b51473e342a1d140a000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a575550483e33281c11050000000000000008131e28323d47505a626c717b82898f92999b95908d8b89898c8f92999b9fa2a9a29e99928e857e736e645c52483e32281e13080000000000050e1a242c363e48505a616c717e879292867d70695e697683908f8275685c4f4235291c0f000713202d3946525e6876797979797979797976695e52463a2d201407000713202d3946525e686d717171717174818e9ba7ada093877a717171717171717171717171717171716f6a6054473c31261a0e02000000000000000000000000000000000000000000000000000000000c1926333f4c5966727f868686868687888a8d90959a9e9b98928d8680796e695f574d43392e23180c03000000000000000000000613202c3946535f6c7987868686847d736d665f5751464146454d555c606c717b83868686867b6e6155483b2e221508000000000000000000000013202c3946535f6c7986929facada093867a6d65656565656565656565656566666769696e72787e859196a1acb1a79f9285796d6053473a2d20140700000000000000000000000000000000000000000000010d1a2734404d5a6773808d9a9a9a8e8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2525252525252525252627252a2d323a444e5863707d8998a2aeac9f93867a6d6154473a2e2114070013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9f9e9d9b999796918c87827c736d675e574d453b31281e11080000000000000009121b22292e3946535f6c7987868686847d736d665f575146413e454d555c606c717b83868686867b6e6155483b2e231c150c030000000006111b2b37434e58626f7c87929fa6aea39992877e766f6a666462616263666a6f78808c919ca5aaa0968c8073695e53443a302419050000000000000000010a12191e23252622211f1b1724303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000030f1b27323d47505a636d74808d939ea69f948e81786c605b514a545c676d7a839096a1a49f93877e716b60584e453b32281f160c030000000000000000000000000000040d192327333f49535b606d737d858f949da0a7acaca49f9c989892918f8e8d8d8d8e8f919298999d9fa7acaca69f99938d847d716c635b51493f352c22180b02000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada093867a6d6767676767676767676767676767676767676767676767676767676767676767676764615a5045392d21140800000000000000010c16202b353f48505a61696e767d8287929fa09d9a979696999c9fa3a9a29f9b97928d86817a716c635c524a40362d20160c0200000000020d17202c363e48505a616c717e879292867d706b6057697683908f8275685c4f4235291c0f0005111d2a36414c565e6c6c6c6c6c6c6c6c6c6c5e574d42362a1e1205000714212e3a4754616d7a7e7d7d7d7d7d828f9ca9b1a4988b7f7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7c6f62574d42372b1e1205000000000000000000000000000000000000000000000000000000000c1825323e4b57636d72797979797a7a7b7e8083888d9399a09f99928c837b6e695f554b4034281f140900000000000000000000000b1825323e4b5865717e8b9296918780786e69625b524c4550575f676d747e869095948d8074695f53463a2d211407000000000000000000000013202c3946535f6c7986929facada09386797272727272727272727272727272737476787b7f848a9297a1a8b2a9a0958c7f72675d5145382c1f130600000000000000000000000000000000000000000000010d1a2734404d5a6773808d8d8d8d8d8174685b4e4135281b0e0200000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a32323232323232323232333330363a3e444c565f6a75818e9baab4aa9d918477685d5246392d2013070013202c3946535f6c7986929facb9a79d959393939393939393939393939393939399929291908f8d8a8784807b756f6a605c554d453b33291f160c0000000000000000000911181d25323e4b5865717e8b9296918780786e69625b524c4550575f676d747e869095948d8074695f53463a2d21110a030000000000000f1b26313c47535f6a73808c949fa7aba399928b827c7773706f6e6f7073777c838d929ca3aba2989184796d60574d4232281e130800000000000000000a131c242a2f32332f2e2b262024303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000007131f2c38434f59616c727f8c929da5a0959082796d665b5044505b666d79828f95a0a59c928b7f726c61594f463c332920160d0400000000000000000000000000000000071017222d384149505b636b707b828990959c9fa4acaca9aaa39f9d9c9b9a9a9a9b9c9d9fa3aaaaababa39f9b948f878079706b625a514940372e231a100600000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facada09386797373737373737373737373737373737373737373737373737373737373737373737373716c6155493c3023170a0000000000000000040d19232d363f49515a61696e757b818e9aa7aaa7a4a3a3aba39f9c9997928e8a85807b746d68615a524a40382e241b0e04000000000008141f29323e48505a616c707e879291857c6f6b646464697683908f8275685c4f4235291c0f00010d1925303a444c525f60606060606060605f524d453b30251a0e02000714212d3a4754606d7a868a8a8a8a8a8f949fabb3a79b918b8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8377695f53463a2d211408000000000000000000000000000000000000000000000000000001020a16222f3a46515b63666c6c6c676d6e6f7173777c81879195a0a39f9590847b6e675c51453b30251a0e02000000000000000000000b1724313d4a56626d73808c9399938d837b726d615e56515a61696e79818a9298958f82786d60574d42372b1e1205000000000000000000000013202c3946535f6c7986929facb2a5988b7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80818384888b91959fa2a9afa8a1979083796d60554b4035291d100400000000000000000000000000000000000000000000000a1724303d4a5763707d80808080807e7164574a3e3124170b0000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473f3f3f3f3f3f3f3f3f3f3f3f404142464750565d686f7c87939facb0a69a8d807367564c4135291d11050013202c3946535f6c7986929facb9a2958b86868686868686868686868686868686868685858382807e7b77736e69625f58514b433b332921170d0400000000000000000000060c1724313d4a56626d73808c9399938d837b726d615e56515a61696e79818a9298958f82786d60574d42372b1e1200000000000000000a15202b37434e58606d78828f959fa6aba39f948f8883807d7c7b7b7d7f838990959ca4aba39992867c6f675d51453b3120160c020000000000000007121c252e353b3e403c3b37322a24303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000915222f3b4854606b717e88939fa4a19690837a6d675c544a4653606c78818e949fa69d938c80736d625a50473d342a21170e0500000000000000000000000000000000000006111b262f383f44515961696e757d83898f939a9c9fa2aaa7a8aaa9a7a7a7a7a7a9a9a8a6a9a29e9b99928e88827c746d676059504840372e251c11080000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb3a79a8d8080808080808080808080808080808080808080808080808080808080808080808080807e7164574a3e3124170b00000000000000000915202a333f48515b636c717b81878e939da9acaba49f9d999992908c8985817d79746e69615e56504840382e261c12090000000000020e1925303b44505a616c707e879291847c717171717171717683908f8275685c4f4235291c0f000008131e28323a41465353535353535353534846423b33291f140900000613202c3945525d6876828f979797979c9fa6b0b7aca39b9897979797979797979797979797979795887b6e6155483b3025190e0200000000000000000000000000000000000000000407090a0d0e0f10121e2a353f495157596060555d60616264676a6f747c839095a0a7a0969083796d60574d42362a1e1205000000000000000000000915212e3a45505a636e74818e939f9590867e756d68605c606c717b838e939f969083796d665c50453c31261a0e02000000000000000000000013202c3946535f6c7986929facb9a79b918b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8c8d8f9196989da0a7adaba59e9691857b6e675c5143392f24180c0000000000000000000000000000000000000000000000000916232f3c4855616b707373737373716c6155493d3023170a0000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d60534c4c4c4c4c4c4c4c4c4c4c4c4c4d4e4d52545a61686d7a83909aa4afac9f94887c6f6255493c3024190d010013202c3946535f6c7986929facada093867979797979797979797979797979797979797878777573716e6966625f57534e454039302920170f050000000000000000000000000915212e3a45505a636e74818e939f9590867e756d68605c606c717b838e939f969083796d665c50453c31261a0e0200000000000000030f1b26313c44505c666d7a8390949fa4aca69f9c95908c8a8988888a8c90959d9fa7a8a19992877e716a5f554b4033291f0e0400000000000000020d19242e3740464b4c4847433c3429303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000091623303c4956636f7c86929a93939791847b6e685d554b424d5a6673808d93939393948e81746e635b51483e352b22180f0500000000000000000000000000000000000000000a141d262d3340474f575e616b70777d82878b8f9298989a9b9d9e9e9f9f9f9e9d9d9b999797928e8a86817c766f6a605d554f473e362e251c130a000000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f02000000000000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8174675b4e4134281b0e01000000000000020e1a26313c45505a636d727e868e939a9da5a39f9c9993908c898683807c7975706d66615e57524c443e362e261c140a00000000000005111e2a36414d56616c707e879292867f7e7d7d7d7d7d7d7d7e83918f8275685c4f4235291c0f0000020c1620283036394646464646464646463b3a36302921170d02000004111d2935414c5665727e8b9aa49f9fa1a3a9b1bbb5aca7a49f9f9f9f9f9f9f9f9f9f9f9f9f9fa7988c7f7265564c41362a1e1105000200000000000000000000000000000000050b101416171a1b1c1d1e1f232e373f464b4c53534b5153545557585f626a6f7a839097a1a8a0958d8074695e52463a2d2014090000000000000000000005111d29343f48525b606d78818f959f98928b827a706b676d747e8690959d9891847b6e675d544a3f332a1f140900000000000000000000000013202c3946535f6c7986929facb9ada39b989898989898989898989898989899999a9c9ea1a8aaacaaa69f9c938e847c6f695f554b4031271d12070000000000000000000000000000000000000000000000000714202c38444f596163676767676764615a5045392d2114080000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6058585858585858585858585858595a5a565e61656c707a829095a0acafa49a8f82766a5f53473b2e1e1308000013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a686664615e5755534d47433c342e271e170e050000000000000000000000000005111d29343f48525b606d78818f959f98928b827a706b676d747e8690959d9891847b6e675d544a3f332a1f14090000000000000000000a152028343f4a545d686d7a828d939a9fa6aba7a09d999795949596999d9fa7aba39f9691877e716c61584e43392f21170d000000000000000007131e2a35404952575955534e463f35303d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000c1925323f4c5865727f868686868686857c6f695e564c4343505c69768286868686868682786d605c52493f362c23191006000000000000000000000000000000000000000000020b141b2227353e454d525960636b70757b7e8285888b8d8f9091929292929191908e8c8a8885817e7a746f6a626058514b433d352d241c130a01000000000000000000000b1825313e4b5864717e8b97a4b1a89b8e8175685b4e4235281b0f06060606060000000000000000010e1b2734414e5a6774818d9aa7b1a4978b7e7164584b3e3125180b0013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675b4e4134281b0e0100000000000006121e2b37424e57626d727f8a92989fa4a29f99928f8b8683807d797673706d6664605c54534d46413a322c241c140a020000000000000714202d3946525e68707e87929999928c8a8a8a8a8a8a8a8a8a91958f8275685c4f4235291c0f000000050e161e252a2d2e39393939393939392e2d2a251f170f05000000010d19242f3b4754616e7b879393939394979fa9bcaea49c9993939393939393939393939393939393908376685e5246392d20140c070f0b0a080500000000000000000000000810161c202324262728292a2b2c202e353a3e3f464640454747484b4e535860686d7a85929ea9a79f92877b6e6154483b31261a0e02000000000000000000010c18222d364044505c666d79829095a09f938f857d746f79818a9298a09992867c6f695e554b42382e21180e0300000000000000000000000013202c3946535f6c7986929facacacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a7a9a9a7aca49f9d99948f89817a6f6a5f574d43392e1f150b0100000000000000000000000000000000000000000000000004101c28333e474f55575a5a5a5a5a575550483e33281d11050000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d656565656565656565656565656566666769696e72777d8590949fa7b1a79f93877c6f62584e43372b1f0c02000013202c3946535f6c7986929facada093867a6d6060606060606060606060606060605f5f5e5d5c5a5754524d4847423c373128231d150c050000000000000000000000000000010c18222d364044505c666d79829095a09f938f857d746f79818a9298a09992867c6f695e554b42382e21180e03000000000000000000030c17232e38424c565d686d78808790949b9fa2aaa8a6a3a2a1a2a3a6a8a9a29f99928d847d716c615a50463c31271d0f0500000000000000000a16232f3b46525b6366625f585146413a3d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000b1824313e4a56626d72797979797979786f6a5f574d443a414e5a667076797979797979756d665c504a40372d241a11070000000000000000000000000000000000000000000000020a1117232c333b42464f54596063696e7276797c7e808283848585868585848382807d7b7975716d68625f58544e45403a312b231b120a0100000000000000000000000b1825313e4b5864717e8b97a4aca89b8e8175685b4e4235281b0f13131313130c06060300000000010e1b2734414e5a6774818d9aa7aca4978b7e7164584b3e3125180b0013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69a8e8174675b4e4134281b0e010000000000000814212e3a47535f6a717e8b919fa2a69f98928d87827e7a7673706d676663605c5453514b46423b363029201c17110a020000000000000814212e3b4754616e7b859299a3a39f9793939393939393939393938f8275685c4f4235291c0f00000000050c13191d20212d2d2d2d2d2d2d2d21201e1a140d0500000000000814202d3a46525e69768386868686878d97aab4a89c928c8686868686868686868686868686868686887a6e6154473b2e211c181c1b171714110c05000000000000000008111a21282c2f30333435363738392d2c282f3233392f35393a3b3c3e43474e565e68717e8b97a1ada3998d807367574d42362a1e12050000000000000000000006111b2428343f4a545d676d7a839196a19e979188807b838e929fa29f93877d706a5f574d433a30261c0f060000000000000000000000000013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa49f9f9f9e9d9c9a999a93908d88827d756d685f584e453c30271d0d0300000000000000000000000000000000000000000000000000000b16212c353e44484a4d4d4d4d4d4a49453e362c22170c000000000000000000000000000000000000000013202c3946535f6c7986929facada093867972727272727272727272727272727272737475787b7f838a91979fa6b0a79f958d80746a6054463c32261b0f00000013202c3946535f6c7986929facada093867a6d605353535353535353535353535353535252504f4d4b4846423b3a37312b262018120b030000000000000000000000000000000006111b2428343f4a545d676d7a839196a19e979188807b838e929fa29f93877d706a5f574d433a30261c0f06000000000000000000000006111c26303a434c565d666d737c83898e9298999b9d9e9f9f9f9e9d9b9997928d87817a6f6b615a50483e342a1f150b0000000000000000000c1925323e4b57636d736f6a625b524c443d4a5763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000915222e3a46515b62656c6c6c6c6c6c6c625f584e453b323e49545e66696c6c6c6c6c6c69605c544a3f382e251b1208000000000000000000000000000000000000000000000000000006111a202930363d44484f54565e6165666d6f7174757778787979787877767573716f6d6664605d56534e47433d352f281f191109000000000000000000000000000b1825313e4b5864717e8b979f9f9f9b8e8175685b4e4235281b1320202020201913120f0b060000010e1b2734414e5a6774818d9a9f9f9f978b7e7164584b3e3125180b0013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675b4e4134281b0e01000000000005111e2a36424d57626e7b86929fa3a59e949086807b75716d686663605d555653504a464540393631302e2d2b28231c140c0400000000000714202d3946525e68717e87929999928a8686868686868686868686868175685c4f4235291c0f000000000002080d11131420202020202020201514120e090200000000000005111e2a36424d56667176797979797b8798a3aea6998c8079797979797979797979797979797979797976685e5246392d2c292329282423211d17100800000000000005101a232c33383c3d404142434445453a38342e27262d24292c2d2e2f31373d444c56606c7885919eabab9e918478695f53463a2d2114070000000000000000000000091217232e38424b555d686e7b849197a2a19a938d8890959da59d928b7f726b61584e453b31281e140a000000000000000000000000000013202c3946535f6c7986929393939393939393939393939393939393939a93929291908f8e8c898683807b76706b615e564e463c332a1e150b00000000000000000000000000000000000000000000000000000005101a232c33383c3d40404040403e3d39332c241a1005000000000000000000000000000000000000000013202c3946535f6c7986929facb2a5988b7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80818285878b90959ea1a9aea69f959083796d60584e43342a20150a00000013202c3946535f6c7986929facada093867a6d6053474646464646464646464646464645454442403e3b3a36302e2b261f1b150c0700000000000000000000000000000000000000091217232e38424b555d686e7b849197a2a19a938d8890959da59d928b7f726b61584e453b31281e140a000000000000000000000000000a151e28313a444c545c606a6f767c8185898c8e909192929292918f8c8985807b746d68605950483e362c22180d030000000000000000000d192633404c5966737f7c726d615d564f444a5763707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000006121e29343f495156586060606060605f55534e463c332938424c545a5c6060606060605c53504a42382e261c130900000000000000000000000000000000000000000000000000000000080e171f252a33383d44484d5254545c60626567686a6b6b6c6c6c6b6a6a68666462605c5454524c47433c383229241d160d0700000000000000000000000000000b1825313e4b5864717e8b93939393938e8175685b4e4235281f202c2d2d2d2c26201f1c17110a02000e1b2734414e5a6774818d93939393938b7e7164584b3e3125180b0013202c3946535f6c79869293939393939393939393939393939393939393939393939393939393939393939393939393939393938e8174675b4e4134281b0e0100000000000714202d3a46525e6975828e98a2a89e938e827b736e6964615e565653514b4946443f3a3e4041403e3d3b3a38342e261e160d040000000005111e2a36414d56616c717e879392867e797979797979797979797979756f65594d4134281b0e00000000000000010507071313131313131313080705020000000000000000020e1925303b44555f666a6c6c6c6c7985929faca89b8e81756c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b5e564c413b3a38342f363531302d28221a120800000000000b16212c353e44484a4d4e4f505152524644403930271c181d20202122262b323a44505b6674818e9aa7ada196887b6e6155483b2e22150800000000000000000000000006111c263039434c565e696f7c859299a3a49f9a959da0a79e948d80746d62594f463c33291f160c02000000000000000000000000000013202c3946535f6c79878686868686868686868686868686868686868686868685858483817f7d7a77736e6a636059524c443c342a21180c030000000000000000000000000000000000000000000000000000000008111a21282c2f30343434343431302d28221a120800000000000000000000000000000000000000000013202c3946535f6c7986929facb9a79b918b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8d8d8f9197989da0a7adaaa39f948f837a6d675c51463d3222180e0400000013202c3946535f6c7986929facada093867a6d6053473a3939393939393939393939393938373533312e2d2a25211e1a150f0a0400000000000000000000000000000000000000000006111c263039434c565e696f7c859299a3a49f9a959da0a79e948d80746d62594f463c33291f160c0200000000000000000000000000030c161f28323a424a515860626b6f75797c7f828385858685858482807c79746e6a615e564f473e362c241a1006000000000000000000020f1c2835424f5b687581867f756d686059504a5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000010d18232d373f464a4c535353535353524847433c342a21303a42494e505353535353534f46443f3830261c130a010000000000000000000000000000000000000000000000000000000000050d141a21272c33383b4246474a545c6a6c6c6c6c6c66605b5f5e5e5d5b59575553504a4745413a37312b272018130c040000000000000000000000000000000b1825313e4b5864717e868686868686868175685b4e4235282b383939393939332d2b28221c140b060e1b2734414e5a677480868686868686867e7164584b3e3125180b0013202c3946535f6c7987868686868686868686868686868686868686868686868686868686868686868686868686868686868686868174675b4e4134281b0e0100000000000814212e3b4754616e7b87939faaa0968e81786e69615e5754524c494745403d3a3840464b4c4e4c4b494846443f3830281f160c01000000020e1925303b44505a616c717e879392877e716c6c6c6c6c6c6c6c6c6c68655d54493d3125190c000000000000000000000000000000000000000000000000000000000000000009141f2932434d555b5d60605b667783909daaaa9d908377675c60606060606060606060606060606054524c4446484745404443423e3d39332c241a100500000004101c28333e474f5557595a5b5c5d5e5f53514a42392e231810131414151b2028333f4a5464717e8b97a4b2a8978a7e7164574b3e3124180b000000000000000000000000000a141e27313a444d575f6a707d879299a49f9f9f9fa9a0958f82786d605b51473e342a21170d04000000000000000000000000000000121f2c3845525e6a757979797979797979797979797979797979797979797979797877767472706d6866625f58544f46413a322a22180f060000000000000000000000000000000000000000000000000000000000000810161c20232427272727272423211d1710080000000000000000000000000000000000000000000013202c3946535f6c7986929facb9ada39b9898989898989898989898989898989899999a9c9ea1a9aaacaba39f98928c827a6d685e554b40342b2110060000000013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d2d2d2d2d2c2c2b2a29272421201e1a14120e09030000000000000000000000000000000000000000000000000a141e27313a444d575f6a707d879299a49f9f9f9fa9a0958f82786d605b51473e342a21170d04000000000000000000000000000000040d162028303940444e54596063666d707275767879797978777573706d66625f57524c443d342c241a120800000000000000000000020f1c2835424f5b6875828e8b827a6f6b605c545763707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000006111b252d343a3e3f464646464646453c3a37312a221e2830383e4143464646464646423a38342e261e140a010000000000000000000000000000000000000000000000000000000000000002090e161c21272c30363a44505c66757979797979726c665f5751504f4d4a4846443f3a39352f2b26201b160d0701000000000000000000000000000000000a1724303d4956626c7179797979797979756f65594d402e34384546464646463f3938332d261d180f091a2733404c58646e7479797979797979716c6256493d3024170a00121f2c3845525e6a757979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746f64594c4033271a0d0100000000000b1825313e4b5864717e8b99a4aa9d9184796d665f57524d4746413d3a38352f3040495157595b5958565453504a423a31281e13080000000008141f29323e48505a616c717e889392877e716c615a6060606060605c59544b42372c2115090000000000000000000000000000000000000000000000000000000000000000020d1720313b434a4e50534a546774818e9aa7ac9f9286796d6053535353535353535353535353535347464a51535453514b504f4e4a49453e362c22170c0000000714202c38444f596163666768696a6b6c605c544a4034281c100607080a0e17222d3d4a5763707d8a96a3b0a5988b7f7265584c3f3225190c00000000000000000000000000020c151f28323b454e58606b717e8793939393939393969083796d665c50493f352c22190f0500000000000000000000000000000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a69676663615e5655534e48443d363028201810060000000000000000000000000000000000000000000000000000000000000000050b101416171a1a1a1a1a171714110c05000000000000000000000000000000000000000000000013202c3946535f6c7986929facacacada7a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a7a8aaa8a6a7a09d99928e867f786d685e564c43392e22190f000000000013202c3946535f6c7986929facaca093867a6d6053473a2d20202020202020202020201f1f1d1c1a181514120e0906020000000000000000000000000000000000000000000000000000020c151f28323b454e58606b717e8793939393939393969083796d665c50493f352c22190f050000000000000000000000000000000000040d161e272e343d43474f54545c606366686a6b6c6c6c6b6a686663605c54534e46413a322b221a12080000000000000000000000020f1c2835424f5b6875828e938f847d736d665e5763707d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000009131b23292e3132393939393939392f2e2b262018161e262d323536393939393939362d2b28231c140c0200000000000000000000000000000000000000000000000000000000000000000000050b10161c1f252d3a4653606d7987868686867f786e69625b524d443e3c3a38342e2c29241e1b150f0a040000000000000000000000000000000000000815212d3945505a62646c6c6c6c6c6c6c68655d53483d383f445253535353534c46443f382f2a2119141824303c48535c64676c6c6c6c6c6c6c64625a5045392d21150800111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c67645d53483c3024180b0000000000010d1a2734404d5a6773808d9aaba4988b7e71675c544d46423b3935302d2c292e3842515b63666866646361605c544c433a2f24190d01000000020d17202c363e48505a626c717e889392877e716c61574d535353534f4d49423930261b1004000000000000000000000000000000000000000000000000000000000000000000050e1f2831383e4243464b5865717e8b98a8aea399897c7063564946464646464646464646464646404a545c6061605c555d5c5b575550483e33281d110500000916232f3c4855616b70737475767778786d665c5144382c1f12060000000616232f3c4956626f7c8995a2afa6998c807366594d4033261a0d0000000000000000000000000000030d162029333c464f59616c727f8686868686868686847b6e675d544a3f372d231a100700000000000000000000000000000000000e1a26313d4751595e5f6060606060606060606060606060606060606060605f5f5e5d5c5b595654524c4847433c38332a251e160e0600000000000000000000000000000000000000000000000000000000000000000000000407090a0d0d0d0d0d0b0a08050000000000000000000000000000000000000000000000000013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9f9e9d9b999795908c86817b736d665e564c443a30271d1007000000000013202c3946535f6c7986929f9f9f9f93867a6d6053473a2d20141313131313131313131212110f0d0b08070502000000000000000000000000000000000000000000000000000000000000030d162029333c464f59616c727f8686868686868686847b6e675d544a3f372d231a100700000000000000000000000000000000000000040c151c232832373d43484b515356595b5d5e5f5f5f5f5e5c595653514b47423c35302820191008000000000000000000000000020f1c2835424f5b6875828e9b96918780786e696163707d8a96a3b0a3978a7d7064574a3d3124170a0000000000000000000000000000000000010911181e2224252d2d2d2d2d2d2c22211f1a150e0c141b212628292d2d2d2d2d2d29201f1c17110a0200000000000000000000000000000000000000000000000000000000000000000000000000050b10141f2b3844505c66717e879399928c827b726d615e565046413a322924201d19130f0a04000000000000000000000000000000000000000005111d29343e48505658606060606060605b59534b4138424a505e5f6060605f5953504a423b332a251f17202b36414a53585a60606060606060585650483e34291d1105000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060605b59534a41362b2014080000000000020e1b2835414e5b6874818e9ba7a194887b6e61554b423b36302d292523282c343f4a54636d73747371706e6d665d564c4135291d110400000000050e1a242c363e48505a626c717f889392877e71695f534646464642413d3730271e140900000000000000000000000000000000000000000000000000000000000000000000000d161f272d3236373b4855616e7b8896a0acab998d807366594f4338393939393939393939393844515c666d6e6d676b6a696864615a5045392d21140800000a1724303d4a5763707d80818283848586786d6053463a2d20160d0909070c1724303d4a5763707d8a96a3b0a69a8d8073675a4d4034271a0d010000000000000000000000000000040e17212a343d47505a626d727979797979797979786e695e554b42382e251b11080000000000000000000000000000000000000915202b353f474e525353535353535353535353535353535353535353535353525251504e4c4a4746413b3a37312c272119130c05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929393939393939393939393939393939393939393939399929291908f8d8a87847f7b756e69605c544c443a32291e150b00000000000013202c3946535f6c7986929393939393867a6d6053473a2d20140706060606060606060605040200000000000000000000000000000000000000000000000000000000000000000000000000040e17212a343d47505a626d727979797979797979786e695e554b42382e251b1108000000000000000000000000000000000000000000030b121820272b323839404546494c4f505252535252514f4d4946454039373129251e160e0700000000000000000000000000020f1c2835424f5b6875828e9ba199928c827b706c63707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000060d121518192020202020201f1515120f0a03030a1015191c1d2020202020201c1312100b06000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54616c717e87939a9490867f766e69615a524c443e352f281f19100700000000000000000000000000000000000000000000000c17222d363e45494b535353535353534e4d4841343f4a545c6a6c6c6c6c6c66605b544d453f3630292019252f3841484c4e535353535353534b49453e362d22170c00000915202b353f474e525353535353535353535353534a545c6a6c6c6c6c6c66605b544d5353535353535353535353535353535353534e4c4841382f251a0f030000000000020e1b2835414e5b6874818e9ba7a194877a6e6154473e39352f3333332e34383d44505c66737f817f7e7c7b786d685d5245392c201306000000000008121b242d363f48505a626d727f8b9192867b6e6155483b39393534312c261e150c020000000000000000000000000000000000000000000000000000000000000000000000040d151c2226292d3a46535f697784919eaaaa9d9184776b6054483d31282d2d2d2d2d2d2d2d3a4653606d787b7a7978777675716c6155493d3023170a00010e1a2734414d5a6774808c8d8e8f9091887c6f6255483e31281f1a171617181d27333f495364717e8b97a4b1a6998c807366594d4033261a0d00000000000000000000000000000000050f18222b353e48515b62656c6c6c6c6c6c6c6c6b615e574d433a30261c130900000000000000000000000000000000000000040f19242d353d4245464646464646464646464646464646464646464646464646454443413f3d3a3936302e2b26201c160d080200000000000000000000000000000000000000000000000000000000000000000000020608080b0e1011121313121211100d0b08070502000000000000000000000000000000000000000013202c3946535f6c79878686868686868686868686868686868686868686868686868685858382807d7a77736e69615f57504a423a322920170c0300000000000013202c3946535f6c798786868686868686796d6053473a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f18222b353e48515b62656c6c6c6c6c6c6c6c6b615e574d433a30261c1309000000000000000000000000000000000000000000000000070c151b21272c2e34383a3d3f424345464646454442403d3a38342e2b262019130c040000000000000000000000000000020f1c2835424f5b6875818e969ea39f9490857d746d707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000106090b0c13131313131312090806030000000005090d0f101313131313130f07060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17232e3842505a616c717e88939a98928b827b716c615e564f45413a312b22190f040000000000000000000000000000000000000000000006111b242d34393d3e4646464646464642403d373844505c66757979797979726c665f575146423b3229251e262f363c4041464646464646463e3d39342d241b11060000040f19242d353d4245464646464646464646464644505c66757979797979726c665f5751464246464646464646464646464646464641403c362f261d1308000000000000000d1a2733404d5a6673808d99aca295897c6f62585047454140403f40404045464f57606d78858e8c8b8987867a6d6054473a2d21140700000000000009121b242d363f48505a626d727f8b8c7f72695f53463a2d2d292825211b140c0300000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1e2a36424d576773808d9aa7aca096897c6f63594f433a3129242322222429333f4a5463707d878685848382817e7164574a3e3124170b00000b1825323e4b5865717e8b989b9c9d988b7f7265594f433a312a2524232323282f3744505b6574818e9aa7b5ab988b7e7265584b3f3225180c0000000000000000000000000000000000061019232c363f4951565860606060606060605e54524d453b31281e140a01000000000000000000000000000000000000000008121b242b3136383939393939393939393939393939393939393939393939393837363433302e2d2a25211f1a15100b050000000000000000000000000000000000000000000000000000000000000000000205090e121415181b1d1e1f20201f1f1e1c1a181514120e0905020000000000000000000000000000000000121f2c3845525e6a7579797979797979797979797979797979797979797979797979797878777573716e6866615e57534d443f38302820170e0500000000000000121f2c3845525e6a75797979797979797976675c5145382c1f1306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061019232c363f4951565860606060606060605e54524d453b31281e140a0100000000000000000000000000000000000000000000000000040a0f161b1d23282c2d303335373839393938373533302d2c28231d1a150d080200000000000000000000000000000000091623303c4956636f7d848e939fa29f97928a8079707d8a96a3b0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c26303e48505a626c717f88939f9f948f857e756d686159514b433d342b21160a000000000000000000000000000000000000000000000009121b22292d3031393939393939393534312d3a4653606d7987868686867f786e69625b524d443e35302820252b3033343939393939393931302d29221b12090000000008121b242b313638393939393939393939393a4653606d7987868686867f786e69625b524d443e353039393939393939393939393433302b251d140b01000000000000000b1824313e4b5764717e8a9aa4a69a8d80736a615a54524c4d4d4c4c4d4b515359606a717e8b979997968f8376685d5245392c2013060000000000000009121b242d363f48515b626d727f80736d63574d42362a1e1c1b191510090200000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1a26313c4855626f7c88959faba89b8f82756b60554b433b352f2f2f2f2f353b44505b6673808c989291908f8b7e7164584b3e3125180b00000815222e3b4855616e7b8896a0a9aa9d9083776b61554b433c36313030302e3439404b55606c7884919eaaafa499897d7063564a3d3023170a00000000000000000000000000000000000007111a242d373f464a4c5353535353535353524846423b33291f160c020000000000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2b2a2928262321201d1914120f090300000000000000000000000000000000000000000000000000000000000000000002080e11151a1e21222528292b2c2c2c2c2b2b29272522211e1a14120e0902000000000000000000000000000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a686664615e5654534d46423c342e261e160e050000000000000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c5c554b4034291c10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111a242d373f464a4c5353535353535353524846423b33291f160c0200000000000000000000000000000000000000000000000000000000040a0f12181c1f202326282a2b2c2c2c2c2b292623201f1c18120e09030000000000000000000000000000000000000915222f3b4854606b6f7a818a92989fa29e928d837b7d8a96a3b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080a0a131313131310100d0a050000000000000000000000000000000000000000000000000000000000000a141e2c363e48505a626d727f8b919b9e97928a817a706b605d554e463d32271b0f0300000000000000000000000000000000000000000000000911171d2124252d2d2d2d2d2d2d28271f2b3844505c66717e879399928c827b726d615e565046413a3229241d2427272d2d2d2d2d2d2d2524211d17110900000000000009121920262a2c2c2d2d2d2d2d2d2d2d2b3844505c66717e879399928c827b726d615e565046413a3229242d2d2d2d2d2d2d2d282724201a130b0200000000000000000814212e3b4754616e7b87939fac9f92867c706c64605d565a5959595a555c60636b707c85929fa9a1968b7e7265564c4135291d1104000000000000000009121b242d363f49515b626d72736e635b51453b31261a0e0e0c090400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915212e3a47535f6a7683909da7aa9e93897c6f675d554c45413d3c3b3c3c40454d57606c7884919e9f9e9d95877a6e6154473b2e21140800000814212d3a47535f697784919daaaca0958a7d70675d554d46423e3d3c3d3e40454b515c67707d8a96a0acac9f93867a6d6054473a2d2114070000000000000000000000000000000000000008121b252d343a3e3f4646464646464646453b3a36302921170d04000000000000000000000000000000000000000000000000080f151a1d1f20202020202020202020202020202020202020202020201f1f1e1d1b19171413110d08060200000000000000000000000000000000000000000000000000000000000000000002080d14191e20262b2e2f323436383939393938373634322e2d2b26201e1a140e0902000000000000000000000000000e1a26313d4751595e5f6060606060606060606060606060606060606060606060605f5f5e5d5c5a5754524c4846423b373128231c140c040000000000000000000e1a26313d4751595e5f606060606060605f514b43392f23180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b252d343a3e3f4646464646464646453b3a36302921170d040000000000000000000000000000000000000000000000000000000000000000070c10131316191c1d1f1f201f1f1e1c1a161313100c070000000000000000000000000000000000000000000713202c38444f5960686d757e8590949fa39d959086818e9ba8b0a3978a7d7064574a3d3124170a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b1014161720202020201d1c1a16110a0300000000000000000000000000000000000000000000000000000000020c1a242d363f48505a626d727f8b919ba29f938e857d746d6760584e43382c1f1307000000000000000000000000000000000000000000000000060c11151718202020202020201b1b1c28343f4a54616c717e87939a9490867f766e69615a524c443e352f281f191b20202020202020181715110c060000000000000000080f151a1d1f20202020202020201c28343f4a54616c717e87939a9490867f766e69615a524c443e352f281f1920202020201b1a18140f08010000000000000000000714202d3946525e6876828f9aa4a39892857d76716d6868676666666668676d70757d859197a2a49e9184796d6053463a2f24190d0100000000000000000009121b242d373f49515b626566635c52493f33291f140900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2b37434e5864707d8a95a0aca59d9183796d675e56514b4a494848494b51575f69717e8b96a1aca89d908377685e5246392d201407000006121e2b37424d5766737f8c98a2aea79e9184796d675f57534d4b4a494a4b4b51555d606d7983909da8b2a99d908376685d5245392c201307000000000000000000000000000000000000000009131b23292e31323939393939393939382e2d2a251f170f05000000000000000000000000000000000000000000000000000004090e11121313131313131313131313131313131313131313131313131211100e0c0a070705010000000000000000000000000000000000000000000000000000000000000000000000040c13191f252a2d31373a3b3e41434445464645454443403e3b3a37312d2a251f1a140d050000000000000000000000000915202b353f474e5253535353535353535353535353535353535353535353535353535252504f4d4a4746413b3a36312b261f17110a02000000000000000000000915202b353f474e5253535353535353535345403931271d12070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131b23292e31323939393939393939382e2d2a251f170f0500000000000000000000000000000000000000000000000000000000000000000000000406070a0c0f101213131312110f0d0a0706040000000000000000000000000000000000000000000000030f1b27323d474f565d606c717b828c9299a0a098928e939eaab0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810171c2023242d2d2d2d2d2a2926221c150d040000000000000000000000000000000000000000000000000000000008121b242d363f48515b626d727f8c919ca39e97918a81796f6a6054483b2e221509000000000000000000000000000000000000000000000000000005080a0b131313131313130f0b17232e3842505a616c717e88939a98928b827b716c615e564f45413a312b22190f1313131313130b0a0805000000000000000000000004090e1112131313131313130b17232e3842505a616c717e88939a98928b827b716c615e564f45413a312b22190f1313130e0d0b0803000000000000000000000005111e2a36414d56626f7c87939fa5a297928a837d7a777573737273737476797d82889197a1a59d928a7e71675c514538281e1308000000000000000000000009121b252d373f495156585a57524a40372d21180d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b26313c4653606c7883909aa4aca0958f82796e68605d555756555556555d60696e7b85929fa8aca1968a7e7164564d41362a1e11050000020e1a26313c4754616d7a86929fa8aca1969082796e69615e575857565657545c60676d75818e95a0acada2978b7f7265564c4135291d11040000000000000000000000000000000000000000010911181e2224252d2d2d2d2d2d2d2d2b21201e1a140d0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080e161e25293036393c4247484b4e50515253535252514f4d4b4846423c3a36302a251f170f080000000000000000000000040f19242d353d4245464646464646464646464646464646464646464646464646464645454442403e3b3936302d2a251f1a140b06000000000000000000000000040f19242d353d424546464646464646464638342f271f150b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010911181e2224252d2d2d2d2d2d2d2d2b21201e1a140d05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212b353d444c525a61696e787f8791969da29f9b9ea5afb0a3978a7d7064574a3d3124170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a22282d303139393939393736322d271f160d030000000000000000000000000000000000000000000000000000000009121b242d363f49515b626d727f8c9193939393938e847c6f6256493c2f231609000000000000000000000000000000000000000000000000000000000000060606060606060006111c26303e48505a626c717f88939f9f948f857e756d686159514b433d342b21160a000606060600000000000000000000000000000000000104060606060606060006111c26303e48505a626c717f88939f9f948f857e756d686159514b433d342b21160a000601010000000000000000000000000000020e1925303b4754606a73808d939fa4a29f94908a86848280807f7f80818385898f939aa1a49f938d80746c61554b403428160c0100000000000000000000000009121b252d373f464a4c4d4b4740382e251c0f0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2b3744505b656f7c88939fa7a89e948f837a736d6765636262626365676d727b849197a2ada59e9184786d6053463b3025190e020000000915202d3946525e6873808c95a0aaa89f9490837b736e6967646363636465666d7179818e939da7b0a69e92857a6d6054473a2f24190d0100000000000000000000000000000000000000000000060d1216181920202020202020201f1514120e09020000000000000000000000000000000000000000000000000000000000000000000104060606060606060601000000000000000000040607090c0e0f11121213131211100e0b0808060200000000000000000000000000000000000000000000000000020a121a202830353b4146474e5355585b5c5e5f5f5f5f5e5e5c5a5855534d4846423b363029211a120a020000000000000000000008121b242b31363839393939393939393939393939393939393939393939393939393938373533312e2d2a25211e1a140e0903000000000000000000000000000008121b242b3136383939393939393939392c29231d150d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d1216181920202020202020201f1514120e090200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003070909131313131313130b0a08040000000000000000000000000000000000040f19232b323a414550575e666c727c848d929ea1a9aaafb7b0a3978a7d7064574a3d3124170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101a232c33393c3d464646464643423e3831281f150a000000000000000000000000000000000000000000000000000000000009121b242d373f49515b636d737f86868686868686868174675a4e4134271b0e0100000000000000000000000000000000000000000000000000000000000000000000000000000a141e2c363e48505a626d727f8b919b9e97928a817a706b605d554e463d32271b0f0300000000000000000000000000000000000000000000000000000000000000000a141e2c363e48505a626d727f8b919b9e97928a817a706b605d554e463d32271b0f0300000000000000000000000000000000000008141f2b37434e58606d78818d939a9fa69f9c9992908f8d8c8c8c8d8e9092989c9fa49f99938c81786d605a5043392e231804000000000000000000000000000009131b252d343a3e3f403f3b352e261c130a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b27333f4953606b74808d959fa8a69e959086807a7672706f6e6f6f7274797f869196a1a9a79d938a7e71665c504438291f14080000000005111d2935414c56606d79849198a2aaa69f959086807b767371706f70717275797e848e939da5afa89f948b7f72675d5145392c1e13080000000000000000000000000000000000000000000000000106090b0c1313131313131313120807050200000000000000000000000000000000000000000000000000000000000000000004090e1112131313131313130e0d0b0703000104070c10131316191b1c1e1f1f20201f1e1d1b181514120f0a0400000000000000000000000000000000000000000000020b141c242c323a41464d5254575f626567696b6c6c6c6c6b6a696765615f5754524d46423b332c241c140a020000000000000000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2b2a29272421201e1914120e0903000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2d2d1f1c18120b030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000106090b0c13131313131313131208070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f13151620202020202020171714110c0500000000000000000000000000000000071119202830353e454d545b606a6f79808a92979ea6aeb4aca3978a7d7064574a3d3124170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222c363e44494a5353535353504e4a433a31271c1105000000000000000000000000000000000000000000000000000000000009121b252d373f49515b636d737979797979797979746e64584c4033271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000020c1a242d363f48505a626d727f8b919ba29f938e857d746d6760584e43382c1f13070000000000000000000000000000000000000000000000000000000000000000020c1a242d363f48505a626d727f8b919ba29f938e857d746d6760584e43382c1f1307000000000000000000000000000000000000020f1b27323d44505c666d78808890959b9fa2a39f9d9b9a999999999b9d9fa2a29e9b948f877f776d665c50483e30271d120700000000000000000000000000000109131b23292e313233322f2a241c140a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222d38414f59606d788390959fa7a79f98928c86827f7d7c7b7b7c7e81858b9298a1a8a69f958e81746c61544a3f3428170d0200000000010d1925303a45515c676f7c869298a1a9a79f98928d8783807e7d7c7d7e7f82858b91969ea5afa7a0969082786c60554b4135291d0c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1d1f202020202020201a1a17130e070d1113181c1f20232527292a2b2c2c2c2c2b2a282522211f1a15100c0701000000000000000000000000000000000000010b141d262e363e444c52565e61666a6e717476777879797878777673716e6966615e57524d453e362e261c140a0000000000000000000000080f151a1d1f20202020202020202020202020202020202020202020202020201f1f1d1c1a171414110e0805020000000000000000000000000000000000000000080f151a1d1f20202020202020202013100c0701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070f161b1f22232d2d2d2d2d2d2d2423211c17100800000000000000000000000000000000070e161e2429333b424a505860676d747d858f949fa29f9f9f978a7d7064574a3d3124170a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c28333e4850555760606060605d5b554d43382d22160a00000000000000000000000000000000000000000000000000000000000009131b252d373f49515b63666c6c6c6c6c6c6c6c67645c53483c3024180b0000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242d363f48515b626d727f8c919ca39e97918a81796f6a6054483b2e22150900000000000000000000000000000000000000000000000000000000000000000008121b242d363f48515b626d727f8c919ca39e97918a81796f6a6054483b2e221509000000000000000000000000000000000000000a152028343f4a545c666c737c83898e9298989b9c9e9e9f9f9f9e9e9d9a9897928e89827c736c655c544a3f362c1e150b00000000000000000000000000000000010911181e2225252726231f19120a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111b262f3d45515c666d7a8390959fa4aaa29f98928f8c8a898888898b8e92979fa2aaa59e949083796d605a5042382e23170500000000000008131e2934404b555f6a707d8692979fa6aaa39f9993908d8b8a89898a8c8f92979da0a8aca59e9590847a6d665b50433a2f24180d00000000000000000000000000000000000000000000000000000000000000020608080b0e1011121313121211100d0b080705020000000000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2726231f1913181d2023282c2d2f323436373839393938383734322f2e2b261f1c18120b03000000000000000000000000000000000009131d262f38404850565e61686e73777b7e81838485868685858482807e7b77736e69615e57504840382e261c1309000000000000000000000004090e111213131313131313131313131313131313131313131313131313131212110f0d0b0807050200000000000000000000000000000000000000000000000004090e1112131313131313131313060400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407090a131313131313130a09070400000000000000000007101921272c2f303939393939393931302d28221a120800000000000000000000000000000000040c131921292f383f444e555d606b707a828b9298939393938a7d7064574a3d3124170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000814202d3944505a61646c6c6c6c6c6a665f554a3e32261a0d0000000000000000000000000000000000000000000000000000000000000109131b252e37404951575960606060606060605a58534a41362b201408000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d363f49515b626d727f8c9193939393938e847c6f6256493c2f2316090000000000000000000000000000000000000000000000000000000000000000000009121b242d363f49515b626d727f8c9193939393938e847c6f6256493c2f23160900000000000000000000000000000000000000040b17232e38424a545b606b6f767d8185898c8e9091929293929291908e8c8985817c766f6a605b534a42382e241a0c03000000000000000000000000000000000000070d121618191a1917130e0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d2834404b545e686d7a838d939a9fa7aaa29f9c989695959596989b9fa2a9a8a09e938e827a6d675d51483e30261c1106000000000000020c18232f39434e58606b707d858f949ea0a8aba49f9c9a9796969697989b9ea1a9aca7a09d938e837b6e685e544a3f31281d1307000000000000000000000000000000000000000000000000000000000205090e121415181b1d1e1f20201f1f1e1c1a181514120e09050200000000000000000000000000000000000008121b242b313638393939393939393433302b241d24292c2e34383a3c3f41424445454646454443413e3b3a37312c29231d150d0700000000000000000000000000000007101b252f38404a525a61686d747b8084888b8e8f919292929291918f8d8b8884807b746e69615a524a40382e251b0f0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b1014161720202020202020171614100b05000000000000040f19232b32383b3c464646464646463e3c39332c241a10050000000000000000000000000000000002080f171d262d333c434b515961686d757e858686868686867d7064574a3d3124170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1623303c4955616c7079797979797671665b4e4236291c1000000000000000000000000000000000000000000000000000000000000000010a131c252e3740464b4c53535353535353534e4c4841382f251a0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d373f49515b636d737f86868686868686868174675a4e4134271b0e010000000000000000000000000000000000000000000000000000000000000000000009121b242d373f49515b636d737f86868686868686868174675a4e4134271b0e010000000000000000000000000000000000000006111c263038424a505960636b7075797c7f81838485858685858483817f7c79746f6b6260585049413830261c120900000000000000000000000000000000000000000106090b0c0d0c0a0702000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b18232e39424c565e686d79808790959b9fa2aaa8a5a3a2a1a2a2a5a7aba49f9c96918981796d685d554b40362c1e150a000000000000000007121d27313c464f59606a6f7b828a91969c9fa3aba8a6a4a3a2a3a4a5a8a8aaa29f9b95908981796e695e564c42382d1f160c01000000000000000000000000000000000000000000000000000002080e11151a1e21222528292b2c2c2c2c2b2b29272522211e1a14120e0902000000000000000000000000000000040f19242d353d424546464646464646413f3c362f282f35393a404546494c4e4f51525253535251504e4b4847433c38342f271f19100a01000000000000000000000000030c19222d37404a525c636c717a81868c9196989a9c9e9f9f9f9f9e9d9c9a9895918d86817b716c645c524a40372d21180e030000000000000000000000020507081313131313131313131313131313131313131313131313131313131313131211100c09060503000000000000000000000000000000000000000000000000000000000000020507080b0e111112131312110f0c0908060300000000000000000406070b0f1213131211100e0c0b0906010000000000000000000000000000000000000000000000010406070a0d10111213131312100e0b070705010000000000000000000000000000000000000000000810161c2023232d2d2d2d2d2d2d2323201c16100800000000000a16212b353d434849535353535353534a49453e362c22170c000000000000000000000000000000000000050b141c2228313940454f565e616d7279797979797979706c6155493c3023160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d868686868683766a5d5043372a1d100000000000000000000000000000000000000000000000000000000000000000010a131c252e353b3e40464646464646464641403c362f261d1308000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b252d373f49515b636d737979797979797979746e64584c4033271a0d01000000000000000000000000000000000000000000000000000000000000000000000009121b252d373f49515b636d737979797979797979746e64584c4033271a0d0100000000000000000000000000000000000000000a141e262f383f444f54596063666d6f72747677787979797877767472706d66636059544e443f382f261e140a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d27303a444c565e676d747c83898e9298999b9d9e9f9f9f9e9d9c9999938f8a847d756d675d564c433a2f241a0c030000000000000000010b151f2a343d474f5860696e767e848a8f9299999b9d9e9f9f9f9f9e9d9b9998928e89837d756d675e564d443a2f261c0d040000000000000000000000000000000000000000000000000002080d14191e20262b2e2f323436383939393938373634322e2d2b26201e1a140e0902000000000000000000000000000915202b353f474e52535353535353534d4c474038313a4045474b515356585a5c5d5e5f5f5f5f5e5d5b5855534e47454039312b221b130a0000000000000000000000000a151e2b343f49525c646e737e858d92999da0a8a9a29f9d9c9b9c9d9fa2aaa7a09d99928e857e736e645c52493f332a1f140900000000000000000002080e1114142020202020202020202020202020202020202020202020202020202020201f1e1c191613120f0b06000000000000000000000000000000000000000000000000000003090e121415181b1d1e1f201f1f1d1b191515120f0a0401000000070c101313181c1e1f201f1e1d1b181815120d06000000000000000000000000000000000000000001070d111314171a1c1e1e1f201f1e1d1b181413110d080200000000000000000000000000000000000008111a21272c2f3039393939393939302f2c27211a1108000000030f1b27323d474f545660606060606060575550483e33281c1104000000000000000000000000000000000000020a11171f272f353e444c525b62656c6c6c6c6c6c6c64615a5044392d20140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a9393939083766a5d5043372a1d10000000000000000000000000000000000000000000000000000000000000000000010a131c232a2f323339393939393939393433302b251d140b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131b252d373f49515b63666c6c6c6c6c6c6c6c67645c53483c3024180b0000000000000000000000000000000000000000000000000000000000000000000000000009131b252d373f49515b63666c6c6c6c6c6c6c6c67645c53483c3024180b000000000000000000000000000000000000000000020c141d262d333d43484f54545c60636568696b6b6c6c6c6b6b6a676563605c54544f47433d332d261d140c020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151e28323a444c555c606b6f767c8185898c8e909192929291908f8d8a86827d79706b605d554c443a31281d120800000000000000000000030d18222b353d464e575e616c71787d82868a8c8f90919293929291908e8c8985817d77706b605d554d443b32281d140a00000000000000000000000000000000000000000000000000040c13191f252a2d31373a3b3e41434445464645454443403e3b3a37312d2a251f1a140d050000000000000000000000000e1a26313d4751595e5f6060606060605a58524a403a434b5153545c60626567696a6b6c6c6c6b6b6a6765625f5853514b433d342d251b12090000000000000000000006111c26303d46515b646e74808a92979fa3a9a19e999792908f8f8f909298989d9fa7a39f97928a80736e635b51453b31261a0e0400000000000000050d14191e20212d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2c2b292623201f1b17110c0600000000000000000000000000000000000000000000040a0f141a1e212125282a2b2c2c2c2b2a282622211f1b15110d08030b12181c1f2025292b2c2c2c2b2a272524221d1811090100000000000000000000000000000000040a0f13181d20202326292a2b2c2c2c2b2a272521201e1913100b0500000000000000000000000000000005101a232c33383c3d464646464646463d3c38332c231a1005000007131f2c38434f5960636c6c6c6c6c6c6c64615a5045392d2114080000000000000000000000000000000000000000060d151d2429323a41465156585f606060606060575550483e33281c100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a979f9d9083766a5d5043372a1d1000000000000000000000000000000000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d272724201a130b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000109131b252e37404951575960606060606060605a58534a41362b201408000000000000000000000000000000000000000000000000000000000000000000000000000109131b252e37404951575960606060606060605a58534a41362b20140800000000000000000000000000000000000000000000020b141c222832383d44484a515356595b5d5e5f5f605f5f5e5d5b595653504a48443d383227221b140b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c162028323a434b515960636b6f75797d7f828385858685858482807d7a76716d666059514b433a32281f160c000000000000000000000000061019232b343d454d525a61666c70757a7d80828385858686858483817f7c7975706b636059514b433b322920160b02000000000000000000000000000000000000000000000000080e161e25293036393c4247484b4e50515253535252514f4d4b4846423c3a36302a251f170f080000000000000000000000111d2a36424e59636a6c6c6c6c6c6c6c67645c5247404b555d6064666d6f727475777878797978777674716e6a64605c554e463f372d251b11070000000000000000000c17232e38424f59626d74808d929ea1a9a39f97918c8885838282838385888b90959ea1a8a29f928d80736d62574d42362a20160a000000000000050e171e252a2d2e39393939393939393939393939393939393939393939393939393939393938373633302d2b27221b17110a0300000000000000000000000000000000000000060c161b1f252a2d2e31343738393939383735322f2e2b26201d19130c151d23282c2d32353839393838363432312e29231b1309000000000000000000000000000002080d151b1d24292c2d3033363738393939383634312e2d2a251e1c160f0a04000000000000000000000000000b16212c353d44484a535353535353534a48443d352c21160b00000915222f3b4854606b6f79797979797979716c6155493c3023170a000000000000000000000000000000000000000000030b1218202930363f454a4b525353535353534a49443e362c22170b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a39d9083766a5d5043372a1d10000000000000000000000000000000000000000000000000000000000000000000000000070d1216191920202020202020201b1a18140f0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e3740464b4c53535353535353534e4c4841382f251a0f030000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e3740464b4c53535353535353534e4c4841382f251a0f030000000000000000000000000000000000000000000000020a111721272c333839404446494c4e5051525253525251504e4c4946443f3838322b272017110a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e162028313940454f54596063676d707375777879797978777673716e6864605c544f454039312820160d0400000000000000000000000000071119222b333b424650545b6064676d707375777879797978787675726f6d67636059544f45403a312920170e050000000000000000000000000000000000000000000000020a121a202830353b4146474e5355585b5c5e5f5f5f5f5e5e5c5a5855534d4846423b363029211a120a02000000000000000000121f2c3845525e6a7579797979797979746e64584c45515d676d7176797c7f81828485858686858483817e7b77716d67605851493f372d23190b020000000000000003101c28343f4a54606b727f8c929ca4aaa299928c84807b787675757677797b7f838a91969fa6a49c928b7f72695f53463d32271b0f0300000000020d1720293036393b4646464646464646464646464646464646464646464646464646464646464544433f3c3937332d28231c150c0500000000000000000000000000000000030a111720272b31363a3b3e4144444546464544423f3c3b37322c29241e191e272e34383a3e42454646454443413f3d3a342d251b1106000000000000000000000000050d131920262b2f35393a3d404344454646464543413e3a3936302c28211b150e06000000000000000000000004101c27333d474f55566060606060606056554f473d33271c100400091623303c4956636f7d868686868686867e7164574a3e3124170b0000000000000000000000000000000000000000000001070e171e252a343a3d3f464646464646463d3c39332c231a10050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a39d9083766a5d5043372a1d100000000000000000000000000000000000000000000000000000000000000000000000000002060a0c0d13131313131313130e0d0b0803000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e353b3e40464646464646464641403c362f261d130800000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e353b3e40464646464646464641403c362f261d13080000000000000000000000000000000000000000000000000000060b161b21272c2e34383a3c3f41434445464646454443413f3d3a38342e2c27211b160b06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e161f272f343d43484f54555c606366686a6b6c6c6c6b6a696664615e5653514a423d352f271f160d04000000000000000000000000000000071019202930363e424a5053555d606366686a6b6c6c6c6c6b6a686663605c55554f48443d352f281f170e050000000000000000000000000000000000000000000000020b141c242c323a41464d5254575f626567696b6c6c6c6c6b6a696765615f5754524d46423b332c241c140a02000000000000000013202c3946535f6c79878686868686868074675a4d4753606d797e8286898b8d8f90919292929291908e8b88837e796f6a625b51493f352b1d140a0000000000000006121f2c3844505c666f7c87929fa4aba29892878079736f6a6a696869656c6e72777d848f949fa6a49f92867b6e61584e43382b1f13060000000008141e29323b41465353535353535353535353535353535353535353535353535353535353535352514f4c4946443f38342e261e170f070000000000000000000000000000030c151c232832373b4246484b4e505152535252504e4c4847433c39352f28222b30394045464b4f5152535251504e4b4a463f372d23180d0100000000000000000000080e171e252a31373a4045474a4d4f515152535251504e4b4746413a38332b2620181009000000000000000000000714202c38444f5961636c6c6c6c6c6c6c6361594f44382c20140700091623303c4956636f7c8993939393938a7d7164574a3e3124170b000000000000000000000000000000000000000000000000050d131923292e31323939393939393931302d28221a1108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a39d9083766a5d5043372a1d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c232a2f323339393939393939393433302b251d140b010000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c232a2f323339393939393939393433302b251d140b01000000000000000000000000000000000000000000000000000000040a0f161c1c23282c2d3032353638383939393838373432302d2c28231c1b160f0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d151d232932383d44484b515356595b5d5e5f5f5f5e5d5c5a5754524d464440393029241d150d040000000000000000000000000000000000070e171f252a2f383f44464b515457595c5d5e5f605f5f5e5d5b595653514b48443d383329241d160d050000000000000000000000000000000000000000000000010b141d262e363e444c52565e61666a6e717476777879797878777673716e6966615e57524d453e362e261c140a000000000000000013202c3946535f6c798692939393938d8074675a4d4f5c6875828b8f9298989a9c9d9e9f9f9f9e9e9d9a9895908b847c726d625b51473d2f261c1106000000000003101c28343f4a54606d78839099a3afa39992867d736d67625f585c5c535b6061656c707a828f949fa9a2988f82766a6054473b2e221508000000020e1925303b444c525f60606060606060606060606060606060606060606060606060606060605f5f5e5c5956535049443f38302921191007000000000000000000000000030d151e262e343d43474d5354585b5d5e5f5f5f5e5d5b5955534e4745413a3129343c424b5153585c5e5f5f5f5e5d5a585651493f34291d120600000000000000000008111a202930363c43474b515356595c5d5e5f5f5f5e5d5a5854524c48443e37312a221b120a0100000000000000000916232f3c4855616b7079797979797979706b6155483c2f23160900091623303c4956636f7c89969f9f9f978a7d7164574a3e3124170b0000000000000000000000000000000000000000000000000002080d181d2224252c2d2d2d2d2d2d2423201c17100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a39d9083766a5d5043372a1d100000000000000000000000000000000000000000000000000000000000060a0e1011121313131212100e0b0707050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d272724201a130b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d272724201a130b02000000000000000000000000000000000000000000000000000000000000050b1012181c1f202326282a2b2c2c2d2c2c2b2a282623201f1c17110f0b040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b121821272c3238394045464a4c4f505252535252514f4d4a4746413b38342e271e18120b0300000000000000000000000000000000000000050d141a1d262d33383a4145474a4d4f50525253535251504e4c494645403938332c272118130c0400000000000000000000000000000000000000000000000009131d262f38404850565e61686e73777b7e81838485868685858482807e7b77736e69615e57504840382e261c13090000000000000013202c3946535f6c7986929f9f9f9a8d8074675a4d4f5c6975828f9c9fa3aaa7a7a4a2a1a1a0a1a3a6a7a79f9d9691877f726d62594f42382d22170b000000000006121f2c3844505c66727f8b95a0aba89f92877d706b605d55534e4f4f495053555a61686d79829097a1a49f94897c6f6256493c2f23160900000005111e2a36414c565e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6a696663605b53504a423b332b23190f0600000000000000000000010b151f2730383f444e54575e6164676a6b6c6c6c6b6a6865625f5854524c433f353c464e545c6065686b6c6c6b6b696765625b51463a2e221509000000000000000008121a232c323a41464e53555d606366696a6b6c6c6c6b696764615e56554f47433c342d241c130a01000000000000000a1723303d4a5663707d868686868686867d7063564a3d3023170a00091623303c4956636f7c8996a2aca4978a7d7164574a3e3124170b000000000000000000000000000000000000000000000000000000060c111517181f202020202020171614100b050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a39d9083766a5d5043372a1d10000000000000000000000000000000000000000000000000000000040b11161a1d1e1f2020201f1e1d1b181413110d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d1216191920202020202020201b1a18140f080100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d1216191920202020202020201b1a18140f080100000000000000000000000000000000000000000000000000000000000000000000070c10121316191b1d1e1f1f201f1f1e1d1b19161312100c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c161b21272c2e34383a3d40424445464646454443403e3b3936302c28231c150c070100000000000000000000000000000000000000000002090b141c22282b2f35393a3d40424445464646454543423f3c3a38342e2c27211c160d070100000000000000000000000000000000000000000000000007101b252f38404a525a61686d747b8084888b8e8f919292929291918f8d8b8884807b746e69615a524a40382e251b0f0600000000000013202c3946535f6c7986929faca79a8d8074675a4d4f5c6976828f9caaa29f9c9a97969594939496999ea0a8a8a099928b7f726b60544a3f33281c0f03000000000713202d3a4653606d7984919ea7ada1968d80736b6059514b474342423f44464850565d676d7a85929b9993908c8275685c4f4235291c0f0200000714202d3946525e6876797979797979797979797979797979797979797979797979797979797979787776726f6c65605c544d453d352b22180d0300000000000000000007121d273139424a50586062696e71747777787979787775726f6a66605d56504540454e5860666d717578797978777674726d62564a3d3124180b0000000000000008111a242c353e444c52585f62676d7073767778797979787674716d68636159534e463f362e251c1309000000000000000a1723303d4a5663707d899393939393897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000000000000000000000000000000000000000000000000000000000105090b0c131313131313130a0a080400000000000000000000000000000000000000000000000000000002050708080808080808080808080808080808080808080808080808080a1724313d4a5764707d8a97a39d9083766a5d5043372a1d100000000000000000000000000000000000000000000000000000050e161c2227292a2c2c2d2c2c2b29282521201d19130f0a0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002060a0c0d13131313131313130e0d0b08030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002060a0c0d13131313131313130e0d0b08030000000000000000000000000000000000000000000000000000000000000000000000000000040607090c0e1011121313131211100e0c0a07060300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f161b1d23282c2d303335373839393938373633312e2d2a251f1c18120b0300000000000000000000000000000000000000000000000000020a11171c1f24292c2d30333537383939393938373533302d2c28231d1c16100b0500000000000000000000000000000000000000000000000000030c19222d37404a525c636c717a81868c9196989a9c9e9f9f9f9f9e9d9c9a9895918d86817b716c645c524a40372d21180e03000000000013202c3946535f6c7986929faca79a8d8074675a4d4f5c6976828f9c9a9892908d8b8988878787898c91969fa2aaa39f93877d70665b5044382b1f120700000004101d2935404b5564717d8a96a1acaa9e9184796d60594f45403937312d3337393e444c555e68717e8b8e8a86837f7c6f6255483c2f2215090000000814212e3b4754616e7a8686868686868686868686868686868686868686868686868686868686868584827f7c78716d665e574f473d342a1f150b0100000000000000020c18242f39434b545c606a6f757b7e8183848586858583817f7c78726d68625a514b4d57606a6f797e82848586858483817f7265584b3f3225180c000000000000050f1a232c363e474f565e616a6f747a7d808284848586858483817e7a76706b625f58514840372e251b11070000000000000a1723303d4a5663707d89969f9f9f96897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090e11141415151515151515151515151515151515151515151515151515151724313d4a5764707d8a97a39d9083766a5d5043372a1d1000000000000000000000000000000000000000000000000000040e1720272e3336373939393939383634312e2d2a251e1a150e060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b0f12181c1f202326282a2b2c2c2c2b2a29272421201e1914100c070000000000000000000000000000000000000000000000000000000000060b0f13181d20212426292a2b2c2d2c2c2b2a282623201f1c1812100b050000000000000000000000000000000000000000000000000000000a151e2b343f49525c646e737e858d92999da0a8a9a29f9d9c9b9c9d9fa2aaa7a09d99928e857e736e645c52493f332a1f1409000000000013202c3946535f6c7986929faca79a8d8074675a4d505c6976838f918d898583807e7c7b7a7a7b7d7f848b9298a2aba4999083786c605346392e23180c0000000613202c3945515d6775828f9ba8aea3988b7e71675d51473d352f2b2622272b2d323a434c56606d7883817e7a76736f6a5f53473b2e2115080000000814212e3b4754616e7a87939393939393939393939393939393939393939393939393939393999292918f8c89837e786e6960594f463c31271d1207000000000000000a141e2935404b555d666d747c82878b8e909192929291908e8c88847f7a716d605d55535f696f7c848b8f9192929291908d86796c605346392d20130000000000020d17212c353e48505961686d757c8186898c8f909192929291908d8b86827d766f6a625b524940372d23190d0300000000000a1723303d4a5663707d8996a3aca396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000000000000000000000000000000000000010507080b0e10111213131211100e0b0807050100000000000000000000000000000000000000000000000000000000050d14191e202121212121212121212121212121212121212121212121212121212124313d4a5764707d8a97a39d9083766a5d5043372a1d10000000000000000000000000000000000000000000000000000b16202932393f434445464646454543413e3a3936302b2620180f0900000000000000000000000000000000000000000000000000000004090e1112131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130b0a0804000000000000000000000004090e1112131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130b0a0804000000000000000000000000000000000000000000040613131313131313131312110e090400000000000000000000000000000000000000000000000000000000020507080b0e111112131312110f0c0908060300000000000000000406070b0f1213131211100e0c0b0906010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c10131317191c1d1f1f201f1f1e1c1a171414110e080400000000000000000000000000000000000000000000000000000000000000000003070d111314171a1c1d1f1f20201f1e1d1b19161313100c07000000000000000000000000000000000000000000000000000000000006111c26303d46515b646e74808a92979fa3a9a19e999792908f8f8f909298989d9fa7a39f97928a80736e635b51453b31261a0e040000000013202c3946535f6c7986929faca79a8d8074675a4d505c6976838a85807c797674716f6e6e6d6e7073787e869299a3aba0958a7e7164544b4034281c100400000714202d3a4753606d7a86929facac9f92867a6d60554b403529241d1a171b1f2028313a44515c666d7775716d6866625f584e43372b1f12060000000814212e3b4754616e7a87949f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa39f9e9d9c9995908b837b6f6b60584e43392f23180c02000000000006111c26303845515d676d7880898f93999a9d9e9f9f9f9e9d9b9896918c857e756d675d58626e7b8691969b9e9f9f9e9e9c9386796c605346392d2013000000000009141f29333d47505a616b707a82888e9298999c9d9e9f9f9f9e9c9a99938f8a837c726d635c52493f352b1f150b01000000000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000000000000000000000000000000000003080d111414171a1c1e1f20201f1e1d1a171414110d080300000000000000000000000000000000000000000000000000050e171f252a2d2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e313d4a5764707d8a97a39d9083766a5d5043372a1d1000000000000000000000000000000000000000000000000006111c27323b434a4f51525353535251504e4b4746413a37312a221b120900000000000000000000000000000000000000000000000000080f151a1d1f20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020171714110c050000000000000000080f151a1d1f20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020171714110c050000000000000000000000000000000001070c10132020202020202020201f1d1a150f080000000000000000000000000000000000000000000000000003090e121415181b1d1e1f201f1f1d1b191515120f0a0401000000070c101313181c1e1f201f1e1d1b181815120d060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000406070a0d0f11121313131211100d0b0807050200000000000000000000000000000000000000000000000000000000000000000000000000010406070a0d0f11121313131212100f0c09070604000000000000000000000000000000000000000000000000000000000000000c17232e38424f59626d74808d929ea1a9a39f97918c8885838282838385888b90959ea1a8a29f928d80736d62574d42362a20160a0000000013202c3946535f6c7986929faca79a8d8074675a4d4e5a6774807d7974706d666764636261606163656c727d87929faca79b8f8275665c5145382c1f130600000a1723303d4a5663707d8998a3aea89b8e8275675d51433a2f23181d1d1d1d1d161f2834404a545c606a6864615e5655534e463c32261b0f030000000814212e3b4754616e7a8794a1acacb4aeaca6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a6a8aaa9a7a09d9590857d6f6a5f554b4034291e130800000000000b17232e3842505a606d79828d929b9fa4ababa39f9d9c9b9c9d9fa19e97928b82796d685f6a76828f98a1a8aaa39f9995949386796c605346392d201300000000020e1a25303b454f59616c717d858f939a9fa3aaa9aaa8a7a6a7a9a9aba49f9c9490867f736e635b51473d31271d1207000000000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000000000000000000000000000000060b1014191e20212427292b2c2c2c2c2b2a272421201e19140f0b0600000000000000000000000000000000000000000000020d17202930363a3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3d4a5764707d8a97a39d9083766a5d5043372a1d100000000000000000000000000000000000000000000000000a16222e39434d555b5d5f5f605f5f5e5c5b5854524c47433c342d241b1108000000000000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c17100800000000000009121920262a2c2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c1710080000000000000000000000000000030b12181c1f2d2d2d2d2d2d2d2d2c2c2a262019120900000000000000000000000000000000000000000000040a0f141a1e212125282a2b2c2c2c2b2a282622211f1b15110d08030b12181c1f2025292b2c2c2c2b2a272524221d181109010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54606b727f8c929ca4aaa299928c84807b787675757677797b7f838a91969fa6a49c928b7f72695f53463d32271b0f0300000013202c3946535f6c7986929faca79a8d8074675a4d4c58646e74716d6663605c54585655545454535b606b74818d9aa9ac9f9285796d6053463a2d20130700000d1a2733404d5a6673808d99aab4aa978b7e7164554c4131282a2a2a2a2a2a2a2a2a232e39424a51535d5b5754524c4847433c342a20150a000000000814212e3b4754616e7a8794a7afb4aba39f9a9898989898989898989898989898989898989898999b9ea1a9aca79f9792857c6e675c51453a3025190d0100000003101c28343f4a54616c74818e949da4aca7a09d9992908f8f8f9192999a9e9f948f837a6d666f7c88949faaaea398928c88878886796c605346392d20130000000005121e2a36424d57606b717e8791979ea5acaba9a19e9b9a9a9b9d9fa4abaca69f98928b80736d62594f43392f23180c000000000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000000000000000000000000020a11171c1f252a2d2e3134363839393938373634312e2d2a251f1b17110a02000000000000000000000000000000000000000009141f29323b4246474848484848484848484848484848484848484848484848484848484848484a5764707d8a97a39d9083766a5d5043372a1d100000000000000000000000000000000000000000000000020e1a27333f4a555f676a6c6c6c6c6c6b696764615e56534e463e362d23190b0200000000000000000000000000000000000000000008121b242b3136383939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393931302d28221a12080000000008121b242b3136383939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393931302d28221a1208000000000000000000000000030d151d23292c3939393939393939393836312b241b12080000000000000000000000000000000000000000060c161b1f252a2d2e31343738393939383735322f2e2b26201d19130c151d23282c2d32353839393838363432312e29231b13090000000000000000000000000000000000020507080b0e111112131312110f0c0908060300000000000000000406070b0f1213131211100e0c0b09060100000000000000000000000000000000000000050a0d0f101313100f0d0a050000000000000000000000000000000000000000000000000000000000000000060a0e1011121313131212100e0b0707050100000000000000000000000000000000000000000000000006121f2c3844505c666f7c87929fa4aba29892878079736f6a6a696869656c6e72777d848f949fa6a49f92867b6e61584e43382b1f130600000013202c3946535f6c7986929faca79a8d8074675a4d47525c646764605c5453514b4b4948474748495059626e7b8897a1ada298887c6f6255493c2f2216090004101c2834404b546976828f9ca9aea398887b6f6255483c2f3737373737373737373737373039404446514e4b4746413c3b37322a261f180f060000000814212e3b4754616e7a87959fa3aba399928d8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8c8c8f92979ea1a9a9a2979184796d60564c41362a1d110500000006121f2b3844505c66717e8b939ea6aea59d95908a86838282838486898d92979f959083786d73808d99a6b0a89f9286807c7a7b7d7063574a3d3024170a000000030e18212d3a46525e69707d879299a1a9ada79f9d97928f8d8d8e9093999fa2aaaaa39f928b7f726b60554b4034291c12070000000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000000000000000000000001070c141c23282b3036393b3e414344454646454443413e3b3936302b27221b140b07000000000000000000000000000000000000020e1925303b444d5254545454545454545454545454545454545454545454545454545454545454545764707d8a97a39d9083766a5d5043372a1d10000000000000000000000000000000000000000000000003101d2936434f5b6771777879797978787674716d68625f5850483e352b1d140a0000000000000000000000000000000000000000040f19242d353d4245464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646463e3c39332c241a10050000040f19242d353d4245464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646463e3c39332c241a100500000000000000000000010b151f272f343846464646464646464645423d352d24190f040000000000000000000000000000000000030a111720272b31363a3b3e4144444546464544423f3c3b37322c29241e191e272e34383a3e42454646454443413f3d3a342d251b1106000000000000000000000000000003090e121415181b1d1e1f201f1f1d1b191515120f0a0401000000070c101313181c1e1f201f1e1d1b181815120d0600000000000000000000000000000000030a11161a1c1d20201d1c1a16110a0300000000000000000000000000000000000000000000000000000000040b11161a1d1e1f2020201f1e1d1b181413110d080200000000000000000000000000000000000000000003101c28343f4a54606d78839099a3afa39992867d736d67625f585c5c535b6061656c707a828f949fa9a2988f82766a6054473b2e22150800000013202c3946535f6c7986929faca79a8d8074675a4d414a52585a5753504a4645403e3c3b3b3a3b3f47535f6a7885929eabaa968a7d7063574a3d3024170a0006131f2c3845515c667884919eabac9f9286796d6053464444444444444444444444444444444444444444444444444444443b3a36312a21180e0300000714202d3a4753606d79838c9299a29f9286807f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f8082858a91969fa7a9a0968c7f73685e5246392d2013080000000713202d3a4653606d7884919ea5afa69d938e837d797776757677797c80858c9298958e81747683909ca9aca0958a7e736f6e6e706b6155483c2f2316090000000915202c38444f59616e7b869299a3abada49c959089858281808183878c9298a0a8aea49f93877d6f675c5145392e23180c0000000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000000000000000000030b12181e262e34383b4146474a4d4f515253535251504d4a4746413b37332d261d18120b030000000000000000000000000000000005111e2a36424d565e61616161616161616161616161616161616161616161616161616161616161616164707d8a97a39d9083766a5d5043372a1d10000000000000000000000000000000000000000000000004111e2a3744515d6a778385868686858483817e7a756e6a615a50473d2f261b1106000000000000000000000000000000000000000915202b353f474e52535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534a49453e362c22170c00000915202b353f474e52535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534a49453e362c22170c0000000000000000000007121d2731394045535353535353535353524e473f352b20150900000000000000000000000000000000030c151c232832373b4246484b4e505152535252504e4c4847433c39352f28222b30394045464b4f5152535251504e4b4a463f372d23180d010000000000000000000000040a0f141a1e212125282a2b2c2c2c2b2a282622211f1b15110d08030b12181c1f2025292b2c2c2c2b2a272524221d1811090100000000000000000000000000040d151c2226292a2d2d2a2926221c150d040000000000000000000000000000000000000000000000000000050e161c2227292a2c2c2d2c2c2b29282521201d19130f0a030000000000000000000000000000000000000006121f2c3844505c66727f8b95a0aba89f92877d706b605d55534e4f4f495053555a61686d79829097a1a49f94897c6f6256493c2f23160900000013202c3946535f6c7986929faca79a8d8074675a4d4141474c4e4a46443f3a38342e302f2e2d2d37434e586a7784909daaa4978b7e7164584b3e3125180b000713202d3a4653606d7986939facaa9d908477665c50505050505050505050505050505050505050505050505050505050504846423b332a1f140900000613202c3945515d676d787f879297a29992867e727272727272727272727272727272727272727375797e8490959fa9a89f92867a6d6154473a2f24190d0100000b1824313e4b5764717e8a96a0acac9f948e8179716d67696869676d70747a7f869095938a7e7885929fabaa9d9184776c6261616361594f44382c2014070000020f1a26313c4855616b75828f98a2abada39b928c837d7975747374767a7f869196a0a8afa4999184796d60544a4034281c100400000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000000000000000000050d151d242930383f44464c5254575a5c5e5f5f5f5f5e5d5a5754524c46443f382f28231c150c030000000000000000000000000000000714202d3a46525e696e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e707d8a97a39d9083766a5d5043372a1d10000000000000000000000000000000000000000000000006121f2c3945525f6c78859292999292918f8e8b87827c716c61594f41382d22170b000000000000000000000000000000000000000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060575550483e33281c1104000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060575550483e33281c11040000000000000000000c18232f39434b515f606060606060605f5e5951473d31261a0e010000000000000000000000000000030d151e262e343d43474d5354585b5d5e5f5f5f5e5d5b5955534e4745413a3129343c424b5153585c5e5f5f5f5e5d5a585651493f34291d120600000000000000000000060c161b1f252a2d2e31343738393939383735322f2e2b26201d19130c151d23282c2d32353839393838363432312e29231b1309000000000000000000000000030d161f272d32353639393635322d271f160d03000000000000000000000000000000000000000000000000040e1720272e3336373939393939383634312e2d2a251e1a150e060000000000000000000000000000000000000713202d3a4653606d7984919ea7ada1968d80736b6059514b474342423f44464850565d676d7a85929b9993908c8275685c4f4235291c0f02000013202c3946535f6c7986929faca79a8d8074675a4d41363c3f413e3a38342e2c2823232221212c3844505c667784919daaa5988b7f7265584b3f3225180c000815212e3b4854616e7b879aa4afa99c90837669545d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d55534d453b31261a0e020004101d2935404b555d666d727d859298a29892877f716b6565656565656565656565656565656566666d717a839097a1ada2988b7f7265564c4135291d11040005121e2a36424d576875818e9ba8afa49a8f82786d66605d555c555c6063676d727b838f9391857b8797a2ada79a8d8074675a545557554f473e33281c1004000006121f2b37434e5863707d8a939eaaafa59b918b8078706c66676768686d737b849196a0acaba0968c7f72665c5144382c1f120600000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000000000000000000050e161f272f353e424a5053565e616467696b6c6c6c6b6a696764615e56535049413d342e271e150c0300000000000000000000000000000814212e3b4754616e7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7f8b98a49d9083766a5d5043372a1d10000000000000000000000000000000000000000000000006121f2c3945525f6c7885929493939496999a99938e867e716b6053493f33271b0f03000000000000000000000000000000000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d21140800111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d211408000000000000000004101c2934404b555c6c6c6c6c6c6c6c6c6c6a63594e42362a1d110400000000000000000000000000010b151f2730383f444e54575e6164676a6b6c6c6c6b6a6865625f5854524c433f353c464e545c6065686b6c6c6b6b696765625b51463a2e2215090000000000000000030a111720272b31363a3b3e4144444546464544423f3c3b37322c29241e191e272e34383a3e42454646454443413f3d3a342d251b110600000000000000000000000a151f2831383e4243464643423e3831281f150a0000000000000000000000000000000000000000000000000b16202932393f434445464646454543413e3a3936302b2620180f090000000000000000000000000000000004101d2935404b5564717d8a96a1acaa9e9184796d60594f45403937312d3337393e444c555e68717e8b8e8a86837f7c6f6255483c2f22150900000013202c3946535f6c7986929faca79a8d8074675a4d4134303334312d2c28231f1c18161e2429363e4653606d7985929facab978a7e7164574b3e3124180b000916232f3c4956626f7c8995acb6a89c8f82756a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a615f574d42362a1e120500010d18242f39434b545c606b707d86929fa29992877d70675d5858585858585858585858585859545c60686d7a85919ea9aa9c908376685d5245392c201306000714202d3a46525e697885919eabac9f93877c6f665c54514b4f4b5153555d60696e79818f949083909da9b3a4988b7e7165584b484a48443e352c21160b0000000814212e3a47535f6a7683909ca5afa99e938b7f736c65605b545a565e61696e7a84919aa4afa89e9285796d6053463a2d22170b00000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000000000000040d162028313940454f545c6064686e7174767778797978777674716e6863605b534e44403930271e150c0300000000000000000000000000111e2a3744515d6a7784878787878787878787878787878787878787878787878787878787878787878787878b919ba99d9083766a5d5043372a1d10000000000000000000000000000000000000000000000006121f2c3945525f6c78858887868787898d92979f9892887d70655b5044372b1f1205000000000000000000000000000000000000121f2c3845525e6a7579797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979716c6155493c3023170a00121f2c3845525e6a7579797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979716c6155493c3023170a000000000000000006131f2c3845515c67767979797979797979756a5e5245382c1f12060000000000000000000000000007121d273139424a50586062696e71747777787979787775726f6a66605d56504540454e5860666d717578797978777674726d62564a3d3124180b00000000000000030c151c232832373b4246484b4e505152535252504e4c4847433c39352f28222b30394045464b4f5152535251504e4b4a463f372d23180d0100000000000000000005111c27313a434a4e505353504e4a433a31271c11050000000000000000000000000000000000000000000006111c27323b434a4f51525353535251504e4b4746413a37312a221b12090000000000000000000000000000000613202c3945515d6775828f9ba8aea3988b7e71675d51473d352f2b2622272b2d323a434c56606d7883817e7a76736f6a5f53473b2e21150800000013202c3946535f6c7986929faca79a8d8074675a4d413427262724201f1c1713141920282f353f48515b63707d8998a2aea399897c6f6356493c30231609000a1623303d495663707c8996a3afa89b8e8177777777777777777777777777777777777777777777777777777777777777776e695f53463a2d211407000007121d283139424a5059606b717e8b949fa39991857a6d60564c4c4c4c4c4c4c4c4c4c4c4c4c4a51565e68717e8b97a1a69f94877a6d6054473a2d211407000815212e3b4854616e7b8797a1adaa9d9083776a5f544b4540424045474b51575f676d78828f9590959fabb0a3968a7d7063574a3d3d3c38332c231a10050000000815222f3b4855626e7b88949fabada2978e81746d605b53504a4d4c52575e68707d87939facada1978a7d716453493f33271b0f03000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000000000000010c161f28323a434b515961666d71767a7e808284858686858483807d7a76706c656058514a423930271e150a00000000000000000000000000111e2a3744515d6a778490949494949494949494949494949494949494949494949494949494949494949494989ba3a99d9083766a5d5043372a1d100000000000000000000000000000000000000000000000000916232f3c4956626f7c7b7a7a7a7b7d808590959f9a9184786c605346392d20130600000000000000000000000000000000000013202c3946535f6c79878686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867e7164574a3e3124170b0013202c3946535f6c79878686868686868686868686868686868686868686868686868686868686868686868686868686868686868686867e7164574a3e3124170b00000000000000000714202d3a4753606d798686868686868687796c5f5346392c201306000000000000000000000000020c18242f39434b545c606a6f757b7e8183848586858583817f7c78726d68625a514b4d57606a6f797e82848586858483817f7265584b3f3225180c000000000000030d151e262e343d43474d5354585b5d5e5f5f5f5e5d5b5955534e4745413a3129343c424b5153585c5e5f5f5f5e5d5a585651493f34291d12060000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a000000000000000000000000000000000000000000000a16222e39434d555b5d5f5f605f5f5e5c5b5854524c47433c342d241b110800000000000000000000000000000714202d3a4753606d7a86929facac9f92867a6d60554b403529241d1a171b1f2028313a44515c666d7775716d6866625f584e43372b1f120600000013202c3946535f6c7986929faca79a8d8074675a4d4134271a1b171312100e171f252a323a4145515a626d76828f9caaac9f9286796d6053473a2d201407000a1724303d4a5763707d8a96a3b0ab9e928583838383838383838383838383838383838383838383838383838383838383837b6e6155483b2e2215080000010c161f2830383f444f59626c76828f9ca7a1978d8073685e52463f3f3f3f3f3f3f3f3f3f3f40444c56606d7985929a999896897c6f6356493c30231609000916222f3c4955626f7c8895a9b3a79a8d817467584e4239352f34383a40454d555c666d7a85919d9fa7b1afa396897c706356493d302f2c28211a110800000005121e2a36424d576774808d9aa6b0ac9f92857a6d615b5049443f4041464d56606b75828f9baab3a99b8e8175655b5044372b1f1205000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000000000008131e28313a444c555d606b70787e82868a8d8f919292929291908d8a87827d786f6a605c544a423930261c1106000000000000000000000000111e2a3744515d6a7784909da1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a4a7aca99d9083766a5d5043372a1d100000000000000000000000000000000000000000000000000815222e3b4754606a6f6e6d6d6d6e70737a83909da096897c6f6356493c3023160900000000000000000000000000000000000013202c3946535f6c798692939393939393939393939393939393939393939393939393939393939393939393939393939393939393938a7e7164574a3e3124170b0013202c3946535f6c798692939393939393939393939393939393939393939393939393939393939393939393939393939393939393938a7e7164574a3e3124170b00000000000000000714202d3a4753606d7a8693939393939286796c5f5346392c2013060000000000000000000000000a141e2935404b555d666d747c82878b8e909192929291908e8c88847f7a716d605d55535f696f7c848b8f9192929291908d86796c605346392d20130000000000010b151f2730383f444e54575e6164676a6b6c6c6c6b6a6865625f5854524c433f353c464e545c6065686b6c6c6b6b696765625b51463a2e2215090000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d010000000000000000000000000000000000000000020e1a27333f4a555f676a6c6c6c6c6c6b696764615e56534e463e362d23190b02000000000000000000000000000a1723303d4a5663707d8998a3aea89b8e8275675d51433a2f23181d1d1d1d1d161f2834404a545c606a6864615e5655534e463c32261b0f0300000013202c3946535f6c7986929faca79a8d8074675a4d4134271a0e0b070b1218202930363e444c525b626c727f8b949faba89c8f8376675d5145392c1f1306000a1724313d4a5764707d8a97a3b0ada1979290909090909090909090909090909090909090909090909090909090909090887b6e6255483b2f221508000000040d161e262e343d47505a63707c8995a0a99f92867a6d6154473b3032323232323232322e343a45515c6674818e8e8c8b89887f7265584c3f3225190c000a1723303d4a5663707d8996a3b0a6998c7f7366594c402f2924292c2f353b434b545d68707d8a959fabb7afa396897c706356493d3023201c161008000000000714212d3a46535f697884919eabafa49a8c7f73685e52443f383330363b444f5963707d8a98a2aeab9f9285796c605346392d201306000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000000000000050e19242f3a434c565e676d747d848a8f93999a9c9e9f9f9f9e9d9c9a9a938f8a837c736d665c544a42382e23170b020000000000000000000000111e2a3744515d6a7784909d9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9d9083766a5d5043372a1d1000000000000000000000000000000000000000000000000006131f2b38434e586062616160606163686f7c8899a4988b7e7265584b3f3225180c00000000000000000000000000000000000013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b0013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b00000000000000000714202d3a4753606d7a86939f9f9f9f9286796c5f5346392c201306000000000000000000000006111c26303845515d676d7880898f93999a9d9e9f9f9f9e9d9b9896918c857e756d675d58626e7b8691969b9e9f9f9e9e9c9386796c605346392d2013000000000007121d273139424a50586062696e71747777787979787775726f6a66605d56504540454e5860666d717578797978777674726d62564a3d3124180b0000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f03000000000000000000000000000000000000000003101d2936434f5b6771777879797978787674716d68625f5850483e352b1d140a000000000000000000000000000d1a2733404d5a6673808d99aab4aa978b7e7164554c4131282a2a2a2a2a2a2a2a2a232e39424a51535d5b5754524c4847433c342a20150a0000000013202c3946535f6c7986929faca79a8d8074675a4d4134271a0e030c151c2328323b41464f565d606d727e87929fa6ada1968b7e7165554b4035291d1004000a1724313d4a5764707d8a97a3b0b3a9a19e9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d94887b6e6155483b2e22150800000000040c141c2328353f4854606b7783909daaa3988c7f7266574d42362a25252525252525232834404b5464717e8281807e7d7c796d6053473a2d201407000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f2e23181c1f24293139424c56616c7683909da9b3afa396897c706356493d302316100b0500000000000815222e3b4855616e7b8896a1aca69f93877b6e61564c41332d28252a323d4653606c7985929fabada297887b6e6155483b2e221508000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000000020d17202935414c555e686d79818a91969c9fa4aba5aba49f9fa4aca5aca49f9c95908780786d665c544a3f34281d140a0000000000000000000000111e2a3744515d6a77839093939393939393939393939393939393939393939393939393939393939393939393939393939083766a5d5043372a1d10000000000000000000000000000000000000000000000000030f1b27323d464e5456555453545456606c7986939f998c807366594d4033261a0d00000000000000000000000000000000000013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4978a7d7164574a3e3124170b0013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4978a7d7164574a3e3124170b00000000000000000714202d3a4753606d7a8693a0acac9f9286796c5f5346392c20130600000000000000000000000b17232e3842505a606d79828d929b9fa4ababa39f9d9c9b9c9d9fa19e97928b82796d685f6a76828f98a1a8aaa39f9995949386796c605346392d201300000000020c18242f39434b545c606a6f757b7e8183848586858583817f7c78726d68625a514b4d57606a6f797e82848586858483817f7265584b3f3225180c000000000000000003101d2a3643505d69768286868276695d5043362a1d1003000000000000000000000000000000000000000004111e2a3744515d6a778385868686858483817e7a756e6a615a50473d2f261b1106000000000000000000000004101c2834404b546976828f9ca9aea398887b6f6255483c2f3737373737373737373737373039404446514e4b4746413c3b37322a261f180f0600000013202c3946535f6c7986929faca79a8d8074675a4d4134271a0e0c151e272e343e444d525961686d757f879299a3afa59e9184796d6053463a2f24180c00000a1723303d4a5663707d8996a3b0b8b0aba99f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa9aaaaaaaaaa94877a6e6154473b2e2114080000000000020a1117232c38444f596673808c99a6aa9d918477695e52463a2d2019191919191918232e394955616c7176747371706f6d675d5145392c201306000a1723303d4a5663707d8996abb5a6998d807366544a403428211e1a181f27303a44505a64707d8a97a2adafa396897c706356493d3023160a000000000000000b1825313e4b5864717e8b939a979a9c908376695e52443a30221b19202b3844505b6676838f9ca9b3a9978a7d7064574a3d3124170a000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000000000008141e29323b45515d676d7a838e939ea0a8a7a09d99959993939a96999ea0a8a7a099928c81786d665c50443d2f261c110600000000000000000000111e2a3744515d6a77838686868686868686868686868686868686868686868686868686868686868686868686868686868683766a5d5043372a1d10000000000000000000000000000000000000000000000000000a162027333f49535b606060606062666e7b8799a4988c7f7265594c3f3226190c00000000000000000000000000000000000013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a978a7d7164574a3e3124170b0013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a978a7d7164574a3e3124170b00000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000003101c28343f4a54616c74818e949da4aca7a09d9992908f8f8f9192999a9e9f948f837a6d666f7c88949faaaea398928c88878886796c605346392d2013000000000a141e2935404b555d666d747c82878b8e909192929291908e8c88847f7a716d605d55535f696f7c848b8f9192929291908d86796c605346392d2013000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000006121f2c3945525f6c78859292999292918f8e8b87827c716c61594f41382d22170b000000000000000000000006131f2c3845515c667884919eabac9f9286796d6053464444444444444444444444444444444444444444444444444444443b3a36312a21180e03000013202c3946535f6c7986929faca79a8d8074675a4d4134271a0b151e273039404450565e616b707a818b9299a3aba79e938b7e71665c5145382c1d12070000091623303c4956636f7c8996a2afb0a69f9c9393939393939393939393939393939393939393939393939c9ea6b0aea398877a6d6054473a2d2114070000000000000006101b27323d4956636f7c8996a9aca095877b6e6154483b2e21150c0c0c0c07121d2d3944505a6164696766656362605d554b4035291d1104000915222f3c4855626f7b8899a3afa89b8f8275665c51443a322d2b2627272628323e4653606d7985929fabafa396897c706356493d3023160a000000000000000c1925323f4c5865727f8486898b8d8f8c807366574d4232281e110f1c28333f4a546774808d9aa7b2a5988b7f7265584c3f3225190c000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000000010d1925303b44515b606d798390959ea5a9a19e95908c8987868687898c91969ea1a9a39f938f81786d60584e42382d22170b00000000000000000000101d2936424f5b677177797979797979797979797979797979797979797979797979797979797979797979797979797979797671665b4e4236291c100000000000000000000000000000000000000000000000000005121f2b3744505b656c6d6c6c6d6f7278818e9ba095897c6f6356493c3023160900000000000000000000000000000000000013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8a7e7164574a3e3124170b0013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8a7e7164574a3e3124170b00000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000006121f2b3844505c66717e8b939ea6aea59d95908a86838282838486898d92979f959083786d73808d99a6b0a89f9286807c7a7b7d7063574a3d3024170a00000006111c26303845515d676d7880898f93999a9d9e9f9f9f9e9d9b9896918c857e756d675d58626e7b8691969b9e9f9f9e9e9c9386796c605346392d2013000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000006121f2c3945525f6c7885929493939496999a99938e867e716b6053493f33271b0f03000000000000000000000713202d3a4653606d7986939facaa9d908477665c50505050505050505050505050505050505050505050505050505050504846423b332a1f1409000013202c3946535f6c7986929faca79a8d8074675a4d4134271a121d273039424a515a62686e757d848e939fa3aba8a0958f81756c61544b4034281c0b0100000815222f3b4855626e7b8895a9b3ab9f948f8686868686868686868686868686868686868686868686868f949eaaac9f928579675d5145392c20130600000000000000000b14212d3a4754606d7a8797a1ada7978b7e7164584b3e3125180b00000000101c28333e485055575c5b5958565553514b433a2f24180d01000714202d3a4753606d7a86929facab9e9285796d60564c443d3a373134333332323845515c6675828f9ca8afa396897c706356493d3023160a000000000000000b1824313e4a56626d72787a7c7e8082847d7063574a3d3024160c0b17222d404c5966737f8c99a6b2a6998d8073665a4d4033271a0d000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000005111e2a36414c56626d75828f959fa7a8a097928a837f7c7a79797a7c7f848a9297a0a8a59e938d80736a60544a3f33281c0f030000000000000000000e1a27333f4a555f676a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a665f554a3e32261a0d000000000000000000000000000000000000000000000001080d13202d394653606c777979797a7b7e838e939e989083786c605346392d20130600000000000000000000000000000000000013202c3946535f6c7986929facb3a79a8d80808080808080808080808080808080808080808080808080808080808080808080808080807c6f6255483c2f2215090013202c3946535f6c7986929facb3a79a8d80808080808080808080808080808080808080808080808080808080808080808080808080807c6f6255483c2f22150900000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000713202d3a4653606d7884919ea5afa69d938e837d797776757677797c80858c9298958e81747683909ca9aca0958a7e736f6e6e706b6155483c2f2316090000000b17232e3842505a606d79828d929b9fa4ababa39f9d9c9b9c9d9fa19e97928b82796d685f6a76828f98a1a8aaa39f9995949386796c605346392d2013000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000006121f2c3945525f6c78858887868787898d92979f9892887d70655b5044372b1f1205000000000000000000000815212e3b4854616e7b879aa4afa99c90837669545d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d55534d453b31261a0e020013202c3946535f6c7986929faca79a8d8074675a4d4134271a18232e39434b545c606c717b818a91969ea5afa69f959083796d605a5042392e23180c0000000714212d3a4754606d7a8797a2ada99c8f82797979797979797979797979797979797979797979797979828f9ca9ab9e9184786b554b4135291d110400000000000000030613202c3945515d677885919eaba6998d8073665a4d4033271a0d0c0c0c0c0b17222c363e44494a4f4e4d4b4a484745403a31281d1307000006131f2c3945515d677783909dabada1978a7e71685e564f484742424140403f3f3f404b546673808c99a6afa396897c706356493d3023160a000000000000000916222e3a46515b6265676d6f71737578706b6155483c2f231604061925323f4c5865727f8b98a5b2a79a8d8074675a4d4134271a0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000000000714202d3946525e68727f8b949ea7a9a09591857e77726f6d686c6d6f72787e859196a0a9a59f93877c6f665b5044382b1f13080000000000000000000a16222e39434d555b5d606060606060606060606060606060606060606060606060606060606060606060606060606060605d5b554d43382d22160a00000000000000000000000000000000000000000003090e13191d202d394653606c7984868687888b90959a9590867c6f665b5044382b1f120802000000000000000000000000000000000013202c3946535f6c7986929facada0938679737373737373737373737373737373737373737373737373737373737373737373737373736f6a5f53473a2e2115080013202c3946535f6c7986929facada0938679737373737373737373737373737373737373737373737373737373737373737373737373736f6a5f53473a2e21150800000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000b1824313e4b5764717e8a96a0acac9f948e8179716d67696869676d70747a7f869095938a7e7885929fabaa9d9184776c6261616361594f44382c201407000003101c28343f4a54616c74818e949da4aca7a09d9992908f8f8f9192999a9e9f948f837a6d666f7c88949faaaea398928c88878886796c605346392d2013000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000916232f3c4956626f7c7b7a7a7a7b7d808590959f9a9184786c605346392d201306000000000000000000000916232f3c4956626f7c8995acb6a89c8f82756a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a615f574d42362a1e12050013202c3946535f6c7986929faca79a8d8074675a4d41342716202834404b555c666d747e858e939ea1a8aca49f9490837b6e675d51483e30271d12070000000613202c3945515d677885929eabaa9d9184776c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c667784919eaaa99c8f8376695c50432f24180d010000000000040a0f13151d2935414b556a7783909daaa89b8f8275685c4f4235291c191919191919191a242c33393c3e4341403e3d3c3a39352f281f160c01000004101d2935404b5566737f8c99a3aea99e91847a6d68615955534d4f4e4d4c4c4c4b4b4c5865727f8b98a5afa396897c706356493d3023160a0000000000000006121e29343f495156555d60626467696b6361594f44382c2014070b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000005111d2935414c56616e7a85929fa6ada19791837b716c6662605d606163656c717b849197a1ada4999184786c6053463a3025190d01000000000000000006111c27313b434a4f5153535353535353535353535353535353535353535353535353535353535353535353535353535353504e4a433a31271c110500000000000000000000000000000000000000030a0f151a1e24292c2e3844505b6673808c9993999292908d89837c6f6a5f544a3f33281c19130d080100000000000000000000000000000013202c3946535f6c7986929facada093867a6d676767676767676767676767676767676767676767676767676767676767676767676767625f584e43372b1f12060013202c3946535f6c7986929facada093867a6d676767676767676767676767676767676767676767676767676767676767676767676767625f584e43372b1f120600000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000005121e2a36424d576875818e9ba8afa49a8f82786d66605d555c555c6063676d727b838f9391857b8797a2ada79a8d8074675a545557554f473e33281c1004000006121f2b3844505c66717e8b939ea6aea59d95908a86838282838486898d92979f959083786d73808d99a6b0a89f9286807c7a7b7d7063574a3d3024170a000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000815222e3b4754606a6f6e6d6d6d6e70737a83909da096897c6f6356493c30231609000000000000000000000a1623303d495663707c8996a3afa89b8e8177777777777777777777777777777777777777777777777777777777777777776e695f53463a2d2114070013202c3946535f6c7986929faca79a8d8074675a4d4134271e28323a45515c676d78818b92979ea5ada8a19a938d827a6e695e554c41362d1e150b0000000004111d2935414c55697683909ca9ab9f928578695f606060606060606060606060606060606060606d7986929faca79a8d8174675a4e4134271b070000000000070f161b1f2223242f43505d697683909ca9a99c908376695d5043362a2525252525252525252520282d303136343332302f2d2c29241d160d04000000000c18242f3b4854616e7b86929fa8ada19690827a706b65615f575c5a5a5959585858585865717e8b98a4afa396897c706356493d3023160a00000000000000010d18232d373f464a4b515356585a5c5e57554f473e33281c10040b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000713202d3946525e6874808d98a2aea69e92857b6e69615a5654525354535b60696e7b85929ea8aba0958a7d7063564c41362a1d11050000000000000000000b151f2931393f42444646464646464646464646464646464646464646464646464646464646464646464646464646464643423e3831281f150a00000000000000000000000000000000000000060b151a1f262b2f35393a40444a54616e7b87939f92878583817d786f6a5f584e4238342e29241e19130c04000000000000000000000000000013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a55534e463c31261b0f030013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a55534e463c31261b0f0300000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000714202d3a46525e697885919eabac9f93877c6f665c54514b4f4b5153555d60696e79818f949083909da9b3a4988b7e7165584b484a48443e352c21160b0000000713202d3a4653606d7884919ea5afa69d938e837d797776757677797c80858c9298958e81747683909ca9aca0958a7e736f6e6e706b6155483c2f231609000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000006131f2b38434e586062616160606163686f7c8899a4988b7e7265584b3f3225180c000000000000000000000a1724303d4a5763707d8a96a3b0ab9e928583838383838383838383838383838383838383838383838383838383838383837b6e6155483b2e2215080013202c3946535f6c7986929faca79a8d8074675a4d41342724303a44515b606d79828e939fa2a9ada59d96918880786d685e564d433a2f241b0c0300000000010d19242f414d5a6774808d9aabaea298887b6e61555353535353535353535353535353535355626f7c8899a3afa9988b7e7265584b3f3225180c0000000007101921272c2f303236434f5c6976828f9ca9aa9d9083776a5d50443732323232323232323232322d2c28232429282625232220201d18130c0400000000000714202d3a46525e6974808d96a1a9a89f9590847d77726e696a6867666665656565646465717e8b98a4afa396897c706356493d3023160a000000000000000006111b252d343a3a404547494b4d4f514a48443e352c21170b000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000714212e3a4754616d7a86929faaab9f948a7d70695e575049474546474950565e69717e8b96a0aca79c8f8275685e5246392d201307000000000000000000040d171f272e333637393939393939393939393939393939393939393939393939393939393939393939393939393939393736322d271f160d030000000000000000000000000000000000020a111720262b31373a4145474a5153555e6976828f9b8f82787774706c655f58504a46443f38353029241e160d070000000000000000000000000013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4847433c342a20150a000013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4847433c342a20150a0000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000815212e3b4854616e7b8797a1adaa9d9083776a5f544b4540424045474b51575f676d78828f9590959fabb0a3968a7d7063574a3d3d3c38332c231a10050000000b1824313e4b5764717e8a96a0acac9f948e8179716d67696869676d70747a7f869095938a7e7885929fabaa9d9184776c6261616361594f44382c201407000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000030f1b27323d464e5456555453545456606c7986939f998c807366594d4033261a0d000000000000000000000a1724313d4a5764707d8a97a3b0ada1979290909090909090909090909090909090909090909090909090909090909090887b6e6255483b2f2215080013202c3946535f6c7986929faca79a8d8074675a4d4134272935414c56626d75818e949da5ada9a19e938e847d736d665d564d443b31281e1209000000000000081724313e4a5764717d8a99a3afaa988b7e7165574d42464646464646464646464646424d5765727f8c98abada297887b6f6255483c2f221509000000040f19222b32383b3c3f3f434f5c6976828f9ca9aa9d9184776a5e51443f3f3f3f3f3f3f3f3f3f3f3f3a38342e271e151a1817151413110d070100000000000005121e2a36424d57606d79849197a1a9a79f969189837f7b78767574737372727271717171717e8b98a4afa396897c706356493d3023160a00000000000000000009131b23292e2f35393a3c3e4042453d3c38332c231a1005000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000005121e2a36424d5765727f8c98a2aea99c8f82766c61574d453e3a39393a3f444d57616c7784919eaaa99f93867a6d6154473a2e21140700000000000000000000050d151c2227292a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2a2926221c150d040000000000000000000000000000000000060c141c232831373c42474c5154545c60626466717e8a9792877b6e6a69676462605b5453504a45413a352f281f18120b03000000000000000000000013202c3946535f6c7986929facada093867a6d6053474040404040404040404040404040404040404040404040404040404040404040403c3a37312a22180e04000013202c3946535f6c7986929facada093867a6d6053474040404040404040404040404040404040404040404040404040404040404040403c3a37312a22180e040000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000916222f3c4955626f7c8895a9b3a79a8d817467584e4239352f34383a40454d555c666d7a85919d9fa7b1afa396897c706356493d302f2c28211a110800000005121e2a36424d576875818e9ba8afa49a8f82786d66605d555c555c6063676d727b838f9391857b8797a2ada79a8d8074675a545557554f473e33281c1004000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000a162027333f49535b606060606062666e7b8799a4988c7f7265594c3f3226190c000000000000000000000a1724313d4a5764707d8a97a3b0b3a9a19e9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d94887b6e6155483b2e2215080013202c3946535f6c7986929faca79a8d8074675a4d4134272d3946525d68727e8b939ea6afa69f979189817a706b605c544c443b32291f160c000000000000000714212e3a4754616d7a86929faca89b8e8275695e53463d313939393939393939303946525e6976828f9ca9ab9e9285786c605346392d2013060000000a16212b343d4348494c4c4c4f5c6976828f9ca9aa9d9184776a5e514c4c4c4c4c4c4c4c4c4c4c4c4c4645403930271d12070a09070604010000000000000000020e1a25303b45515d676f7c8591979ea5a8a09e95908b8885838281807f7f7f7e7e7e7e7d7d808d9aa7afa396897c706356493d3023160a000000000000000000010911181e1d24292c2d2f31343638302f2c28211a110800000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000714202d3a46525e697783909daaada197897d7063594f453b332d2c2d2d333b45505a66737f8c999d9c9c998a7d7063574a3d3024170a0000000000000000000000040b11161a1d1e202020202020202020202020202020202020202020202020202020202020202020202020202020201d1c1a16110a030000000000000000000000000000000000070f181e262e343c43474d53555d6064666d6f717375798592998c8078777673716e6c6663605c54524c45413a3128231d150c040000000000000000000013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343434342f2e2b262018100600000013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343434342f2e2b2620181006000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000a1723303d4a5663707d8996a3b0a6998c7f7366594c402f2924292c2f353b434b545d68707d8a959fabb7afa396897c706356493d3023201c161008000000000714202d3a46525e697885919eabac9f93877c6f665c54514b4f4b5153555d60696e79818f949083909da9b3a4988b7e7165584b484a48443e352c21160b00000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000005121f2b3744505b656c6d6c6c6d6f7278818e9ba095897c6f6356493c30231609000000000000000000000a1723303d4a5663707d8996a3b0b8b0aba99f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa9aaaaaaaaaa94877a6e6154473b2e2114080013202c3946535f6c7986929faca79a8d8074675a4d4134272e3a4754616d7a85929fa5afa59e948f857d746d676059514a423a322920170d04000000000000000713202d3946525d6876828f9ca9ac9f92867b6e61584e433b322c292424292c3139424d57616e7b86929faca89b8e8174655b5044372b1f12050000030f1b27323d474f5456585858585c6976828f9ca9aa9d9184776a5e585858585858585858585858585853514b42392e23180c00000000000000000000000000000009141f2935414b555f6a6f7c858f939c9fa4a79f9d989892908f8d8d8c8c8b8b8b8b8a8a8a8d929da9afa396897c706356493d3023160a0000000000000000000000060d1213181d2020232527292b2423201c1710080000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000815212e3b4854616e7b87959fabab9e9184786c6053463e33292120202227333e4956626f7c899191908f8e8d8073665a4d4033271a0d00000000000000000000000000060a0e10111313131313131313131313131313131313131313131313131313131313131313131313131313131310100d0a05000000000000000000000000000000000000081019212a30383f444e53575f62676d7175797c7e80828390979c928c848382807e7b7974706d66605d56524c433d342e271e160e0500000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2727272727272727272727272727272727272727272727272727272727272722211f1b150e060000000013202c3946535f6c7986929facada093867a6d6053473a2d2727272727272727272727272727272727272727272727272727272727272722211f1b150e0600000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f2e23181c1f24293139424c56616c7683909da9b3afa396897c706356493d302316100b0500000000000815212e3b4854616e7b8797a1adaa9d9083776a5f544b4540424045474b51575f676d78828f9590959fabb0a3968a7d7063574a3d3d3c38332c231a100500000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000613202d394653606c777979797a7b7e838e939e989083786c605346392d20130600000000000000000000091623303c4956636f7c8996a2afb0a69f9c9393939393939393939393939393939393939393939393939c9ea6b0aea398877a6d6054473a2d2114070013202c3946535f6c7986929faca79a8d8074675a4d41342935404b5565727f8c97a2ada59e938e827a706b605d554f444039302820170e05000000000000000005111d2935414c5664717e8b96a1ada3998d80746a60564d443e39352f2f35383c434b545e6973808d99a3aca096897d706353493f33271b0f03000007131f2c38434f59606365656565656976828f9ca9aa9d9184776a656565656565656565656565656565605c544b4034281c10040000000000000000000000000000020d18242f3a434e585f6a6f7a82898f93999c9fa2aaa29f9d9b9a999998989898979797979a9da4aeafa396897c706356493d3023160a0000000000000000000000000101070d11131416181a1c1e171614100b05000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000b1824313e4b5764717e8a97a7b1a79a8d8174665b5044382c2017131317202d3a4753606d79868584838281807e7164574b3e3124180b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a222b333c424a50585f62696e747a7e8185888b8d8f9095a0a49c9691908f8d8a8885817d79736d68605d564f454039302820160e05000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1515120f0a04000000000013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1515120f0a040000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000a1723303d4a5663707d8996abb5a6998d807366544a403428211e1a181f27303a44505a64707d8a97a2adafa396897c706356493d3023160a000000000000000916222f3c4955626f7c8895a9b3a79a8d817467584e4239352f34383a40454d555c666d7a85919d9fa7b1afa396897c706356493d302f2c28211a11080000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000020a13202d394653606c7984868687888b90959a9590867c6f665b5044382b1f1206000000000000000000000815222f3b4855626e7b8895a9b3ab9f948f8686868686868686868686868686868686868686868686868f949eaaac9f928579675d5145392c2013060013202c3946535f6c7986929faca79a8d8074675a4d41342c3945515d677783909da9ac9e938e81786d686159514c433d342e271e160e05000000000000000000010d1924303a4653606d7984919ea7ab9f92877c6f685e564f47454141414045474e555c666e7b86929faba89e9184786c605346392d22170b0000000915222f3b4854606b6f72727272727276828f9ca9aa9d918477727272727272727272727272727272726d665c5145382c1f130600000000000000000000000000000007131d28313c464e585f686d757c82878b8f929897999a9b9c9d9d9d9e9e9e9e9f9f9f9fa3abacb5afa396897c706356493d3023160a00000000000000000000000000000001040607090b0d0f120a0a07040000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00010e1b2734414e5a6774818d9aa7b4aa978a7e7164544a3f33281a0e0606131f2c3845515c676d79787776757474716c6155493d3023170a0000000000000000000000000000000000000000000000000002050708080808080808060503000000000000000000000000000000000000000000000000000000000000000000000000000000000007111a232b343d454d545c606a6e757b81868a8e929897999c9da0a7aea8a19e9d9c9a9797928e8985807a736d686059514b423a322820170e050000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d090806030000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0908060300000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000915222f3c4855626f7b8899a3afa89b8f8275665c51443a322d2b2627272628323e4653606d7985929fabafa396897c706356493d3023160a000000000000000a1723303d4a5663707d8996a3b0a6998c7f7366594c402f2924292c2f353b434b545d68707d8a959fabb7afa396897c706356493d3023201c161008000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000001070c141c232b3844505b6673808c9993999292908d89837c6f6a5f544a3f33281c0f03000000000000000000000714212d3a4754606d7a8797a2ada99c8f82797979797979797979797979797979797979797979797979828f9ca9ab9e9184786b554b4135291d11040013202c3946535f6c7986929faca79a8d8074675a4d41342d3a4753606d7a86929faca49a8f81776d665e564f45413a3128231c150c04000000000000000000000008131f2c3845515c67727f8b95a0aba39991847a6e68615954514c4e4e4b5153575f676d78839098a2aca0968b7f72665b5044382b1b1106000000091623303c4956636f7d7f7f7f7f7f7f7f83919daaab9e91857f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6053463a2d201307000000000000000000000000000000010c161f2a343c464e565e616b6f757b7f8285888a8c8d8f8f9090919191919292929292999ba3acafa396897c706356493d3023160a000000000000000000000000000000000000000000010305000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0004111d2935414c566a7683909da9aea298887b6e6155483b2d2217080004101c2934404b555c606c6b6a6969686764615a5045392d211408000000000000000000000000000000000000000000000003090e12141515151515151513120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000050f19232b353d464e575f666d727c81878e92999b9fa2aaa6a8aaa9a8a7a7a8a9aaa9a6a9a29e9a97928d85807a706b605c544c443a322920170c0300000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140701010101010101010101010101010101010101010101010101010101000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407010101010101010101010101010101010101010101010101010101010000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000714202d3a4753606d7a86929facab9e9285796d60564c443d3a373134333332323845515c6675828f9ca8afa396897c706356493d3023160a000000000000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f2e23181c1f24293139424c56616c7683909da9b3afa396897c706356493d302316100b0500000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000030b12181e262e34383f4a54616e7b87939f92878583817d786f6a5f584e42382d2218120b030000000000000000000613202c3945515d677885929eabaa9d9184776c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c667784919eaaa99c8f8376695c50432f24180d010013202c3946535f6c7986929faca79a8d8074675a4d41342f3c4855626f7b8899a3ac9f93877b6e655c544c443d352f281f18120b0300000000000000000000000004101c2834404b55606d78839099a3aba09690837a706b64605d555b5b555d60636a6e79818e959faaa49a9184796d60544a3f33281c0a000000000d1a2734404d5a6773808b8b8b8b8b8b8b9195a0acada197918b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b877a6d6054473a2d21140700000000000000000000000000000000040d18222a343c444c52596063696e7276797b7d7f81828383848484848585858585868b909ba7afa396897c706356493d3023160a000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000713202c3945525d687885929fabac9f9285796c605346392d20130600000c18232f39434b51535f5e5e5d5c5b5a575550483e33281d110500000000000000000000000000000000000000000000050d141a1e2121212121212121201f1b17110a020000000000000000000000000000000000000000000000000000000000000000000000030d17212b353d474f5860696e787f868e93999fa3ababaca8a9a29e9d9b9b9a9b9c9d9fa3aaa9aba9a19e98928c857d736d665d564c443a32291e150a00000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000006131f2c3945515d677783909dabada1978a7e71685e564f484742424140403f3f3f404b546673808c99a6afa396897c706356493d3023160a000000000000000a1723303d4a5663707d8996abb5a6998d807366544a403428211e1a181f27303a44505a64707d8a97a2adafa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000050d151d242930383f44464c535e6976828f9b8f82787774706c655f584e443f382f28231c150c03000000000000000004111d2935414c55697683909ca9ab9f928578695f606060606060606060606060606060606060606d7986929faca79a8d8174675a4e4134271b07000013202c3946535f6c7986929faca79a8d8074675a4d4134303c4956636f7c8996abaa9e918477695e534a423a3229241e160d070000000000000000000000000000000c18232e3944515c666f7c87929fa4a8a09590847d76716d6769676869676d70757b838e939ea7a59f93887d70665c5142382d22170b000000000d1a2734404d5a6773808d9898989898989da0a7b1b3a9a19e98989898989898989898989898989893877a6d6054473a2d21140700000000000000000000000000000000050e171e252a323a41464f54575e6165666d6f717374757676777777787878787879797e8b98a4afa396897c706356493d3023160a000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000714212d3a4754606d7a8797a2adaa9d918477655b5044372b1f1205000007121d273139404547525251504f4e4d4b49453e362c22170c00000000000000000000000000000000000000000000050f171f252a2d2e2e2e2e2e2e2e2d2b27221b140b02000000000000000000000000000000000000000000000000000000000000000000010b151f29333d474f59606a6f7b838c92999fa4abadaaa29f9b979792908f8e8e8e8f909298989d9fa7acaaa29f97918880786d685e564c443a30261c1106000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c07060401000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c070604010000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000004101d2935404b5566737f8c99a3aea99e91847a6d68615955534d4f4e4d4c4c4c4b4b4c5865727f8b98a5afa396897c706356493d3023160a000000000000000915222f3c4855626f7b8899a3afa89b8f8275665c51443a322d2b2627272628323e4653606d7985929fabafa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000050e161f272f353e424a5053565e6164717e8a9792877b6e696764615e56535049413d342e271e150c0300000000000000010d19242f414d5a6774808d9aabaea298887b6e61555353535353535353535353535353535355626f7c8899a3afa9988b7e7265584b3f3225180c000013202c3946535f6c7986929faca79a8d8074675a4d41342f3c4955626f7c8895a7ab9e9184786a5f544a423930281f160d040000000000000000000000000000000007121d2834404a54606a727f8c929ca4a7a096918a827d7a7775747475767a7d818790959ea5a59e938d80736b60544b402f261c1106000000000d1a2734404d5a6773808d9a9f9f9f9f9fa9aab0b8bab2acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f93877a6d6054473a2d211407000000000000000000000000000000020c1720293036393a3e3f44484d5354545c606264666768696a6a6a6b6b6b6b6c6c6c717e8b98a4afa396897c706356493d3023160a000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000815222f3b4855626e7b8895a9b3a99c8f82766953493f33271b0f030000010b151f272f34383a464544434241413e3d39332c241a1006000000000000000000000000000000000000000000030c17212931363a3b3b3b3b3b3b3b3937332d261d140a00000000000000000000000000000000000000000000000000000000000000000007121d27313b454f59606b707c8590959fa3abaea9a19e98928e8a87858382818181828386888b90959b9fa4aca9a19a938d837a6d685e564c42382e23170d040000000013202c3946535f6c7986929facada093867a6d6053473a2d2019191919191919191919191919191919191919191919191919191413110d070100000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2019191919191919191919191919191919191919191919191919191413110d0701000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000c18242f3b4854616e7b86929fa8ada19690827a706b65615f575c5a5a5959585858585865717e8b98a4afa396897c706356493d3023160a000000000000000714202d3a4753606d7a86929facab9e9285796d60564c443d3a373134333332323845515c6675828f9ca8afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000040d162028313940454f545c6064686e7174798592998c80777674716e6863605b534e44403930271e150c0300000000000000081724313e4a5764717d8a99a3afaa988b7e7165574d42464646464646464646464646424d5765727f8c98abada297887b6f6255483c2f221509000013202c3946535f6c7986929faca79a8d8074675a4d41342e3a4754616d7a8795a0aca196887c6f665c544b423a31281f160d03000000000000000000000000000000000c18232e39424e58626d73808c929ea1a8a19e948f8a8683828181828386898e93999fa7a39f938f81786d60594f42392e1d140a00000000000d1a2734404d5a6773808d9393939393939c9fa6b0b2a8a09393939393939393939393939393939393877a6d6054473a2d21140700000000000000000000000000000008131e29323a4146474b4c4d4e4f51524a50535557595a5c5c5d5d5e5e5e5e5f5f5f65717e8b98a4afa396897c706356493d3023160a000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00091623303c4956636f7c8996a2afa89b8e8175685b4e422d22170b00000000030d151d23292c2d3938373636353431302d28221a1208000000000000000000000000000000000000000000000a151e29333b42464848484848484846443f382f261b110600000000000000000000000000000000000000000000000000000000000000000c18242f39434d57606b707d8692979fa7aeaba39f96918b86817e7b7876757474757677797c7f83888e939a9fa7aca49f9590837a6d685e544a3f34281f160c0100000013202c3946535f6c7986929facada093867a6d6053473a2d26262626262626262626262626262626262626262626262626262621201d18130c04000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d26262626262626262626262626262626262626262626262626262621201d18130c040000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000714202d3a46525e6974808d96a1a9a89f9590847d77726e696a6867666665656565646465717e8b98a4afa396897c706356493d3023160a0000000000000006131f2c3945515d677783909dabada1978a7e71685e564f484742424140403f3f3f404b546673808c99a6afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000010c161f28323a434b515961666d71767a7e80828f979c928c8483807d7a76706c656058514a423930271e150a000000000000000714212e3a4754616d7a86929faca89b8e8275695e53463d313939393939393939303946525e6976828f9ca9ab9e9285786c605346392d201306000013202c3946535f6c7986929faca79a8d8074675a4d41342d3946525e687784919da8a89c9082786d665c544b433a31281f150b0100000000000000000000000000000007121c27303d46515b646e73808a92979fa3a69f9c9992908f8e8e8f9092989b9fa4a69f99928c81786d665c50473d30271d0b0200000000000d1a2734404d5a677380868686868686868f949faaaca0968986868686868686868686868686868686867a6d6054473a2d2114070000000000000000000000000000010d1925303a444c525457595a5b5c5d5e5b5953484a4c4e4f5050515151515252525965727f8c98a5afa396897c706356493d3023160a000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000a1724303d4a5763707d8a96a3b0a79a8d8174675a4e4134271b060000000000030b12181c1f202c2b2b2a2928272423211d1710080000000000000000000000000000000000000000000006111c26303b454d535454545454545453504941382d22170b0000000000000000000000000000000000000000000000000000000000000004101d2935404b555e69707d879298a2a9b1a8a099928c847f7a75716e696a6868676869666d6f72767b818790959da4afa79f9590837a6d665c50443e31281d130700000013202c3946535f6c7986929facada093867a6d6053473a333333333333333333333333333333333333333333333333333333332d2c29241d160d040000000000000013202c3946535f6c7986929facada093867a6d6053473a333333333333333333333333333333333333333333333333333333332d2c29241d160d0400000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000005121e2a36424d57606d79849197a1a9a79f969189837f7b78767574737372727271717171717e8b98a4afa396897c706356493d3023160a0000000000000004101d2935404b5566737f8c99a3aea99e91847a6d68615955534d4f4e4d4c4c4c4b4b4c5865727f8b98a5afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000008131e28313a444c555d606b70787e82868a8d8f949fa49c9691908d8a87827d786f6a605c544a423930261c11060000000000000713202d3946525d6876828f9ca9ac9f92867b6e61584e433b322c292424292c3139424d57616e7b86929faca89b8e8174655b5044372b1f1205000013202c3946535f6c7986929faca79a8d8074675a4d41342935414c5666727f8c96a1ab9f948e81786d665d554c433a31271d1207000000000000000000000000000000000b151e2b343f49525c646e737e858e92999ea1a8a39f9d9c9a9b9c9d9fa3a9a29f9b948f877f776d665c544a3f352c1e150b0000000000000d1926333f4c58646e7379797979797979828f9ca9aa9d9184797979797979797979797979797979797976685d5245392c201307000000000000000000000000000005111d2a36414c565e6164656768696a6b68655d534840414243434444444545454d596673808c99a6afa295897c6f6256493c2f231609000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000a1724313d4a5764707d8a97a3b0a79a8d8074675a4d4134271a0e01000000000001070c1013141f1f1e1d1c1b1a181714110c0600000000000000000000000000000000000000000000000c17232e38424d575e61616161616161605b53493f33271b0f03000000000000000000000000000000000000000000000000000000000005101a232c3945515d676e7b859299a2aab1a79f9691878079726d6764615e575c5b5b5b545c6062656a6e747c838d929fa3aba7a0959082786d60594f433a2f24180d02000013202c3946535f6c7986929facada093867a6d6053473f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3a39352f281f160c0100000000000013202c3946535f6c7986929facada093867a6d6053473f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3a39352f281f160c01000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000020e1a25303b45515d676f7c8591979ea5a8a09e95908b8885838281807f7f7f7e7e7e7e7d7d808d9aa7afa396897c706356493d3023160a00000000000000000c18242f3b4854616e7b86929fa8ada19690827a706b65615f575c5a5a5959585858585865717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000050e19242f3a434c565e676d747d848a8f93999a9c9fa6aca8a09e9c9a9a938f8a837c736d665c544a42382e23170b02000000000005111d2935414c5664717e8b96a1ada3998d80746a60564d443e39352f2f35383c434b545e6973808d99a3aca096897d706353493f33271b0f03000013202c3946535f6c7986929faca79a8d8074675a4d413425303a4754606d79849199a4a69e938e81786d675d564c43392f24180d03000000000000000000000000000000030c19222d37404a525c636c717a81868d9196989b9c9e9f9f9f9f9e9d9b9997928e89827c736c655c544b42382e231a0c030000000000000b17232f3b47525c64676c6c6c6c6c6c76828f9ca9aa9d9184776c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5d564c4135291d110400000000000000000000000000000713202d3946525e686d71727374767778756f65594d3d323536373737383835404b556774818e9aa7b2a995887b6e6255483b2f221508000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000b1724313e4a5764717d8a97a4b0a69a8d8073675a4d4034271a0d010000000000000000040607131211100f0e0e0b0a080500000000000000000000000000000000000000000000000003101c28343f4a545e696e6e6e6e6e6e6e6c655b5044372b1f120500000000000000000000000000000000000000000000000000000000000b16212b37434e58606d79839097a1abb1a79f9590847c736d67605d5554524d4f4e4e4e4a505355585f626a6f78808a9299a3aba79f948d80736b61554b4035291f1409000013202c3946535f6c7986929facada093867a6d60534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4745413a31281d130700000000000013202c3946535f6c7986929facada093867a6d60534c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4745413a31281d1307000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000009141f2935414b555f6a6f7c858f939c9fa4a79f9d989892908f8d8d8c8c8b8b8b8b8a8a8a8d929da9afa396897c706356493d3023160a00000000000000000714202d3a46525e6974808d96a1a9a89f9590847d77726e696a6867666665656565646465717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000020d17202935414c555e686d79818a91969c9fa4aba5aba49f9fa4aca5aca49f9c95908780786d665c544a3f34281d140a0000000000010d1924303a4653606d7984919ea7ab9f92877c6f685e564f47454141414045474e555c666e7b86929faba89e9184786c605346392d22170b00000013202c3946535f6c7986929faca79a8d8074675a4d4134272c3945515d67707d87939fa3a59e938f82796d685d554b4035291f150b0100000000000000000000000000000007101b252e38404a525a61686d747b8084888b8e90919292929291908e8c8985817c766f6a605b534b423930261c11080000000000000007131f2b36404a52585a60606060606976828f9ca9aa9d9184776a6060606060606060606060606060605f524c443a2f24190d0100000000000000000000000000000714212e3a4754616d7a7e7f8081828485817568584e43372e2c2823282c2f3945515d677783909daaada196877a6d6054473a2d211407000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000a1724313d4a5764707d8a97a3b0a79a8d8074675a4d4134271a0e010000000000000105090b0b121111100f0e0d0908060300000000000000000000000000000000000000000000000006121f2c3844505c66767b7b7b7b7b7b7b776c605346392d2013060000000000000000000000000000000000000000000000000000000004101c27333a47535f6a74808d95a0a9b2a89f9590837a6f6a605c55514b484642424141423f4446494e53585f666d737e879299a4afa69f93887d70675d51453b30251a0e020013202c3946535f6c7986929facada093867a6d605959595959595959595959595959595959595959595959595959595959595954514b433a2f24180d01000000000013202c3946535f6c7986929facada093867a6d605959595959595959595959595959595959595959595959595959595959595954514b433a2f24180d010000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000020d18242f3a434e585f6a6f7a82898f93999c9fa2aaa29f9d9b9a999998989898979797979a9da4aeafa396897c706356493d3023160a000000000000000005121e2a36424d57606d79849197a1a9a79f969189837f7b78767574737372727271717171717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000008141e29323b45515d676d7a838e939ea0a8a7a09d99959993939a96999ea0a8a7a099928c81786d665c50443d2f261c1106000000000008131f2c3845515c67727f8b95a0aba39991847a6e68615954514c4e4e4b5153575f676d78839098a2aca0968b7f72665b5044382b1b110600000013202c3946535f6c7986929faca79a8d8074675a4d4134272935414b55606b727f8c919fa3a59e948f837a6d675d51453e31271d12070000000000000000000000000000000009131c262e38404850565e61696e73787c7e818384858686858583817f7c79746f6a625f585049413930271e150a0000000000000000020e19242e3840474c4d535353535c6976828f9ca9aa9d9184776a5e53535353535353535353535353535345413a32281e13080000000000000000000000000000000815212e3b4854616e7b878c8d8e8f909184786a6054473f3a38342e34383a404b55606d7a86929facab9e918578675d5145392c201306000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000a1724303d4a5763707d8a96a3b0a79a8d8074675a4d4134271a0e010000000000060c111517181f1e1d1c1b1a191615130f0a04000000000000000000000000000000000000000000000713202d3a4653606d7986878787878786796d6053473a2d201407000000000000000000000000000000000000000000000000000000000714202c38444f59626e7c87929fa7b1aaa1969083796d685f58514b45413b3a363035342e34383a3c43474e545c606c717e87939fa5afa49a9185796d60574d42362a1e11050013202c3946535f6c7986929facada093867a6d6666666666666666666666666666666666666666666666666666666666666666605d554b4135291d1104000000000013202c3946535f6c7986929facada093867a6d6666666666666666666666666666666666666666666666666666666666666666605d554b4135291d11040000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000007131d28313c464e585f686d757c82878b8f929897999a9b9c9d9d9d9e9e9e9e9f9f9f9fa3abacb5afa396897c706356493d3023160a0000000000000000020e1a25303b45515d676f7c8591979ea5a8a09e95908b8885838281807f7f7f7e7e7e7e7d7d808d9aa7afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000010d1925303b44515b606d798390959ea5a9a19e95908c8987868687898c91969ea1a9a39f938f81786d60584e42382d22170b000000000004101c2834404b55606d78839099a3aba09690837a706b64605d555b5b555d60636a6e79818e959faaa49a9184796d60544a3f33281c0a0000000013202c3946535f6c7986929faca79a8d8074675a4d413427242f3a434f59626d727f8b9299a2a69f959083796d605a5043392f24180c000000000000000000000000000000000915202b353f474e524c52575e61666a6f7274767878797978787675726f6d66626058534e4846423c332a1f140900000000000000000008121c262e363b3f404646464f5c6976828f9ca9aa9d9184776a5e51464646464646464646464646464639352f2820160c010000000000000000000000000000000714212d3a46535e697884919a9b9c9d96897c6f625a504a464440434044464b515c67717e8b98a3aeaa9b8f827568554b4135291d1104000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000a1623303d495663707c8996a3afa79a8e8174675b4e4134281b0700000000000911181d2124252c2b2a2928272622211f1b150e060000000000000000000000000000000000000000000713202d3a4653606d79869394949493867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000916232f3c4855616b76828f99a3afaea39891847a6d675e564e454039352f2d2a25282823282c2d31373c424a505a616c727f8b939ea8aca1978c8073695e52463a2d2014070013202c3946535f6c7986929facada09386797272727272727272727272727272727272727272727272727272727272727272726d675d5145392c201306000000000013202c3946535f6c7986929facada09386797272727272727272727272727272727272727272727272727272727272727272726d675d5145392c2013060000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000010c161f2a343c464e565e616b6f757b7f8285888a8c8d8f8f9090919191919292929292999ba3acafa396897c706356493d3023160a00000000000000000009141f2935414b555f6a6f7c858f939c9fa4a79f9d989892908f8d8d8c8c8b8b8b8b8a8a8a8d929da9afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000005111e2a36414c56626d75828f959fa7a8a097928a837f7c7a79797a7c7f848a9297a0a8a59e938d80736a60544a3f33281c0f0300000000000c18232e3944515c666f7c87929fa4a8a09590847d76716d6769676869676d70757b838e939ea7a59f93887d70665c5142382d22170b0000000013202c3946535f6c7986929faca79a8d8074675a4d4134271d28313d47515b636d727e879298a2a79f958e81756c61554b4035291d10040000000000000000000000000000010e1a26313d4751595e5f6060605e585f626568696b6c6c6c6c6b6a686663605c546060606055534d453c31261a0e020000000000000000010a141c242b2f33343939434f5c6976828f9ca9aa9d9184776a5e5144393939393939393939393939392c29241e160d040000000000000000000000000000000005121e2a36424d576774818e9aa6a9a89b8e81756c605c5453514a504a5153555d606d7983919daaaea2988b7e7165584b3e2f24180d01000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000815222f3b4855626e7b8895a9b3a89b8f8275685c4f422e23180c0000000009121b22292e3132393837363534332f2e2b262018100600000000000000000000000000000000000000000713202d3a4653606d798693a0a1a093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000005121e2a36424d5763707d89949fabb2a89f92867c6f685e554c443c342e2924201e1a1b1b171c1f20262b30383f44505a626d75818e96a0aca79f92867b6e6154473b2e2114080013202c3946535f6c7986929facb2a6998c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6054473a2d211407000000000013202c3946535f6c7986929facb2a6998c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f796d6054473a2d2114070000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000040d18222a343c444c52596063696e7276797b7d7f81828383848484848585858585868b909ba7afa396897c706356493d3023160a000000000000000000020d18242f3a434e585f6a6f7a82898f93999c9fa2aaa29f9d9b9a999998989898979797979a9da4aeafa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000714202d3946525e68727f8b949ea7a9a09591857e77726f6d686c6d6f72787e859196a0a9a59f93877c6f665b5044382b1f1308000000000007121d2834404a54606a727f8c929ca4a7a096918a827d7a7775747475767a7d818790959ea5a59e938d80736b60544b402f261c11060000000013202c3946535f6c7986929faca79a8d8074675a4d413427161f2c353f49515b636c717d869299a3a79e938a7e71675d5145382c1f1307000000000000000000000000000004111d2a36424e59636a6c6c6c6c6b636059585b5d5e5f5f5f5f5e5d5b59575f626a6c6c6c6c6c5f574d42372b1e1205000000000000000000020a12191f2326272d36434f5c6976828f9ca9aa9d9184776a5e5144372d2d2d2d2d2d2d2d2d2d2d2d201d19130c040000000000000000000000000000000000020e1a25313c4855626f7c88949faaaa9e938a7e726d6662605c545d545c6062676d75808d95a0aca99f92867a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3b0a396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000714212e3a4754616d7a8797a2ada99c90837669544a4034281c1004000006111b242d343a3d3e454444434241403c3b37322a22180e04000000000000000000000000000000000000000713202d3a4653606d798693a0aca093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000714212d3a46535e6975828f9ca6b0aca0968c7f736a60564c433a3228231d1814120e09060c1012131a1e262e343e48515b606d7984919ea09d95908a807366594d4033261a0d0013202c3946535f6c7986929facb9a89c918c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877b6e6154483b2e211508000000000013202c3946535f6c7986929facb9a89c918c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c877b6e6154483b2e2115080000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000050e171e252a323a41464f54575e6165666d6f717374757676777777787878787879797e8b98a4afa396897c706356493d3023160a0000000000000000000007131d28313c464e585f686d757c82878b8f929897999a9b9c9d9d9d9e9e9e9e9f9f9f9fa3abacb5afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000005111d2935414c56616e7a85929fa6ada19791837b716c6662605d606163656c717b849197a1ada4999184786c6053463a3025190d0100000000000c18232e39424e58626d73808c929ea1a8a19e948f8a8683828181828386898e93999fa7a39f938f81786d60594f42392e1d140a0000000000131f2c3946525f6c7985929faca79a8e8174675b4e4134281b1a232d373f49515a626b707d87929fa6a59e9184796d6053473a2f24180d010000000000000000000000000006121f2c3845525e6a757979797978706b605c544d5152535352524b515a61696e777979797976695f53463a2d2114070000000000000000000001080e1317191c2936434f5c6976828f9ca9aa9d9184776a5e5144372b202020202020202020201413110d0805030000000000000000000000000000000000000915212e3b47535f6a76828f98a2aea59f92877f78726f6d666a696a666d6f7379818d929da7aca2978d8074685d5246392d20130700000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3aca396897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000713202d3946525d687885929fabaa9e918477665c5144382c1f120600010c18222d363f454a4b5251504f4e4d4c4947433c342a20150a000000000000000000000000000000000000000713202d3a4653606d798693a0a7a093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000815212e3b4854616e7b87939facb2a89d9184796d60584e443a31292018120d0705020000000306090c151c2328363f45515d676f7d899395908a837e776c605346392d2013060013202c3946535f6c7986929facb9ada39c999999999999999999999999999999999999999999999999999999999999999994877b6e6154483b2e211508000000000013202c3946535f6c7986929facb9ada39c999999999999999999999999999999999999999999999999999999999999999994877b6e6154483b2e2115080000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000020c1720293036393a3e3f44484d5354545c606264666768696a6a6a6b6b6b6b6c6c6c717e8b98a4afa396897c706356493d3023160a00000000000000000000010c161f2a343c464e565e616b6f757b7f8285888a8c8d8f8f9090919191919292929292999ba3acafa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000713202d3946525e6874808d98a2aea69e92857b6e69615a5654525354535b60696e7b85929ea8aba0958a7d7063564c41362a1d1105000000000007121c27303d46515b646e73808a92979fa3a69f9c9992908f8e8e8f9092989b9fa4a69f99928c81786d665c50473d30271d0b020000000000121f2c3945525f6c7885929faba89b8e8275685b4f42302519111b252e373f485059606b717e8b949faba1968b7e7165554b4135291d1104000000000000000000000000000613202c3946535f6c7987868686847d736d665f5751464146454d555c606c717b83868686867b6e6155483b2e22150800000000000000000000000002070b101c2936434f5c6976828f9ca9aa9d9184776a5e5144372b1e13131313130b101316171e1a1613120f0b060300000000000000000000000000000006121f2b37434e58626f7c86929fa4aca399928b837f7b797777767777797c80858e939da4aea49a92857a6d61564c4135291d110500000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d89969f9f9f96897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0005111d2935414c566a7683909da9ac9f9286796d6053463a2d2013070005111d29343f485056585f5e5d5c5b5a5955534e463c32261b0f030000000000000000000000000000000000000713202d3a4653606d7986939a9a9a93867a6d6053473a2d201407000000000000000000000000000000000000000000000000000005121e2a36424d576673808d99a4afaca0968a7e71665c51463c32281f170e0700000000000000000000030a1117242935414b55606b75818e8a837d78706c655b5044372b1f12050013202c3946535f6c7986929facb9b5ada8a6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a194877b6e6154483b2e211508000000000013202c3946535f6c7986929facb9b5ada8a6a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a194877b6e6154483b2e2115080000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000008131e29323a4146474b4c4d4e4f51524a50535557595a5c5c5d5d5e5e5e5e5f5f5f65717e8b98a4afa396897c706356493d3023160a0000000000000000000000040d18222a343c444c52596063696e7276797b7d7f81828383848484848585858585868b909ba7afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000714212e3a4754616d7a86929faaab9f948a7d70695e575049474546474950565e69717e8b96a0aca79c8f8275685e5246392d2013070000000000000b151e2b343f49525c646e737e858e92999ea1a8a39f9d9c9a9b9c9d9fa3a9a29f9b948f877f776d665c544a3f352c1e150b000000000000121e2b3845515e6b7884919eaba99c8f827669564c41362a1e11131c252e363e474f59626d76828f9caaa99c908376675d5145392c20130600000000000000000000000000000b1825323e4b5865717e8b9296918780786e69625b524c4550575f676d747e869095948d8074695f53463a2d211407000000000000000000000000000003101c2936434f5c6976828f9ca9aa9d9184776a5e5144372b1e110600080f161c2022232b2723201f1b17120f0b0600000000000000000000000000030f1b26323c47535f6a717e8b939aa2aaa39f95918c8886848483838485898c92979ea5aaa39f93887d70685e52443a3024190d0100000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d899393939393897d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00010d192430414e5b6774818e9aa7afa399887b6f6255483c2e23180c060615212e3a45505a62656c6b6a69686766625f584e43372b1f13060000000000000000040607080808080808080813202d3a4653606d79868d8d8d8d8d86796d6053473a2d20140808080808080808070604000000000000000000000000000000000714212d3a46535f697784919eabb5ab9d9184786c60544b40342b20160d0500000000000000000000000000061218242f3a434f59616e7b837e78716c65605b53493f33271b0f030013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f94877b6e6154483b2e211508000000000013202c3946535f6c7986929facb9afa7a2a09f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f94877b6e6154483b2e2115080000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000010d1925303a444c525457595a5b5c5d5e5b5953484a4c4e4f5050515151515252525965727f8c98a5afa396897c706356493d3023160a0000000000000000000000050e171e252a323a41464f54575e6165666d6f717374757676777777787878787879797e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000005121e2a36424d5765727f8c98a2aea99c8f82766c61574d453e3a39393a3f444d57616c7784919eaaa99f93867a6d6154473a2e211407000000000000030c19222d37404a525c636c717a81868d9196989b9c9e9f9f9f9f9e9d9b9997928e89827c736c655c544b42382e231a0c03000000000000101d2a3643505d697683909ca9ab9e918478685e5246392d20140a131c242d353d47505a63707d8998a3ac9f92867a6d6054473a2d21140700000000000000000000000000000b1724313d4a56626d73808c9399938d837b726d615e56515a61696e79818a9298958f82786d60574d42372b1e1205000000000000000000000000000003101c2936434f5c6976828f9ca9aa9d9184776a5e5144372b1e070008111921272c2f3038342f2d2b27221f1c17110a020000000000000000000000000a15202b37434e58616c727f8892989fa3a7a09d99999291909090919298999ea2a9a69f98928b7f726c61564c4132281e13080000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000a1723303d4a5663707d868686868686867d7063564a3d3023170a00091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000081825313e4b5864717e8b97a7b1ab988b7e7165554b4034281d1413131624313d4a56626c71787777767574736f6a5f53473b2e211508000000000001070c101314151515151515151515202d394653606c7880808080808080786d6053463a2d201515151515151515151413100c0701000000000000000000000000000815222e3b4855616e7b8896a0acafa3998c7f72665b5042392e22190e0500000000000000000000000000000007131d28313d46535f696e77716c65605b53504941382d22170b000013202c3946535f6c7986929facb9a79d95939393939393939393939393939393939393939393939393939393939393939393877b6e6154483b2e211508000000000013202c3946535f6c7986929facb9a79d95939393939393939393939393939393939393939393939393939393939393939393877b6e6154483b2e2115080000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000005111d2a36414c565e6164656768696a6b68655d534840414243434444444545454d596673808c99a6afa295897c6f6256493c2f23160900000000000000000000020c1720293036393a3e3f44484d5354545c606264666768696a6a6a6b6b6b6b6c6c6c717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000714202d3a46525e697783909daaada197897d7063594f453b332d2c2d2d333b45505a66737f8c999d9c9c998a7d7063574a3d3024170a0000000000000007101b252e38404a525a61686d747b8084888b8e90919292929291908e8c8985817c766f6a605b534b423930261c1108000000000000000f1b2835424e5b6875818e9ba8ada196877a6e6154473b30251b1413121b232b353f4653606d7986929faca399897c6f6256493c2f23160900000000000000000000000000000915212e3a45505a636e74818e939f9590867e756d68605c606c717b838e939f969083796d665c50453c31261a0e02000000000000000000000000000003101c2936434f5c6976828f9ca9aa9d9184776a5e51442f24180d050f19232b33383c3d45403c3937332d2b28221c140b050000000000000000000000040f1a26313c46505a636d727e868e92999da0a8aba39f9e9d9c9d9e9fa2aaaaa29f9b948f867e726d62594f443a3020160c020000000000000000000000000000000000000000000000000000000000000000000000010b1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000916232f3c4855616b7079797979797979706b6155483c2f23160900091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000815212e3b4854616e7b87959faba89b8e8175675c5145392e2521201f202935404b5565717e8584838281807f7c6f6255493c2f22160900000000030b12181d1f20212121212121212121212b3844505b666c747474747474746d665c5044382c21212121212121212121201f1d18120b030000000000000000000000000c1825323f4b5865727e8b98a8b2ac9f92867a6e61544a3f30271d100700000000000000000000000000000000010c161f2a36424d575f616a64605b535049443f382f261b1106000013202c3946535f6c7986929facb9a2958b868686868686868686868686868686868686868686868686868686868686868686867b6e6154483b2e211508000000000013202c3946535f6c7986929facb9a2958b868686868686868686868686868686868686868686868686868686868686868686867b6e6154483b2e2115080000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000713202d3946525e686d71727374767778756f65594d3d323536373737383835404b556774818e9aa7b2a995887b6e6255483b2f2215080000000000000000000008131e29323a4146474b4c4d4e4f51524a50535557595a5c5c5d5d5e5e5e5e5f5f5f65717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000815212e3b4854616e7b87959fabab9e9184786c6053463e33292120202227333e4956626f7c899191908f8e8d8073665a4d4033271a0d000000000000000009131c262e38404850565e61696e73787c7e818384858686858583817f7c79746f6a625f585049413930271e150a00000000000000000c1926323f4c5965727f8c98a9b2a8978a7d7064564d42362b2621201f1f20232c3845515c667784919eaaab978a7d7164574a3e3124170b000000000000000000000000000005111d29343f48525b606d78818f959f98928b827a706b676d747e8690959d9891847b6e675d544a3f332a1f1409000000000000000000000000000000020f1c2935424f5c6875828f9ba8ab9e9184786b554b4035291d110b16212b353d44484a514d4946443f3938332d261d170e0500000000000000000000000a15202a343e48515b636c717b81878c919597999c9d9e9e9f9f9f9e9d9b9998928e89827b716c625b51473e32281e0e04000000000000000000000000000000000000000000000000000000000000000105090b0b0d0d1825313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000714202c38444f5961636c6c6c6c6c6c6c6361594f44382c20140700091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000714202d3a46525e697783909daaab9f9285796d60544b4036312d2c2c2d323a45515d6775818e91908f8e8d897c6f6356493c30231609000000030d151d24292c2d2e2e2e2e2e2e2e2e2e2e2e333f4a545b6067676767676767605c544a3f342e2e2e2e2e2e2e2e2e2e2e2d2c29241d150d030000000000000000000004101d2935404b556875828f9ba8b5a99c908376685e5242382d1e150b000000000000000000000000000000000000040d1a26313b454d53555d57535049443f38332d261d140a00000013202c3946535f6c7986929facada093867979797979797979797979797979797979797979797979797979797979797979797976695e52463a2d201407000000000013202c3946535f6c7986929facada093867979797979797979797979797979797979797979797979797979797979797979797976695e52463a2d2014070000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000714212e3a4754616d7a7e7f8081828485817568584e43372e2c2823282c2f3945515d677783909daaada196877a6d6054473a2d211407000000000000000000010d1925303a444c525457595a5b5c5d5e5b5953484a4c4e4f5050515151515252525965727f8c98a5afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1824313e4b5764717e8a97a7b1a79a8d8174665b5044382c2017131317202d3a4753606d79868584838281807e7164574b3e3124180b0000000000000000010a141c262e363e444c52575e61666a6f7274767878797978787675726f6d66626058534e443f382f271e150c030000000000000000091623303c4956636f7c8997a2ada89b8f8275695e52463f37312e2d2c2c2d2e343b45515d677885919eaba4978b7e7164584b3e3125180b0000000000000000000000000000010c18222d364044505c666d79829095a09f938f857d746f79818a9298a09992867c6f695e554b42382e21180e03000000000000000000000000000000020f1b2835424e5b6875818e9ba8ab9f928578675d5145392c2017161c27333d474f54565e5a5653504946443f382f2920170d0200000000000000000000030e18222d363f49515a61696e747b8084888b8d8f90919292929291908e8c8985817c766e69615a51493f352c20160c00000000000000000000000000000000000000000000000000000000000000060c111517181a1a1a25313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e0004101c27333d474f55566060606060606056554f473d33271c100400091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000005121e2a36424d5765727f8c98a2aea2988b7e71665c5146423b3a39383a3d444d57606d7a85929e9d9c9b9285796d6053463a2d2013070000010b151f272f35383a3b3b3b3b3b3b3b3b3b3b3b3b3b424a50535a5a5a5a5a5a5a53504a423b3b3b3b3b3b3b3b3b3b3b3b3b3a39352f271f150b0100000000000000000006131f2c3845515d677884919eabb6ac998c7f7266564c412f261c0c030000000000000000000000000000000000000009141f29333b424648504a46443f38332d27221b140b0200000013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5e574d42362a1e1205000000000013202c3946535f6c7986929facada093867a6d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5e574d42362a1e12050000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000815212e3b4854616e7b878c8d8e8f909184786a6054473f3a38342e34383a404b55606d7a86929facab9e918578675d5145392c20130600000000000000000005111d2a36414c565e6164656768696a6b68655d534840414243434444444545454d596673808c99a6afa295897c6f6256493c2f231609000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000010e1b2734414e5a6774818d9aa7b4aa978a7e7164544a3f33281a0e0606131f2c3845515c676d79787776757474716c6155493d3023170a000000000000000000020a131c242c323a41464d5254585f626568696b6c6c6c6c6b6a686663605c54544e47433c332d261d150c030000000000000000000713202d3a4653606d7985929fabac9f92877b6e615a5147433c3b3a38383a3b40444d56606d7a86939facaa978a7d7164574a3e3124170b00000000000000000000000000000006111b2428343f4a545d676d7a839196a19e979188807b838e929fa29f93877d706a5f574d433a30261c0f0600000000000000000000000000000000010d1a2734404d5a6773808d9aa6ac9f93867a6d6053473a2e262323262c38444f5960636b6762605b5353504a423b33291f1409000000000000000000000006101b242e373f4850575e61696e73777b7e80828484858686858583827f7d79756f6b625f5750483f372d231a0e040000000000000000000000000000000000000000000000000000000000000911181d21242527272727313e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e00000b16212c353d44484a535353535353534a48443d352c21160b0000091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000020e1a25303b4754616d7a86929fa9aa9e9184796d605b534d4847454546484f565e69727f8c98a2aaa69b8e8275665c5044382c1f1206000007121d27313940454748484848484848484848484848484848484d4d4d4d4d4d4d48484848484848484848484848484848484745403931271d12070000000000000000000714202d3a4753606d7a86939facafa49a897c6f6356493c3023140a0000000000000000000000000000000000000000030d17212931363a3b443e3937332d27221b17110a020000000013202c3946535f6c7986929facada093867a6d60606060606060606060606060606060606060606060606060606060606060605f524d453b30251a0e02000000000013202c3946535f6c7986929facada093867a6d60606060606060606060606060606060606060606060606060606060606060605f524d453b30251a0e020000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000714212d3a46535e697884919a9b9c9d96897c6f625a504a464440434044464b515c67717e8b98a3aeaa9b8f827568554b4135291d11040000000000000000000713202d3946525e686d71727374767778756f65594d3d323536373737383835404b556774818e9aa7b2a995887b6e6255483b2f221508000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000004111d2935414c566a7683909da9aea298887b6e6155483b2d2217080004101c2934404b555c606c6b6a6969686764615a5045392d21140800000000000000000000010a121a202830363b4246484e5361696b6c6c6c68605c545d5b595653514a47433d373127221b140b030000000000000000000006121f2c3844505c6674818e9ba6afa3998e81756c625b534e494746444446484a51575e68727e8b99a4aea398897c6f6256493c2f23160900000000000000000000000000000000091217232e38424b555d686e7b849197a2a19a938d8890959da59d928b7f726b61584e453b31281e140a0000000000000000000000000000000000000c1825323f4b5865727e8b98aaafa49a897c7063544b403631303031363f4854606b7078736f6c6563605b544d453b30251a0e02000000000000000000000009121c252e363e454d52575f62666a6e71737577787879797978777573706d67636059534d453e362d251b110800000000000000000000000000000000000000000000000000000000000009121b22292e313234343434343e4b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000005101a232c33383c3d464646464646463d3c38332c231a10050000091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000914202d3946525d6874808d97a2aca0968d80746d615e575554515153555960686e7b86929faaab9f94897c6f63544a3f34281c100300000c18242f39434b5153545454545454545454545454545454545454545454545454545454545454545454545454545454545453514b43392f24180c0000000000000000000915222f3c4855626f7b889aa4afac9f93867a6d6054473a2d211407000000000000000000000000000000000000000000060f171f262a2d2e37312d2b27221b17110b0600000000000013202c3946535f6c7986929facada093867a6d60535353535353535353535353535353535353535353535353535353535353534846423b33291f140900000000000013202c3946535f6c7986929facada093867a6d60535353535353535353535353535353535353535353535353535353535353534846423b33291f1409000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000005121e2a36424d576774818e9aa6a9a89b8e81756c605c5453514a504a5153555d606d7983919daaaea2988b7e7165584b3e2f24180d010000000000000000000714212e3a4754616d7a7e7f8081828485817568584e43372e2c2823282c2f3945515d677783909daaada196877a6d6054473a2d211407000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000713202c3945525d687885929fabac9f9285796c605346392d20130600000c18232f39434b51535f5e5e5d5c5b5a575550483e33281d1105000000000000000000000000080e161e252a30363a3c505d697378797979746d665e564e4c494644403937322b262017110a02000000000000000000000003101c28343f4a54626f7c89949fabab9e938b7e726d625f5856545351505355545c60696e7a85929eabac9f92867a6d6053473a2d201407000000000000000000000000000000000006111c263039434c565e696f7c859299a3a49f9a959da0a79e948d80746d62594f463c33291f160c02000000000000000000000000000000000000091623303c4956636f7c8998a2aeac998c8073665c5146423e3d3c3d4246515b63707d84807c78746f6c665e574d42362a1e11050000000000000000000000000a131c242c333b42464d5355575f626466696a6b6b6c6c6c6b6a686663605d55544f4c4841382f241b130900000000000000000000000000000000000000000000000000000000000006111b242d343a3d3e4040404040404b5864717e8b97a4b1a79a8e8174675b4e4134281b0e000008131e28313a414547494949494949494745413a31281e13080000091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000005111d2935414c56616d7a85929fa5a89d928c7f756e696461605d5c6062656b6f7a839198a2aea3999083766b605442382e23170c000004101d2935404b555d606161616161616161616161616161616161616161616161616161616161616161616161616161616161605d554b4035291d100400000000000000000b1724313e4a5764717d8a97acb6aa9e918477675d5145392c20130600000000000000000000000000000000000000000000060d141a1e21222a24201f1b17110b06000000000000000013202c3946535f6c7986929facada093867a6d60534746464646464646464646464646464646464646464646464646464646463b3a36302921170d0200000000000013202c3946535f6c7986929facada093867a6d60534746464646464646464646464646464646464646464646464646464646463b3a36302921170d02000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000020e1a25313c4855626f7c88949faaaa9e938a7e726d6662605c545d545c6062676d75808d95a0aca99f92867a6d6154473a2e211407000000000000000000000815212e3b4854616e7b878c8d8e8f909184786a6054473f3a38342e34383a404b55606d7a86929facab9e918578675d5145392c201306000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000714212d3a4754606d7a8797a2adaa9d918477655b5044372b1f1205000007121d273139404547525251504f4e4d4b49453e362c22170c0000000000000000000000000000050c13191f252a3845525f6b788586868681786d685f584f473f38342e2b27201b150b0600000000000000000000000000000c17232e384754606a76828f99a3aea59f92877f756f6a666261605c5c606164666d727b839097a1ada59c8f8275675d5145392c1f13060000000000000000000000000000000000000a141e27313a444d575f6a707d879299a49f9f9f9fa9a0958f82786d605b51473e342a21170d04000000000000000000000000000000000000000714202d3a4753606d7985929facab9e9185796d605a534d4b4a494a4d535b626d76828f8d8984807c786e695e52463a2d201407000000000000000000000000020e1925303b444c525f6060606060605d5c5d5e5f5f5f5f5e5d5b6060606060605a58534a41362b2014080000000000000000000000000000000000000000000000000000000000010c18222d363f454a4b4d4d4d4d4d4d4d5864717e8b97a4b1a79a8e8174675b4e4134281b0e00010d19242f3a434c52545656565656565654524c433a2f24190d0100091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000000010d1924303a46525e68727e8b939ea7a49c918c827b75716e6d67666d6f71767d849195a0aaa69f92877c6f63594f4330261c1106000006131f2c3845515d676d6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d675d5145392c1f130600000000000000000c1926323f4c5965727f8c98a5b2a99c8f837669554b4135291d1104000000000000000000000000000000000000000000000003090e1214151d1713120f0b060000000000000000000013202c3946535f6c7986929facada093867a6d6053473a393939393939393939393939393939393939393939393939393939392e2d2a251f170f050000000000000013202c3946535f6c7986929facada093867a6d6053473a393939393939393939393939393939393939393939393939393939392e2d2a251f170f0500000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000915212e3b47535f6a76828f98a2aea59f92877f78726f6d666a696a666d6f7379818d929da7aca2978d8074685d5246392d201307000000000000000000000714212d3a46535e697884919a9b9c9d96897c6f625a504a464440434044464b515c67717e8b98a3aeaa9b8f827568554b4135291d1104000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000815222f3b4855626e7b8895a9b3a99c8f82766953493f33271b0f030000010b151f272f34383a464544434241413e3d39332c241a100600000000000000000000000000000002080d141a26323f4c5965727f8c93938e827a6f6a615951444039302820180f0a0300000000000000000000000000000006111c2b38434e58626f7c87929fa5afa399928b817c76726f6e6d66666d6e7074797f859095a0a9a89e93897d7063554b4035291d1004000000000000000000000000000000000000020c151f28323b454e58606b717e8793939393939393969083796d665c50493f352c22190f05000000000000000000000000000000000000000006131f2c3845515c6775828f9ba7ada1978c80736c615f5757565657575f616d727f8b949a96918d89857b6e6154473b2e21140800000000000000000000000005111e2a36414c565e6c6c6c6c6c6c6c6a675f555253534f5960636c6c6c6c6c6c67645c53483c3024180b000000000000000000000000000000000000000000000000000000000005111d29343f485056585a5a5a5a5a5a5a5a64717e8b97a4b1a79a8e8174675b4e4134281b0e0004111d2935414c565d6062626262626262605d564c4135291d110400091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b0000000008131e2a36414c56626d75818e959fa6a49c948f86827e7b7a7979797b7e83899196a0a7a59e948c7f736b6054473d321e150a0000000714202d3a4753606d797b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b796d6053473a2d20140700000000000000000d192633404c5966737f8c99a6b2a89b8e8175685b4e422f24180d010000000000000000000000000000000000000000000000000002050708110b06050300000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d21201e1a140d05000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d21201e1a140d050000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000006121f2b37434e58626f7c86929fa4aca399928b837f7b797777767777797c80858e939da4aea49a92857a6d61564c4135291d11050000000000000000000005121e2a36424d576774818e9aa6a9a89b8e81756c605c5453514a504a5153555d606d7983919daaaea2988b7e7165584b3e2f24180d01000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000091623303c4956636f7c8996a2afa89b8e8175685b4e422d22170b00000000030d151d23292c2d3938373636353431302d28221a120800000000000000000000000000000000000003091825313e4a56626d75818f969490847c706b625b514a423a322a21191106000000000000000000000000000000000f1b27323d47535f6a727f8c939da5aba39f938e87827f7c7a797879797b7d81858b9297a0a7a8a0968f82756b605443392f24180c0000000000000000000000000000000000000000030d162029333c464f59616c727f8686868686868686847b6e675d544a3f372d231a100700000000000000000000000000000000000000000004101c2934404b5563707d8a95a0aca99f93887e746e69666463636366696e757f87939fa6a19e9a908377695e52463a2d2014070000000000000000000000000714202d3946525e68767979797979797771675b4f464854606b70797979797979746e64584c4033271a0d01000000000000000000000000000000000000000000000000000000000915212e3a45505a6265676767676767676767717e8b97a4b1a79a8e8174675b4e4134281b0e000613202c3945525d686d6f6f6f6f6f6f6f6d685d5245392c20130600091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b00000000020d1925303a44515b606d798390949da5a69e98928f8b8887858586888b90949ea1a8a39f938e82786d60594f43352b210c030000000a1723303d4a5663707d87878787878787878787878787878787878787878787878787878787878787878787878787878787877e7164574a3e3124170b00000000000000000d1a2734404d5a6773808d9aa6b3a79a8d8074675a4d4134271a07000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2020202020202020202020202020202020202020202020202020201514120e090200000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d2020202020202020202020202020202020202020202020202020201514120e0902000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000030f1b26323c47535f6a717e8b939aa2aaa39f95918c8886848483838485898c92979ea5aaa39f93887d70685e52443a3024190d0100000000000000000000020e1a25313c4855626f7c88949faaaa9e938a7e726d6662605c545d545c6062676d75808d95a0aca99f92867a6d6154473a2e21140700000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1724303d4a5763707d8a96a3b0a79a8d8174675a4e4134271b060000000000030b12181c1f202c2b2b2a2928272423211d17100800000000000000000000000000000000000000000916222e3a46515b606d7a8491989691867d726d605c544c443c332b2317110a0200000000000000000000000000000a16202b37434e58606c77818e939fa2aaa59e9a938f8c898786858586888a8d92979ea1a9a59e9691847a6d61594f4431271d1207000000000000000000000000000000000000000000040e17212a343d47505a626d727979797979797979786e695e554b42382e251b110800000000000000000000000000000000000000000000000c18232f394653606c7883909aa4afa49a938b817b767371706f7072767b818b9399a4afa99f948a7e7164574d42362a1e11050000000000000000000000000814212e3b4754616e7a86868686868683776a5d5144495663707d8686868686868074675a4e4134271b0e01000000000000000000000000000000000000000000000000000000000b1724313d4a56626d71737373737373737373737e8b97a4b1a79a8e8174675b4e4134281b0e000714212d3a4754606d7a7c7c7c7c7c7c7c7a6d6054473a2d21140700091623303c4956636f7c8996a2afa4978a7d7164574a3e3124170b000000000008131e28323f45515d676d7a828e939da0a7a39f9b97949892929895989c9fa6a7a099928d81786d665c50463d3223190f000000000a1723303d4a5663707d899494949494949494949494949494949494949494949494949494949494949494949494949494948a7d7164574a3e3124170b00000000000000000e1b2734414e5a6774818d9aa7b3a69a8d8073675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20141313131313131313131313131313131313131313131313131308070502000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201413131313131313131313131313131313131313131313131313080705020000000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000a15202b37434e58616c727f8892989fa3a7a09d99999291909090919298999ea2a9a69f98928b7f726c61564c4132281e13080000000000000000000000000915212e3b47535f6a76828f98a2aea59f92877f78726f6d666a696a666d6f7379818d929da7aca2978d8074685d5246392d20130700000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1724313d4a5764707d8a97a3b0a79a8d8074675a4d4134271a0e01000000000001070c1013141f1f1e1d1c1b1a181714110c0600000000000000000000000000000000000000000006121e29353f45525d686f7c86929f9892877f746d665d564d453d3528231c140c0300000000000000000000000000040f1b26323c44505b656d78818b92989fa4aca49f9c9995949892929894979a9ea1a9a7a09d938f847b6e685d52473d331f150b0100000000000000000000000000000000000000000000050f18222b353e48515b62656c6c6c6c6c6c6c6c6b615e574d433a30261c130900000000000000000000000000000000000000000000000007121f2b3844505b66707d88939fa5aca49f938e8783807e7d7c7d7f82878e939fa4aba9a1978f82766c6155453b30251a0e020000000000000000000000000814212e3b4754616e7a87939393939084776a5d5144495663707c89939393938d8174675a4e4134271b0e01000000000000000000000000000000000000000000000000000000000b1825323e4b5865717f80808080808080808080828f9ca9b4a79a8e8174675b4e4134281b0e000a1723303d4a5663707d898989898989897d7063564a3d3023170a00091623303c4956636f7c8996a2aca4978a7d7164574a3e3124170b0000000000020c16202935404b555d686d78818991959c9fa3aba4aaa29f9fa2aaa4aba49f9c95908780786d665c544a3f342b211007000000000a1723303d4a5663707d8996a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1978a7d7164574a3e3124170b00000000000000000e1b2835414e5b6874818e9ba7b3a6998c807366594d4033261a0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0b0a080500000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d20140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0b0a0805000000000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000040f1a26313c46505a636d727e868e92999da0a8aba39f9e9d9c9d9e9fa2aaaaa29f9b948f867e726d62594f443a3020160c0200000000000000000000000006121f2b37434e58626f7c86929fa4aca399928b837f7b797777767777797c80858e939da4aea49a92857a6d61564c4135291d110500000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1724313e4a5764717d8a97a4b0a69a8d8073675a4d4034271a0d010000000000000000040607131211100f0e0e0b0a08050000000000000000000000000000000000000000000000010d18232935414c565f6a727e8b939e99938c81786d685f574f473f342e261e150c03000000000000000000000000000a152027333f49535c666d747f868e939a9ea1a8a7a5a2aaa29f9fa2aaa3a7aaa29f9b959089827a6e695e564c41352b210d03000000000000000000000000000000000000000000000000061019232c363f4951565860606060606060605e54524d453b31281e140a01000000000000000000000000000000000000000000000000030f1c28333f4a54606b73808d939da4aca59d99938f8c8a89898a8c8f93999ea5aea79f9791857b6e615a504533291f1409000000000000000000000000000814212e3b4754616e7a87949f9f9d9084776a5d5144495663707c89969f9f9a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000000000000003101d293643505c6976828d8d8d8d8d8d8d8d8d8d8f949eaab4a79a8e8174675b4e4134281b0e000a1723303d4a5663707d899595959595897d7063564a3d3023170a00091623303c4956636f7c89969f9f9f978a7d7164574a3e3124170b000000000000050e18242f3a434c565d666d747d848a8f92999a9c9e9e9f9f9e9d9c9a99938f8a837c736c665c544a42382e22190f00000000000a1723303d4a5663707d89969f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b00000000000000000e1b2835414e5b6874818e9ba7b3a6998d8073665a4d4033271a0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a171714110c050000000000000013202c3946535f6c7986929facada093867a6d6053473a2d201a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a171714110c0500000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000a15202a343e48515b636c717b81878c919597999c9d9e9e9f9f9f9e9d9b9998928e89827b716c625b51473e32281e0e0400000000000000000000000000030f1b26323c47535f6a717e8b939aa2aaa39f95918c8886848483838485898c92979ea5aaa39f93887d70685e52443a3024190d0100000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1724313d4a5764707d8a97a3b0a79a8d8074675a4d4134271a0e010000000000000105090b0b121111100f0e0d09080603000000000000000000000000000000000000000000000000070d19242f3a434e58626d75818e95a09f928e827a6e69605951443f3830271e150b00000000000000000000000000040b17222d38414a545c606d727b81878d9196989a9c9d9e9f9f9f9e9d9d9b9898928e8a837d756d685e574d443a3023190f000000000000000000000000000000000000000000000000000007111a242d373f464a4c5353535353535353524846423b33291f160c0200000000000000000000000000000000000000000000000000000b17222d38424f59606c78818d929ea0a8aba49f9c9997969696999c9fa4abaaa29f9590857c6f695e53483e3420170d02000000000000000000000000000814212e3b4754616e7a8794a1aa9d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000000000000003101d293643505c6976838f9a9a9a9a9a9a9a9a9a9c9ea6b0b4a79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a2a2a296897d7063564a3d3023170a00091623303c4956636f7c8993939393938a7d7164574a3e3124170b0000000000000007131d28313a444c545c606b70787e82868a8d8f9192929291918f8d8a86827d786f6a605b544a423930261c100700000000000a1723303d4a5663707d899393939393939393939393939393939393939393939393939393939393939393939393939393938a7d7164574a3e3124170b00000000000000000e1b2734414e5a6774818d9aa7b3a69a8d8073675a4d4034271a0d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a2d27272727272727272727272727272727272727272727272727272727272423211c17100800000000000013202c3946535f6c7986929facada093867a6d6053473a2d27272727272727272727272727272727272727272727272727272727272423211c171008000000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000030e18222d363f49515a61696e747b8084888b8d8f90919292929291908e8c8985817c766e69615a51493f352c20160c0000000000000000000000000000000a15202b37434e58616c727f8892989fa3a7a09d99999291909090919298999ea2a9a69f98928b7f726c61564c4132281e13080000000000000000000000000000000203101d2a3643505d69768390908376695d5043362a1d100302000000000000000a1724303d4a5763707d8a96a3b0a79a8d8074675a4d4134271a0e010000000000060c111517181f1e1d1c1b1a191615130f0a04000000000000000000000000000000000000000000000008131e28313c46515b606d79839198a29d948f847b706b625b504a423930271d12070000000000000000000000000006111b262f38424a505b62696e757b8084888b8d8f90929292929191908e8b8985817d78706b605d564d453b32281e110700000000000000000000000000000000000000000000000000000008121b252d343a3e3f4646464646464646453b3a36302921170d0400000000000000000000000000000000000000000000000000000006111c262f3d44505b666d78808a91969d9fa7a7a9a6a4a3a2a3a5a9a7a8a09e98928c837b6f6a5f574d42362c220e0500000000000000000000000000000814212e3b4754616e7a8794a1a99d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000000000000003101d293643505c6976838f9ca6a6a6a6a6a6a6a6a9aab0acaca79a8e8174675b4e4134281b0e000a1723303d4a5663707d8996a3aca396897d7063564a3d3023170a00091623303c4956636f7d868686868686867e7164574a3e3124170b00000000000000010c161f28323a424b515960666c71767a7d808284858686858483807d7a75706c666058504a423930271e140a0000000000000a1723303d4a5663707d86868686868686868686868686868686868686868686868686868686868686868686868686868686867e7164574a3e3124170b00000000000000000d1a2734404d5a6773808d9aa6b3a79a8d8174675a4e4134271b09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343431302d28221a1208000000000013202c3946535f6c7986929facada093867a6d6053473a34343434343434343434343434343434343434343434343434343434343431302d28221a12080000000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000006101b242e373f4850575e61696e73777b7e80828484858686858583827f7d79756f6b625f5750483f372d231a0e04000000000000000000000000000000040f1a26313c46505a636d727e868e92999da0a8aba39f9e9d9c9d9e9fa2aaaaa29f9b948f867e726d62594f443a3020160c0200000000000000000000000000050a0f12101d2a3643505d69768390908376695d5043362a1d10120f0a0500000000000a1623303d495663707c8996a3afa79a8e8174675b4e4134281b0700000000000911181d2124252c2b2a2928272622211f1b150e0600000000000000000000000000000000000000000000010c161f2a343f45515d676e7c86929fa59f9691857d726d605c544b42392e23180c00000000000000000000000000000a141d2630383f4451575f61696e73787b7e80828485858685858483817f7c7a75706d666059524c443b332920160c000000000000000000000000000000000000000000000000000000000009131b23292e31323939393939393939382e2d2a251f170f0500000000000000000000000000000000000000000000000000000000000a141d28333f4a545c666d747d848b9095979a9c9e9f9f9f9f9e9d9a9896918c857f786e695f584e453b31241a100000000000000000000000000000000814212e3b4754616e7a87949c9c9c9084776a5d5144495663707c89969c9c9a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000000000000003101d293643505c6976838f9c9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675b4e4134281b0e000a1723303d4a5663707d89969f9f9f96897d7063564a3d3023170a000915222f3b4854606b6f79797979797979716c6155493c3023170a0000000000000000040d162028303940454f545b6064686e7174767778797978777673716e6863605b544e443f382f271e150c020000000000000916232f3c4855616b707979797979797979797979797979797979797979797979797979797979797979797979797979797979716c6155493c3023170a00000000000000000d192633404c5966737f8c99a6b2a89b8f8275685c4f4230251a0e020000000000000000000000000000000000000000000000000000010203000000000000000000000000000000000013202c3946535f6c7986929facada093867a6d605347404040404040404040404040404040404040404040404040404040404040403e3c39332c241a10050000000013202c3946535f6c7986929facada093867a6d605347404040404040404040404040404040404040404040404040404040404040403e3c39332c241a100500000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000009121c252e363e454d52575f62666a6e71737577787879797978777573706d67636059534d453e362d251b110800000000000000000000000000000000000a15202a343e48515b636c717b81878c919597999c9d9e9e9f9f9f9e9d9b9998928e89827b716c625b51473e32281e0e04000000000000000000000000010910161b1e20202a3643505d69768390908376695d5043362a20201e1b161009010000000815222f3b4855626e7b8895a9b3a89b8f8275685c4f422e23180c0000000009121b22292e3132393837363534332f2e2b262018100600000000000000000000000000000000000000000000040d18222935404b555f6a717e8a939da7a09792877f746d665c544b4034281c100400000000000000000000000000020b151e262e343f454d53575f6266696e71747677787979797877767472706d6763605c544f45413a322921170e040000000000000000000000000000000000000000000000000000000000010911181e2224252d2d2d2d2d2d2d2d2b21201e1a140d05000000000000000000000000000000000000000000000000000000000000020b17222d38424a545c606b70797e83878b8d8f919292929291908e8b88847f7a736d665f574e463c33291f12090000000000000000000000000000000814212e3b4754616e7a878f8f8f8f8f84776a5d5144495663707c898f8f8f8f8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000000000000003101d293643505c6976838f939393939393939393939393939393938e8174675b4e4134281b0e000a1723303d4a5663707d899393939393897d7063564a3d3023170a0007131f2c38434f5960636c6c6c6c6c6c6c64615a5045392d211408000000000000000000040d161e272e343d424a5053565e616467696b6b6c6c6b6a696764615e5653504a423c332d261d150c03000000000000000714202c38444f5961636c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d21140800000000000000000b1825313e4b5864717e8b97a4b1a99d9083766a574d42362a1e1105000000000000000000000000000000000000000000000003080c0e0e0f0b0707040100000000000000000000000013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4a49453e362c22170c0000000013202c3946535f6c7986929facada093867a6d60534d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4a49453e362c22170c00000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000a131c242c333b42464d5355575f626466696a6b6b6c6c6c6b6a686663605d55544f47423c332d241b1309000000000000000000000000000000000000030e18222d363f49515a61696e747b8084888b8d8f90919292929291908e8c8985817c766e69615a51493f352c20160c000000000000000000000000010a131b21272b2d2d2d3643505d69768390908376695d5043362d2d2d2b27211b130a0100000714212e3a4754616d7a8797a2ada99c90837669544a4034281c1004000006111b242d343a3d3e454444434241403c3b37322a22180e0400000000000000000000000000000000000000000000071018242f39434e58616c74818e95a0a9a299928b80786d665c5145382c1f13060000000000000000000000000000030c151c2328333c42464d5355575f626567696a6b6c6c6c6b6a6a686563605d5553504a423d35302820170f050000000000000000000000000000000000000000000000000000000000000000060d1216181920202020202020201f1514120e0902000000000000000000000000000000000000000000000000000000000000000006111c262f38424a505961666d71767b7e818384858686858483817f7b77736d68605c544d453c342a21170d000000000000000000000000000000000714212d3a4754606d7a8283838383838174675b4e414855626f7c8283838383827f7265584c3f3225190c0000000000000000000000000000000000000000000000000000000003101d293643505c6976828686868686868686868686868686868686868174675b4e4134281b0e000a1723303d4a5663707d868686868686867d7063564a3d3023170a00030f1b27323d474f545660606060606060575550483e33281c110400000000000000000000040c151d23282f383f44464c5254575a5c5e5f5f5f5e5e5c5a5754524c46443f382f28221c140b03000000000000000004101c27333d474f55566060606060606060606060606060606060606060606060606060606060606060606060606060606060575550483e33281c110400000000000000000a1723303d4a5663707d8996aab4ab9f928578695e52463a2d20140700000000000000000000000000000000000000000001090f14181a1b1c181413110d08050100000000000000000013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a575550483e33281c110500000013202c3946535f6c7986929facada093867a6d605a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a575550483e33281c1105000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000010a121a212930363c4247484e5355596063676a6b6c6b6a666260585653514b48433d37312a211b1209010000000000000000000000000000000000000006101b242e373f4850575e61696e73777b7e80828484858686858583827f7d79756f6b625f5750483f372d231a0e0400000000000000000000000009131c252c33373939393943505d69768390908376695d50433939393937332c251c130900000713202d3946525d687885929fabaa9e918477665c5144382c1f120600010c18222d363f454a4b5251504f4e4d4c4947433c342a20150a000000000000000000000000000000000000000000000007121d28313c46505a606d7983909893939393928d82796d6053463a2d201307000000000000000000000000000000030a1117212a31373c4247484d5355585a5c5d5f5f5f5f5e5e5d5b585653514b46443f383029241e160e05000000000000000000000000000000000000000000000000000000000000000000000106090b0c1313131313131313120807050200000000000000000000000000000000000000000000000000000000000000000000000a141d2630383f444f545c6064696e7174767778797978787674726f6a66605d56514a423c332a22180f05000000000000000000000000000000000713202c3945525d686d767676767676746f64584c4047535f6a6f767676767676726d62564a3e3125180b00000000000000000000000000000000000000000000000000000000020f1c2835414e5a667076797979797979797979797979797979797979746f64594c4033271a0d000916232f3c4855616b7079797979797979706b6155483c2f23160900000a16212b353d434849535353535353534a49453e362c22170c000000000000000000000000030b12181d262d33383b4146474a4d4f515253535251504d4a4746413b38332d261d17110a02000000000000000000000b16212c353d44484a53535353535353535353535353535353535353535353535353535353535353535353535353535353534a49453e362c22170c0000000000000000000815222e3b4855616e7b8898a2aeada297877b6e6154473b2e21140a0000000000000000000000000000000000000000030b131a20242728292521201d1913110d08020000000000000013202c3946535f6c7986929facada093867a6d6767676767676767676767676767676767676767676767676767676767676767676764615a5045392d21140800000013202c3946535f6c7986929facada093867a6d6767676767676767676767676767676767676767676767676767676767676767676764615a5045392d211408000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000080f171f252a31373e4850585f626b6f737778797877736f6a615f574f473d38322b2620180f090000000000000000000000000000000000000000000009121c252e363e454d52575f62666a6e71737577787879797978777573706d67636059534d453e362d251b110800000000000000000000000005101b252e373e434646464646505d69768390908376695d504646464646433e372e251b10050005111d2935414c566a7683909da9ac9f9286796d6053463a2d2013070005111d29343f485056585f5e5d5c5b5a5955534e463c32261b0f0300000000000000000000000000000000000000000000010c161f2a343e45515c676e7b8586868686868686867a6e6154473b2e2114080000000000000000000000000000000000060f181f262b31373a3c4247484b4d4f51525253525251504e4c494745403a38342e261e19130c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141e262e343e424a5153575e616467696b6c6c6c6c6b6a6765625f5854524c444039302a21181006000000000000000000000000000000000004111d2935414c565d6069696969696967645c53483c434e585f6269696969696965625b51463a2e22160900000000000000000000000000000000000000000000000000000000000d1926323e49545e66696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c67645d53483c3024180b000714202c38444f5961636c6c6c6c6c6c6c6361594f44382c2014070000040f19232b32383b3c464646464646463e3c39332c241a10050000000000000000000000000000070b141c22282b3036393b3e414344454646454443403e3b3936302b28221c140b0600000000000000000000000005101a232c33383c3d46464646464646464646464646463f44464f4f4f4f4f4f4f46444046464646464646464646464646463e3c39332c241a10050000000000000000000613202d394653606c7985929facb3a9968a7d7063574a3d31261b0f01000000000000000000000000000000000000000b151d252b30343536312d2c2924201d19130c0701000000000013202c3946535f6c7986929facada09386797373737373737373737373737373737373737373737373737373737373737373737373716c6155493c3023170a00000013202c3946535f6c7986929facada09386797373737373737373737373737373737373737373737373737373737373737373737373716c6155493c3023170a000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000050d15202a333e47505a616a6f767c808385868583807c756e6960594f473d32291f150e060000000000000000000000000000000000000000000000000a131c242c333b42464d5355575f626466696a6b6b6c6c6c6b6a686663605d55544f47423c332d241b1309000000000000000000000000000a16212c3740494f5353535353535d69768390908376695d5353535353534f4940372c21160a00010d192430414e5b6774818e9aa7afa399887b6f6255483c2e23180c060615212e3a45505a62656c6b6a69686766625f584e43372b1f13060000000000000000000000000000000000000000000000040d18222934404b555f696e78797979797979797976685e5246392d201407000000000000000000000000000000000000060e141a1f262b2e31373a3b3e41434445464646454443413f3d3a39352f2b28231c140c0802000000000000000000000000000000000000000000000000030608090f1112131313110f0c0707050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c141c232830394044464d5254585a5c5e5f5f5f5f5e5d5b5855534e4745413a342e271e180f06000000000000000000000000000000000000010d1924303a444c52545c5c5c5c5c5c5b58534a41363c464e53555c5c5c5c5c5c585651493f34291e120600000000000000000000000000000000000000000000000000000000000915212d38424c545a5c6060606060606060606060606060606060605b59534a41362b2014080004101c27333d474f55566060606060606056554f473d33271c100400000007101921272c2f303939393939393931302d28221a120800000000000000000000000000000000020a11171c1f252a2d2e3134363838393938373634312e2d2a251f1c17110a02000000000000000000000000000008111a21272c2f3039393939393939393939392d38424a50535c5c5c5c5c5c5c53514a42392e393939393939393939393931302d28221a12080000000000000000000006121f2b3844505b667683909ca9b3a79a8d807467584e43372b1e1308000000000000000000000000000000000000060f1d272f373c4041423e3a39352f2d29251e18120b030000000013202c3946535f6c7986929facb3a79a8d8080808080808080808080808080808080808080808080808080808080808080808080807e7164574a3e3124170b00000013202c3946535f6c7986929facb3a79a8d8080808080808080808080808080808080808080808080808080808080808080808080807e7164574a3e3124170b000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000020e1a26313c454f59616c707c82898d90929291908d88827b706b60594f443b3025190e02000000000000000000000000000000000000000000000000010a121a212930363c4247484e5355585a5c5d5e5f5a61646c6c6c6c66635c5248433d37312a211b120901000000000000000000000000000f1b27333e49525a5f60606060606069768390908376696060606060605f5a52493e33271b0f0000081825313e4b5864717e8b97a7b1ab988b7e7165554b4034281d1413131624313d4a56626c71787777767574736f6a5f53473b2e211508000000000000000000000000000000000000000000000000060f18232f39434d575f616c6c6c6c6c6c6c6c6c6c5e564c41362a1e11050000000000000000000000000000000000000003090e151a1e21262b2e2f32343637383939393837373532302d2c29241f1c17110a02000000000000000000000000000000000000000000000000030a0f1215151c1e1f1f201f1e1c181413110d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171e272e34383b4246484b4e50515253535251504e4c4847433c39353028231c150c06000000000000000000000000000000000000000008131e28323a4145475050505050504e4c4841382f343c4347485050505050504c4a463f372d23180d01000000000000000000000000000000000000000000000000000000000005101b26303a42494e505353535353535353535353535353535353534e4c4841382f251a0f0300000b16212c353d44484a535353535353534a48443d352c21160b0000000000070f161b1f22232d2d2d2d2d2d2d2423211c17100800000000000000000000000000000000000000060b0f14191e20212427292b2c2c2c2b2b29272421201e19140f0b0600000000000000000000000000000000000810161c2023232d2d2d2d2d2d2d2d2d2d28333f4a545b6068686868686868605c544a4034282d2d2d2d2d2d2d2d2d2d2423211c1710080000000000000000000000030f1c28333f4a546774808d9aaab4aa9d9184776a5f53473a2f24190b0200000000000000000000000000000000030e18212f3941484d4e4f4b4745413a39353029241d150d0300000013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8174675b4e4134281b0e01000013202c3946535f6c7986929facb9a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8174675b4e4134281b0e010000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000006121e2b37424d57616c707e868f949a9c9998999c99938f857d706b60564d42362a1f14080000000000000000000000000000000000000000000000000000080f171f252a31373a3c4247484b4d4f4a505b636c7079797979736e63574b3f322b2620180f09000000000000000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c7683909083766c6c6c6c6c6c6c6c645a4f43372b1e1200000815212e3b4854616e7b87959faba89b8e8175675c5145392e2521201f202935404b5565717e8584838281807f7c6f6255493c2f2216090000000000000000000000000000000000000000000000000007121d27313c454d53555f60606060606060605f524c443b3025190e0200000000000000000000000000000000000000000003090e12151a1e21222527292a2c2c2c2c2b2b2a282523201f1d1812100b0600000000000000000000000000000000000000000000000000060e151b1f2122282a2b2c2c2c2b292521201d19130d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c151c23282c30363a3b3e414344454646454543413f3c3a37312c29241e18120b03000000000000000000000000000000000000000000020c1620283035393a43434343434341403c362f262a32373b3c4343434343433f3e3a342d251b1107000000000000000000000000000000000000000000000000000000000000000a141e2830383e414346464646464646464646464646464646464641403c362f261d130800000005101a232c33383c3d464646464646463d3c38332c231a1005000000000000040a0f13151620202020202020171714110c050000000000000000000000000000000000000000000003080d111414171a1c1e1f20201f1e1d1a171414110e08030000000000000000000000000000000000000000050b101416172020202020202020201f2b3844505b666c757575757575756d665c5144382c1f202020202020202020171714110c05000000000000000000000000000b17222d3d4a5763707d8a98a2aeaca095887c6f62564c4135291d140a000000000000000000000000000000000915202a33414b53595b5c5854524c4746413a352f271f150b01000013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675b4e4134281b0e01000013202c3946535f6c7986929facb9aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8e8174675b4e4134281b0e010000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000814212e3a47535f69707e87929899938f8c8b8c90949e9792877d6f695e52463b3025190e020000000000000000000000000000000000000000000000000000050d141a1f262b2e31373a3b3e444c545c606d727e868686868073665a4d4033271a150e060000000000000000000000000000000013202d3946535f6c767979797979797979839090837979797979797979766c5f5346392d201300000714202d3a46525e697783909daaab9f9285796d60544b4036312d2c2c2d323a45515d6775818e91908f8e8d897c6f6356493c3023160900000000000000000000000000000000000000000000000000010b151f2a333c4246485253535353535353535346413b32291e14080000000000000000000000000000000000000000000000000206090e121415181a1c1e1f1f201f1f1e1d1b19161413100c0703000000000000000000000000000000000000000000000000000006101820262b2e2f3537383939393835322e2d2a251e19130c04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b12181c1f252a2d2e3134363839393939383734322f2e2b26201d19130c07000000000000000000000000000000000000000000000000040e161e24292c2d3636363636363433302b251d20262b2e2f36363636363632312e29231b13090000000000000000000000000000000000000000000000000000000000000000030c161e262d3235363939393939393939393939393939393939393433302b251d140b010000000008111a21272c2f3039393939393939302f2c27211a110800000000000000000003070909131313131313130b0a08040000000000000000000000000000000000000000000000000000010507080b0e10111213131211100d0b080705020000000000000000000000000000000000000000000000000407090a131313131313131313202d394653606c7881828282828281796d6053463a2d201313131313131313130b0a08040000000000000000000000000000000614202d3a4753606d7985929facb1a79a8d8073685d52453b2f261b1106000000000000000000000000000006101a26313c45535d64686964605d5654524c45403931271d1207000013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69a8e8174675b4e4134281b0e01000013202c3946535f6c7986929facacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a69a8e8174675b4e4134281b0e010000000000000000020714202d3a4753606d7a8693a0acac9f9286796c5f5346392c2013070502000000000000000000000000000000000006121f2b37434e58626e7b869299959187827f7f80838991969992857b6e61564d41362a1e110500000000000000000000000000000000000000000000000000000002090e151a1e21262b343d454d565d666d747f87929892857b6e6154473b2e21140903000000000000000000000000000000000013202d394653606c798686868686868686909494908686868686868686796c605346392d2013000005121e2a36424d5765727f8c98a2aea2988b7e71665c5146423b3a39383a3d444d57606d7a85929e9d9c9b9285796d6053463a2d2013070000000000000000000000000000000000000000000000000000030d18212a31373a3b4546464646464646463b3936302920170d02000000000000000000000000000000000000000000000000000000020608080b0e1011121313131211100e0c0a07060400000000000000000000000000000000000000000000000000000000030e18222a31373a3c42444546464644423f3a39363029241e160e0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c10141a1e20212527292b2c2c2c2c2b2a282522211f1b15110d08020000000000000000000000000000000000000000000000000000040c13191d2021292929292929282724201a13151b1f21222929292929292525221e18110901000000000000000000000000000000000000000000000000000000000000000000040c141b212628292d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d282724201a130b020000000000000810161c2023232d2d2d2d2d2d2d2323201c161008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060606060606060713202d3a4653606d79868f8f8f8f8f867a6d6053473a2d201407060606060606060000000000000000000000000000000000000006131f2c3845515c6775828f9ba8b2ab9f92857a6d60574d41382d2217110a020000000000000000000001081018222b37424e57646f7475716d6865615e56514b43392f24180c000013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675b4e4134281b0e01000013202c3946535f6c7986929f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9a8e8174675b4e4134281b0e0100000000000003090e1214202d3a4753606d7a86939f9f9f9f9286796c5f5346392c201514120e09030000000000000000000000000000000815212e3a47535f6a75828f989691837c76737273767d849197978e8174685e5246392d2014070000000000000000000000000000000000000000000000000000000000050c151d2328363e464f575f686d78818c939993877d70695e52463a2d20140700000000000000000000000000000000000013202d394653606c7986939393939393939c9f9f9c9393939393939386796c605346392d20130000020e1a25303b4754616d7a86929fa9aa9e9184796d605b534d4847454546484f565e69727f8c98a2aaa69b8e8275665c5044382c1f1206000000000000000000000000000000000000000000000000000000060f181f262b2d2e3939393939393939392e2d2a251e170e0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a15202a343c4347484f5152525352514f4b4746413a35302820191108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090e121415181b1d1e1f20201f1e1d1b191515120f0a0401000000000000000000000000000000000000000000000000000000000002080d1113141d1d1d1d1d1d1b1a18140f080a0f1215151d1d1d1d1d1d191816120d07000000000000000000000000000000000000000000000000000000000000000000000000030a1015191c1d2020202020202020202020202020202020201b1a18140f08010000000000000000050b1014161720202020202020171614100b05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a0500000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7986939b9b9b93867a6d6053473a2d201407000000000000000000000000000000000000000000000000000004101c2934404b5563707d8a96a1acaea2988c7f73695e53493f3327221b140b090603000001000205080d1319222a343c47535f6a7481827e7a76716d68605d554b4035291d10040013202c3946535f6c79869293939393939393939393939393939393939393939393939393939393939393939393939393939393938e8174675b4e4134281b0e01000013202c3946535f6c79869293939393939393939393939393939393939393939393939393939393939393939393939393939393938e8174675b4e4134281b0e010000000000050d141a1e21212d3a4753606d7a8693939393939286796c5f5346392d2d21211e1a140d0500000000000000000000000000000915222f3c4855626f7b88949e91847a6f6a6665666b6f7b85929e93877b6e6154473b2e21140800000000000000000000000000000000000000000000000000000000060e161e272e344048505960696e7a828e939f948c7f736b60574d42362a1e110500000000000000000000000000000000000013202d394653606c7986939f9f9f9f9f9fa9ababa99f9f9f9f9f9f9386796c605346392d20130000000914202d3946525d6874808d97a2aca0968d80746d615e575554515153555960686e7b86929faaab9f94897c6f63544a3f34281c100300000000000000000000000000000000000000000000000000000000060e141a1e21222c2d2d2d2d2d2d2d2d21201e19140d05000000000000000000000000000000000000000000000000000000000000000000000406070a0d0f11121313131212100e0c090606030000000000000000000000000000000000000000000000030f1b26313c464e53555b5d5e5f5f5f5e5c5854524c46413a322b231a1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020507080b0e10111213131212100e0c0908060300000000000000000000000000000000000000000000000000000000000000000000010407071010101010100e0d0b08030000030608091010101010100c0b09060100000000000000000000000000000000000000000000000000000000000000000000000000000005090d0f101313131313131313131313131313131313130e0d0b08030000000000000000000000000407090a131313131313130a090704000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a030000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d798693a0a8a093867a6d6053473a2d2014070000000000000000000000000000000000000000000000000000000c18232f394653606c7884919ea8b2aa9f92867b6e655b50443e332d261d1a1312100b060e090e1214191e2429343c46505a626e7b878f8b86827e7a766d675d5145392c1f13060013202c3946535f6c7987868686868686868686868686868686868686868686868686868686868686868686868686868686868686868174675b4e4134281b0e01000013202c3946535f6c7987868686868686868686868686868686868686868686868686868686868686868686868686868686868686868174675b4e4134281b0e0100000000050f171f252a2d2e393a4753606d798686868686868687796c5f53463939392e2d2a251f170f05000000000000000000000000000d192633404c5966737f8c99968a7d70685f5858596069717e8b98998b7e7165584b3e3225180b000000000000000000000000000000000000000000000000000000070f18202830394045525a616b6f7b838f949d968f82776c60594f453b30251a0e0200000000000000000000000000000000000013202d394653606c7986939facacacacacb6b7b7b6acacacacac9f9386796c605346392d201300000005111d2935414c56616d7a85929fa5a89d928c7f756e696461605d5c6062656b6f7a839198a2aea3999083766b605442382e23170c00000000000000000000000000000000000000000000000000000000000003090e1214151f20202020202020201414110e0802000000000000000000000000000000000000000000000000000000000000000001070c10131416191c1d1f1f20201f1e1d1b191613120f0b0600000000000000000000000000000000000000000006121f2b37434e585f62686a6b6c6c6c6b6865615e56524c443d352c241a110800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d0400000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d798693a0aca093867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000007121f2b3844505b66727f8b96a1acaea2988f82776c605a50443f382f2b26201f1c171b1a1b1a1e2124292f353e464e58626c75828f9999928f8b8682796d6053473a2d20140700121f2c3845525e6a757979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746f64594c4033271a0d010000121f2c3845525e6a757979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746f64594c4033271a0d01000000030d17212931363a3b464645515c67767979797979797979756a5e52464646463b3a36312921170d030000000000000000000000020f1c2935424f5c6875828f9b9184786b61564e4c4f57606d7a86929a8e8174675b4e4134281b0e0100000000000000000000000000000000000000000000000000071019212a323a434b515b636c717d8591959f9991847a6d655b50473d33291f14090000000000000000000000000000000000000013202d394653606c7986939facb9b9b9b9c3c4c4c3b9b9b9b9ac9f9386796c605346392d2013000000010d1924303a46525e68727e8b939ea7a49c918c827b75716e6d67666d6f71767d849195a0aaa69f92877c6f63594f4330261c1106000000000000000000000000000000000000000000000000000000000000000002050708121313131313131313080705020000000000000000000000000000000000000000000000000000000000000000040a0f12181c1f202326282a2b2c2c2c2c2b2a282523201f1c17110f0a030000000000000000000000000000000000000815212e3a47535f6a6f7577787979797775726d68615d564f473e362c231a1006000000000000000000000000000000000000000000000000000000000000000000000000000000020507080b0e111112131312110f0c0908060300000000000000000406070b0f1213131211100e0c0b09060100000000000000000000000000000000000000000000000000020507080b0d0f1112131313131211100e0b08080602000000000000000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a0500000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a050000000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a0500000000000000000000000000000000000000000000000000030d161f272d32353639393635322d271f160d03000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7986939f9f9f93867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000030f1c28333f4a54606d7984919ea6b0aa9e948c7f726c615a5049413c37312d2b2823272728252a2d2f353a41454f585f6a717e8b939ea39f9c998f8275675d5145392c1f130600111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c67645d53483c3024180b000000111d2a36424e59636a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c67645d53483c3024180b0000000009141f29333b4246485353534b555c6c6c6c6c6c6c6c6c6c6a635953535353534846423b33291f1409000000000000000000000004101d2a3743505d6a7683909c8f827669594f443f45515d677784919c8f8275695c4f4236291c0f03000000000000000000000000000000000000000000000000040f19222b333c444c555c606d737e869297a09f92877c6f685d53493f352b20170d020000000000000000000000000000000000000013202d394653606c7986939facb9c6c6c6cfd0d0cfc6c6c6b9ac9f9386796c605346392d20130000000008131e2a36414c56626d75818e959fa6a49c948f86827e7b7a7979797b7e83899196a0a7a59e948c7f736b6054473d321e150a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f161b1d23292c2d303335373839393939383635322f2d2b28221c1b150e0903000000000000000000000000000000000915222f3c4855626f7c81848585868584827e7a746d68605950483e352c22180d0300000000000000000000000000000000000000000000000000000000000000000000000003090e121415181b1d1e1f201f1f1d1b191515120f0a0401000000070c101313181c1e1f201f1e1d1b181815120d060000000000000000000000000000000000000000000205090e121415181a1c1e1f1f20201f1f1e1c1a181514120e09060300000000000000000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a03000000000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a0300000000000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a0300000000000000000000000000000000000000000000000a151f2831383e4243464643423e3831281f150a000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d79869393939393867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000b17222d3845515c67717e8b949ea9b0a69f92877e716c605b534d47423c3a38342e34343531363a3b41454c5159616a6f7c86929fa5aea99f93877c6f62554b4035291d1004000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060605b59534a41362b2014080000000e1a26313d4751595e5f606060606060606060606060606060606060606060606060606060606060606060606060606060606060605b59534a41362b201408000000020e1a25313b454d535f6060606060605d606060606060605f5e5c6060606060605f534d453b31251a0e020000000000000000000004101d2a3743505d6a7683909c8f827669594f454045515d677784909c8f8275695c4f4236291c0f030000000000000000000000000000000000000000000000000a16212b343d454d565e676d757f8a9298a19e938b7f726a60564c41382d23190e05000000000000000000000000000000000000000013202d394653606c7986939facb9c6d2d2dcdddddcd2d2c6b9ac9f9386796c605346392d201300000000020d1925303a44515b606d798390949da5a69e98928f8b8887858586888b90949ea1a8a39f938e82786d60594f43352b210c0300000000000000000000000000000000000000000000000000010406070a0d0f11121313131212100f0d0a070704010000000000000000000000000000000000000000000000000000000000000000060b151b21272c2f34383a3d40424445464646454543413f3c3938332d2b26201a150b060000000000000000000000000000000a1724313d4a5764707d8a9091929292918f8b86807a706b615a50473e342a1f150b01000000000000000000000000000000000000000000000000000000000000000000040a0f141a1e212125282a2b2c2c2c2b2a282622211f1b15110d08030b12181c1f2025292b2c2c2c2b2a272524221d18110901000000000000000000000000000000000003090e12141a1e21212527292a2b2c2c2c2c2c2a29272522211e1a15120f0a0400000000000000000000000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d0400000000000000000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d040000000000000000000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d0400000000000000000000000000000000000000000005111c27313a434a4e505353504e4a433a31271c11050000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7886868686868686796d6053473a2d2014070000000000000000000000000000000000000000000000000000000006111c2834404b55616c75828f97a2abafa39992877e726c655f57534d4946443f41414141424246484c52555d606b707c859298a2aeada2978f82756a5f5343392f24180c00000915202b353f474e52535353535353535353535353535353535353534d545b60666c6c6c6c6c6a5c544a53535353535353535353534e4c4841382f251a0f030000000915202b353f474e52535353535353534d575e6c6c6c6c6c6c6c6a665f55535353545e66696c6c6c6c6c6c6c5e574d5353535353534e4c4841382f251a0f0300000005121e2a36424d575e6c6c6c6c6c6c6c6a665f55535353545e66696c6c6c6c6c6c6c5e574d42362a1e120500000000000000000000020f1c2935424f5c6875828f9b9184786b61574f4d5058606d7a86929a8e8174675b4e4134281b0e010000000000000000000000000000000000000000000000030f1b27323d464e575f686d79818c929fa3a0958e81756d62584e443a2f261b110800000000000000000000000000000000000000000013202d394653606c7986939facb9c6d2dfe9eaeae9dfd2c6b9ac9f9386796c605346392d2013000000000008131e28323f45515d676d7a828e939da0a7a39f9b97949892929895989c9fa6a7a099928d81786d665c50463d3223190f00000000000000000000000000000000000000000000000004080d111314171a1c1d1f1f20201f1f1d1c1a171413110d080400000000000000000000000000000000000000000000000000000000020a111720262b323839404547494c4f50525253535251504e4c4946443f3837312b262017110a02000000000000000000000000000a1724313d4a5764707d8a979e9f9f9f9e9b98928d847d716c61594f463c31271d12070000000000000000000000000000000000000000000000000000000000000000060c161b1f252a2d2e31343738393939383735322f2e2b26201d19130c151d23282c2d32353839393838363432312e29231b130900000000000000000000000000000003090e141a1e21252a2d2e31343637383939393938373634322f2e2b26211f1b150f0a0400000000000000000000000000000000000000000000030d161f272d32353639393635322d271f160d030000000000000000000000000000000000000000030d161f272d32353639393635322d271f160d03000000000000000000000000000000000000000000030d161f272d32353639393635322d271f160d0300000000000000000000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a00000000000000000000000000000000000000000000000000000000000000000000000006121f2c3844505c66767979797979797976675c5145382c1f130600000000000000000000000000000000000000000000000000000000000c18232e3943505a616e7b859299a3afaba39992877f776e69615f575553504a4e4e4d4e4f4d5354565d60676d747d859297a1aaaea49e92857b6e61584e4331271d12070000040f19242d353d424546464646464646464646464646464646424651575f666c72797979797975665c50444646464646464646464641403c362f261d130800000000040f19242d353d424546464646464646535e69767979797979797771665b4f464e5a66707679797979797976695e5346464646464641403c362f261d1308000000000714212d3a46535e69767979797979797771665b4f464e5a66707679797979797976695e53463a2d21140700000000000000000000000d192633404c5966737f8c99968a7d706960595a5a616a727e8b98998b7e7265584b3f3225180c00000000000000000000000000000000000000000000000007131f2c38434e5860696e7a828e939ca4a2989183796d605b51463d32281d140a0000000000000000000000000000000000000000000013202d394653606c7986939facb9c6d2dfecf6f6ecdfd2c6b9ac9f9386796c605346392d20130000000000020c16202935404b555d686d78818991959c9fa3aba4aaa29f9fa2aaa4aba49f9c95908780786d665c544a3f342b21100700000000000000000000000000000000000000000000070c1013191d20212426292a2b2c2c2c2c2b2a28262421201d1913100c0701000000000000000000000000000000000000000000000000040b141c222832373d43484b515356595b5d5e5f5f5f5f5e5d5b585653504a47433c373127221b140b030000000000000000000000000a1724313d4a5764707d8a979e9ea2a9a9aaa39f9691877e716b61584e43392f23180c030000000000000000000000000000000000000000000000000000000000030a111720272b31363a3b3e4144444546464544423f3c3b37322c29241e191e272e34383a3e42454646454443413f3d3a342d251b110600000000000000000000000000060b151a1f262a2d31363a3b3e4042444546464646454443413e3b3a37312e2b26201b150c070000000000000000000000000000000000000000000a151f2831383e4243464643423e3831281f150a00000000000000000000000000000000000000000a151f2831383e4243464643423e3831281f150a0000000000000000000000000000000000000000000a151f2831383e4243464643423e3831281f150a00000000000000000000000000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d01000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a545c6c6c6c6c6c6c6c6c6c5c554b4034291c1004000000000000000000000000000000000000000000000000000000000007121d27303e46525e69707d87929fa4acaba399938c827b746e696562605c545b5a5a5b5c575e6164686d737a808a9297a1a9afa59d928a7e70695e52463c321f150b0100000008121b242b31363839393939393939393939393930353e444d525b62696e787f8686868687796d6053463a3939393939393939393433302b251d140b01000000000008121b242b31363839393939393b4854616e7b86868686868683776a5d50444f5c6976828686868686867b6e6154483b393939393433302b251d140b01000000000815212e3b4854616e7b86868686868683776a5d50444f5c6976828686868686867b6e6154483b2e21150800000000000000000000000916222f3c4955626f7c88949e91847b706b6766676c717c85929f93877b6e6154473b2e2114080000000000000000000000000000000000000000000000000915222e3b4854606a6f7b8490949ea5a49f92867c6e675d51493f342b20160b020000000000000000000000000000000000000000000013202d394653606c7986939facb9c6d2dfececececdfd2c6b9ac9f9386796c605346392d2013000000000000050e18242f3a434c565d666d747d848a8f92999a9c9e9e9f9f9e9d9c9a99938f8a837c736c665c544a42382e22190f000000000000000000000000000000000000000000060b12181c1f24292c2d31333537383939393938373533302d2c29241f1c18120c0700000000000000000000000000000000000000000000040d161d262d333c43474f54555c606366686a6b6c6c6c6c6b69686562605b54534e47423c332d261d150d0300000000000000000000000a1724313d4a5764707d8a92919297979c9fa6a9a19992877d706a5f554b4034291f140900000000000000000000000000000000000000000000000000000000030c151c232832373b4246484b4e505152535252504e4c4847433c39352f28222b30394045464b4f5152535251504e4b4a463f372d23180d0100000000000000000000020a11171f262b31363a3b4246484b4d4f51525253535252514f4d4b4847423c3a37312b262018120b0300000000000000000000000000000000000005111c27313a434a4e505353504e4a433a31271c110500000000000000000000000000000000000005111c27313a434a4e505353504e4a433a31271c11050000000000000000000000000000000000000005111c27313a434a4e505353504e4a433a31271c1105000000000000000000000000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f030000000000000000000000000000000000000000000000000000000000000000000000000c17232e38424a505f606060606060605f514b43392f23180c000000000000000000000000000000000000000000000000000000000000000b151e2a36424d56606b717f8b939aa3ababa49f948f86817b76726f6d6668686767686869696e71757a7f858d929ea2a9afa59e938d80746c61574d42342a200d03000000000009121920262a2c2c2d2d2d2d2d2d2d2d2429323a414650565e616d727b828c929992877e71665c5044382b2d2d2d2d2d2d2d2d282724201a130b020000000000000009121920262a2c2c2d2d2d2e3b4854616e7b87939393939083776a5d50444f5c6976828f93939393877b6e6154483b2e2d2d2d282724201a130b0200000000000815212e3b4854616e7b87939393939083776a5d50444f5c6976828f93939393877b6e6154483b2e21150800000000000000000000000815212e3b47535f6a76828f989691847d77747374777e859297978e8174695e52463a2d2014070000000000000000000000000000000000000000000000000916232f3c4956626f7c85919693939393928a7e716a5f554b40372d22190e04000000000000000000000000000000000000000000000013202d394653606c7986939facb9c6d2dfdfdfdfdfdfd2c6b9ac9f9386796c605346392d20130000000000000007131d28313a444c545c606b70787e82868a8d8f9192929291918f8d8a86827d786f6a605b544a423930261c100700000000000000000000000000000000000000020a11171c23282c2f35393a3d4042444546464645454342403d3a39352f2c29231d18120b0300000000000000000000000000000000000000030c161f282f383f444e54596063676d707375777879797978787674726f6c66625f58534d443f382f271f150d03000000000000000000000a1724313d4a5764707d87858585868a8f949fa2aaa39992867c6f675c51453b31261a0e030000000000000000000000000000000000000000000000000000030d151e262e343d43474d5354585b5d5e5f5f5f5e5d5b5955534e4745413a3129343c424b5153585c5e5f5f5f5e5d5a585651493f34291d1206000000000000000000040c141c232831373b4246484d5354585a5c5d5e5f5f5f5f5f5d5c5a5855534d4847433c373228231d150c0500000000000000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a0000000000000000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a000000000000000000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a00000000000000000000000000000000000003101d2a3643505d69768286868276695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000000000006111c2630383f4453535353535353535345403931271d120700000000000000000000000000000000000000000000000000000000000000030c1925303b444f59626d727f889299a1a8afa69f99928e88837f7c797775747474747576787b7e82868c92979da4adaba39f938e81786d605a50453b3022180e00000000000000080f151a1d1f202020202020191f282f353e444c525a61696e767f8690949a93877e716c61544a3f34281c202020202020201b1a18140f0801000000000000000000080f151a1d1f202020212e3b4854616e7b87949f9f9d9083776a5d50444f5c6976828f9c9f9f94877b6e6154483b2e2120201b1a18140f08010000000000000815212e3b4854616e7b87949f9f9d9083776a5d50444f5c6976828f9c9f9f94877b6e6154483b2e211508000000000000000000000006131f2b37434e58626f7c86929a96918984818081848a92979892857a6e61564d42362a1e11050000000000000000000000000000000000000000000000000d1a2633404d59667380868686868686868680746c61574e43392f251b100700000000000000000000000000000000000000000000000013202d394653606c7986939facb9c6d2d2d2d2d2d2d2d2c6b9ac9f9386796c605346392d201300000000000000010c161f28323a424b515960666c71767a7d808284858686858483807d7a75706c666058504a423930271e140a00000000000000000000000000000000000000050b141c22282e34383a4145474a4d4f50525253535252504f4d4a4745413a38342f28231d150c070000000000000000000000000000000000000b151e283139424a50585f626b6f75797d7f828385858686858483817f7c79746f6a625f575049413931271f150b010000000000000000000714202d3a4753606d79797878787a7d828a9298a1a9a2989083796d60574d42362a20150a00000000000000000000000000000000000000000000000000010b151f2730383f444e54575e6164676a6b6c6c6c6b6a6865625f5854524c433f353c464e545c6065686b6c6c6b6b696765625b51463a2e2215090000000000000000050e161e262e343c42474d5355575e616467696a6b6c6c6c6c6b6a696765625f5755534e47433c342e271e170e05000000000000000000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d0100000000000000000000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d010000000000000000000000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d01000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000000000000000000000000000000000a151e262e343846464646464646464638342f271f150b01000000000000000000000000000000000000000000000000000000000000000009141f29323d47505a626d727e8791969ea5acaba39f9a95908c8885848281818081828385878b8f92989fa2a9ada8a099928d81786d665c50483e33291f1006000000000000000004090e1112131313130f19222b313a41454f565e616c717b828b92989a93887e716c615a5042382e23170b1313131313130e0d0b080300000000000000000000000004090e1112131315212e3b4854616e7b8794a1aa9d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e2115130e0d0b080300000000000000000815212e3b4854616e7b8794a1aa9d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e2115080000000000000000000000030f1b26323c47535f6a717e8892989e95908d8d8e91969e9792867d6f685e52443b3025190e020000000000000000000000000000000000000000000000000c1925323f4b57636d737979797979797979746e645a50453c31281d12090000000000000000000000000000000000000000000000000013202d394653606c7986939facb9c6c6c6c6c6c6c6c6c6c6b9ac9f9386796c605346392d20130000000000000000040d162028303940454f545b6064686e7174767778797978777673716e6863605b544e443f382f271e150c02000000000000000000000000000000000000070f171d262d33394044464c525457595c5d5e5f5f5f5f5e5d5b595754524c47454039342e271e1810090000000000000000000000000000000007121d273039434b545b606a6f767c8185898c8e90919292929291908e8b8985817c756e69605b534b433931271d120700000000000000000006131f2c3845515c676d6d676b676d70767e869297a1aaa0958c8073695f53463c31261a0f0300000000000000000000000000000000000000000000000007121d273139424a50586062696e71747777787979787775726f6a66605d56504540454e5860666d717578797978777674726d62564a3d3124180b00000000000000050e17202830383f444d53575f6166696e71737577787979797978777674716e6967625f58544e454039302920170e050000000000000000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f0300000000000000000000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f030000000000000000000000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f03000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000000000000030c151c23282c3939393939393939392c29231d150d03000000000000000000000000000000000000000000000000000000000000000000020d17202b353f48515b626c717d848e939da0a7abaca79f9d989892908f8e8d8d8e8f909298979c9fa3aaada9a29f96918780786c665c544a3f362c21170d00000000000000000000000104060606000a16212b343d434b515961686d757e858f949f9f93887f716c625a50483e30261c110600060606060601010000000000000000000000000000000000010406060815212e3b4854616e7b8794a1a99d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e211508010100000000000000000000000815212e3b4854616e7b8794a1a99d9083776a5d50444f5c6976828f9ca9a194877b6e6154483b2e2115080000000000000000000000000a15202b37434e58616c717e868f949a9d9a999a9d99938f857d706b60564d4132291f1409000000000000000000000000000000000000000000000000000a16232f3b47525b63666c6c6c6c6c6c6c6c67645c52483e332a1f160c000000000000000000000000000000000000000000000000000013202d394653606c7986939facb9b9b9b9b9b9b9b9b9b9b9b9ac9f9386796c605346392d2013000000000000000000040d161e272e343d424a5053565e616467696b6b6c6c6b6a696764615e5653504a423c332d261d150c0300000000000000000000000000000000000007101921292f383f444a5153565d606466686a6b6c6c6c6c6b6a686663605d5653514b454039302a221a12090000000000000000000000000000040d18232e39434b555d666c737c83898e9298999b9d9e9f9f9f9f9e9c9b9897918d88827b736c655d554b43392f24180e05000000000000000004101c2934404b555c60605c555d60646c717c859298a3a79f92867b6e61584e43372b1f14090000000000000000000000000000000000000000000000020c18242f39434b545c606a6f757b7e8183848586858583817f7c78726d68625a514b4d57606a6f797e82848586858483817f7265584b3f3225180c000000000000030c172029323a424a50575f62696e73777b7e8082848585868685858482807e7b78736f6a625f58514b423a322920170c030000000000000000000000000003101d2a3643505d69768286868276695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768286868276695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768286868276695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000000000000000000000000000000030a11171c1f2d2d2d2d2d2d2d2d2d1f1c18120b030000000000000000000000000000000000000000000000000000000000000000000000050e19232d363f49515a626b6f7a818990959c9fa6a9aca9aaa29f9d9b9b9a9a9b9b9c9fa2aaa8acaaa9a19e97928c847c736c665b544a42382e241a0f0500000000000000000000000000000000030f1b27323d464e555d606b707a818a92979f9b918b7f726d625a50483e362c1e140a0000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b87949c9c9c9083776a5d50444f5c6976828f9c9c9c94877b6e6154483b2e211508000000000000000000000000000815212e3b4854616e7b87949c9c9c9083776a5d50444f5c6976828f9c9c9c94877b6e6154483b2e211508000000000000000000000000040f1b26313c46505a616c717c82898d90929291908d88827b706b60594f443b3020170d020000000000000000000000000000000000000000000000000007131e2a35404952575960606060606060605a58524a40362c21180d04000000000000000000000000000000000000000000000000000013202d394653606c7986939facacacacacacacacacacacacacac9f9386796c605346392d201300000000000000000000040c151d23282f383f44464c5254575a5c5e5f5f5f5e5e5c5a5754524c46443f382f28221c140b03000000000000000000000000000000000000071119222b333b424a50545c6064686d70737577787979797878767573706d6864605c55514b423c342c241b1209000000000000000000000000010c161f2834404b555d676d78808790949b9fa2a9a29e9c9b9a9a9b9d9fa3a9a19e9a948f877f776d675d554b40352920170d0200000000000000000c18232f39434b515353514b51535a616a6f7c86929fa7a3988e81756a5f53473b30251a0e01000000000000000000000000000000000000000000000a141e2935404b555d666d747c82878b8e909192929291908e8c88847f7a716d605d55535f696f7c848b8f9192929291908d86796c605346392d20130000000000000b151e29323a444c545c60696e757b8084878b8d8f90919292929292908f8d8b8884807c766f6a605c544c443b32291e150b0000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000000000000000000060c101220202020202020202013100c07010000000000000000000000000000000000000000000000000000000000000000000000000008111b242d373f48505960686d757d83898f94989c9fa3aba7a8aaa8a7a7a7a7a8a9a9a7a5a8a09e9a97918c8580796f6b605b544a423830261c1108000000000000000000000000000000000007131f2c38434e5860676d747d858e939fa29b918b7f726d625a50483f362d241a0c020000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b878f8f8f8f8f83776a5d50444f5c6976828f8f8f8f8f877b6e6154483b2e211508000000000000000000000000000815212e3b4854616e7b878f8f8f8f8f83776a5d50444f5c6976828f8f8f8f8f877b6e6154483b2e211508000000000000000000000000000a15202a343e48505a616a6f767c808385868583807c756e6960594f473d32291f0e050000000000000000000000000000000000000000000000000000020d19242e3740474b4d53535353535353534d4c4740382f241a0f0600000000000000000000000000000000000000000000000000000013202d394653606c7986939f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9386796c605346392d20130000000000000000000000030b12181d262d33383b4146474a4d4f515253535251504d4a4746413b38332d261d17110a02000000000000000000000000000000000000060f19232b343d454d545b60666d71767a7d8082838585868685858382807d7a76716d67605c544e463e362d241b1108000000000000000000000008131e28313a45515c676d79828d92999fa6a39f9a97928f8e8d8e8e9092989b9fa3a69e99928c82796d675d51453f32291e1408000000000000000007121d27313940454747454045475058606a727f8c959faa9f93877c6f62574d42362a1d120700000000000000000000000000000000000000000006111c26303845515d676d7880898f93999a9d9e9f9f9f9e9d9b9896918c857e756d675d58626e7b8691969b9e9f9f9e9e9c9386796c605346392d2013000000000007121d27303a444c565d666d737b81878c9196979a9c9d9e9f9f9f9f9e9d9c9a9896918d88827c746d665e564c443b30271d120700000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000000000000000000000003061313131313131313130604000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b252d363f474f565e616b70787d82878b909299989a9c9d9e9f9f9f9e9e9d9c9b999696918d89857f7a736d676059504a42382f261e140a0000000000000000000000000000000000000915222e3b4854606a6f79818a91979ea39c918c7f726d625b51483f362d241b1208000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8283838383828074675a4e414d5a6673808283838383827a6e6154473b2e211408000000000000000000000000000814212e3b4754616e7a8283838383828074675a4e414d5a6673808283838383827a6e6154473b2e21140800000000000000000000000000030e18222c363e4850585f626b6f737778797876736f6a615e574f473d342b20170d0000000000000000000000000000000000000000000000000000000007121c252e353b3f404646464646464646413f3c362f261d12080000000000000000000000000000000000000000000000000000000013202d394653606c798693939393939393939393939393939393939386796c605346392d201300000000000000000000000000070b141c22282b3036393b3e414344454646454443403e3b3936302b28221c140b0600000000000000000000000000000000000000030c18212b353d464f575e666c71797e82868a8c8f90919292929291908e8c8a86837e79726d665f5850483f362d231a0e05000000000000000000010d19242f3a43505a606d79828f949fa3a7a099928e898583818181828386898e92999fa7a39f948f82796d605b51443b3025190e0200000000000000010b151f272f34383a3a3835393e464e58606c7883909da6a49a8e8175695e5246392f23180c0000000000000000000000000000000000000000000b17232e3842505a606d79828d929b9fa4ababa39f9d9c9b9c9d9fa19e97928b82796d685f6a76828f98a1a8aaa39f9995949386796c605346392d201300000000000c18232e39434c565e686d7880868e93999da0a8aba39f9d9d9c9c9c9d9fa2aaa8a19e9a948f8780786d685e564c42392e23180c03000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131b242d353d444c525960656c70767b7f8386898b8d8f9091929292929190908e8c8a8784807c79726d67605d554f443f382f261d140c020000000000000000000000000000000000000916232f3c4956626f7c848e9393939393918c7f726d625b51493f362d241b120900000000000000000000000000000000000000000000000000000000000000000714202d3946525e686e767676767676746e64584c404b58636e737676767676766e685e5246392d201407000000000000000000000000000714202d3946525e686e767676767676746e64584c404b58636e737676767676766e685e5246392d201407000000000000000000000000000006101a242c363e464e53596063676a6b6c6b6a66625f58534d453d352b22190e0500000000000000000000000000000000000000000000000000000000000a131c242a2f323339393939393939393433302b241d140b000000000000000000000000000000000000000000000000000000000013202d394653606c798686868686868686868686868686868686868686796c605346392d20130000000000000000000000000000020a11171c1f252a2d2e3134363838393938373634312e2d2a251f1c17110a0200000000000000000000000000000000000000000a151e2a333d474f5960696e787e848a8f9299999b9d9e9f9f9f9f9e9d9b9999928f8b857f796f6a615a50483f352b20170d02000000000000000004111d2935414c56616c74818e949ea6a69f959087817c79767474747577797d818790959ea5a69e948e81756d62564c41362a1e14080000000000000000030d151d23292c2d2d2c292c343d44505b666f7c89949eac9f92877b6e61554b4034291c10040000000000000000000000000000000000000003101c28343f4a54616c74818e949da4aca7a09d9992908f8f8f9192999a9e9f948f837a6d666f7c88949faaaea398928c88878886796c605346392d20130000000004101c2834404b555e686d7a828c92999fa4a9a19e99999291908f8f90909298989da0a8a69e99928d837a6e685e544b40342820150a000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000010406070a0d10111213131211100d0a070604000000000305050606060606060000000000000000000000000000000000000000000000000000000000000000000000000000000000000109121b232b323a41464f535b6063696e7276797c7f8182848585868685848483817f7d7b7773706d66605d55514b433d332d261d140b02000000000000000000000000000000000000010e1b2734414e5a67748186868686868686867f736d635b51493f372d241b120900000000000000000000000000000000000000000000000000000000000000000005111e2a36414c565e6169696969696967645c52473c47525c6366696969696969615e564c41362a1e11050000000000000000000000000005111e2a36414c565e6169696969696967645c52473c47525c6366696969696969615e564c41362a1e110500000000000000000000000000000008121a242c343c43474f54565a5d5f5f5e5d5a55534e46423b332b23191007000000000000000000000000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d2726241f19130b02000000000000000000000000000000000000000000000000000000000013202d3946535f6c767979797979797979797979797979797979797979766c5f5346392d201300000000000000000000000000000000060b0f14191e20212427292b2c2c2c2b2b29272421201e19140f0b0600000000000000000000000000000000000000000006111c26303c454f59606b6f7b828b91969c9fa3a9a19e9c9b9a9b9c9d9fa2aaa39f9c97928c847c716c625a50473d32291e130800000000000000000613202c3945525d68717e8a939da6a89f948f837c746f6c6668676768666d70757c838f939ea7a69e938b7f72685e52463b3025190d010000000000000000030b12181c1f20201f1d2228333f4a54606b75828f9ca8a3998d8073675c5145382c1f14090000000000000000000000000000000000000006121f2b3844505c66717e8b939ea6aea59d95908a86838282838486898d92979f959083786d73808d99a6b0a89f9286807c7a7b7d7063574a3d3024170a000000020d17202c3845515c676d7a838f949fa3aaa29f97918c898684838282838485888b91969ea1a9a39f9590837a6e665c51453c31261a0f020000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000001080d111314171a1d1e1f1f201f1e1c1a171413100c07010c0f11121313131313130909070300000000000000000000000000000000000000000000000000000000000000000000000000000000091019202830363d41495053575e6165676d6f7274757778787979787877767472706e696763605c54514c45403a3128221c140b0200000000000000000000000000000000000000010d1a2733404c58646e747979797979797979736d635b51493f372d251b120900000000000000000000000000000000000000000000000000000000000000000000010d1925303b444c52545c5c5c5c5c5c5a58524a4136404a52585a5c5c5c5c5c5c54524c443b3025190d0100000000000000000000000000010d1925303b444c52545c5c5c5c5c5c5a58524a4136404a52585a5c5c5c5c5c5c54524c443b3025190d010000000000000000000000000000000008121a222a31373d4348494d50525352504d4947433c36312921191107000000000000000000000000000000000000000000000000000000000000000000070d1316191a20202020202020201a1a17130e0801000000000000000000000000000000000000000000000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e1200000000000000000000000000000000000003080d111414171a1c1e1f20201f1e1d1a171414110e080300000000000000000000000000000000000000000000000c17232e38424d57606b707d8590949ea1a8a29e9997918f8e8e8e8f909298999ea2a9a19e9691867e716c62594f443a3025190d0400000000000004111d2935414c55606d7a85929ea5aca0968f82796e6a62605b545a5b545c60636a6e78818f959faba59f92857a6e61564c41362a1e110500000000000000000001070c10131414131017222d38424f5963707d8995a0ab9e9285796d6053473b31261a0e000000000000000000000000000000000000000713202d3a4653606d7884919ea5afa69d938e837d797776757677797c80858c9298958e81747683909ca9aca0958a7e736f6e6e706b6155483c2f23160900000009141f2b37434e58606d798390959fa6a8a098928b85807c79777675757677797c7f848a92979fa7a79f959083786d60584e43372b1e13080000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000003090e13191d20212427292b2b2c2c2c2b292724201f1c18120e181c1e1f2020202020201615130f0a04000000000000000000000000000000000000000000000000000000000000000000000000000000070e161e252a2f383f44464d5354555c60636567696a6b6c6c6c6b6b6a69686663615e575653504a45413a352f281f17110a020000000000000000000000000000000000000000000b1824303c48535c64676c6c6c6c6c6c6c6c66635b51493f372d251b130900000000000000000000000000000000000000000000000000000000000000000000000008141e29323b4146475050505050504e4c4741382f3840474b4d5050505050504746413b32291e140800000000000000000000000000000008141e29323b4146475050505050504e4c4741382f3840474b4d5050505050504746413b32291e140800000000000000000000000000000000000008101820262b32383b3c404445464543403c3b37322a251f170f07000000000000000000000000000000000000000000000000000000000000000000000002070a0c0d13131313131313130e0d0b070300000000000000000000000000000000000000000000000000000000000000000f1b27333e49525a5f60606060606060606060606060606060606060605f5a52493e33271b0f0000000000000000000000000000000000000000010507080b0e10111213131211100d0b0807050200000000000000000000000000000000000000000000000003101c28343f4a545f69707d8692979fa6a49d97928c888583828181828385898c92979fa3a8a09892887e716b60564c41362a20150a0000000000000613202c3945515d6773808d97a1ada69e91847a6d675f5853504a4e4e4b5153585f666d79839099a3ada2978d8174685e5246392d201409000000000000000000000000040607070606111c262f3d4854606b7784919daba2978a7e7164574d42362a1b11060000000000000000000000000000000000000b1824313e4b5764717e8a96a0acac9f948e8179716d67696869676d70747a7f869095938a7e7885929fabaa9d9184776c6261616361594f44382c2014070000020e1925303a47535f6a73808d959fa7aaa09691867f79736f6d676a696969666d6f72787d8590959fa9a79f958d80736a5f53473a3025190d0100000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000060e141a1e24292c2d3033363738393939383634302d2c29231d1a24282b2c2d2d2d2d2d2d23221f1b160f07000000000000000000000000000000000000000000000000000000000000000000000000000000050c13191d262d33373b4246484b515356585a5c5d5e5f5f5f5f5e5d5d5b595754534d4946443f38352f29241d160d0600000000000000000000000000000000000000000000000814202b36414a53585a60606060606060605957514940372e251b130900000000000000000000000000000000000000000000000000000000000000000000000000020d1720293036393b43434343434341403c362f262e353b3f404343434343433b3936302920170d02000000000000000000000000000000020d1720293036393b43434343434341403c362f262e353b3f404343434343433b3936302920170d0200000000000000000000000000000000000000060e151b21272c2f30343738393837332f2e2b26201a140d0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a16212c3740494f535353535353535353535353535353535353535353534f4940372c21160a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2c3844505c666e7b859298a2a9a49f928d857f7c78767574747576797c80858c9299a2aaa39a92877d70685e52463c32261b0f0200000000000714212d3a4754606d7a85929fa9aa9e94897d70685d554e46443f41414045464e545c676f7c87929faca99f92867a6e6154473c31261a0e0200000000000000000000000000000000000a141d2c38444f5965727f8c99a3a99c8f8276695f5346382d22170b000000000000000000000000000000000005121e2a36424d576875818e9ba8afa49a8f82786d66605d555c555c6063676d727b838f9391857b8797a2ada79a8d8074675a545557554f473e33281c1004000005111e2a36424d56626f7c87929fa7aea29891847c726d6763605c555c5c545c6062656c707a839097a1ada79f92877c6f62564c41362a1e110500000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000070f181f262a2f35393a3d404344454646454443403d3a38342f2a252f3437383939393939392f2e2c272119100700000000000000000000000000000000000000000000000000000000000000000000000000000002080b141b22272b31363a3b404547494c4e4f5152525353525151504e4c4a4846423d3a38342e29241e18130c04000000000000000000000000000000000000000000000000030f1a252f3841484c4e53535353535353534c4b4640372e251c1309010000000000000000000000000000000000000000000000000000000000000000000000000000050e171e252a2d2e3636363636363433302b241d242a2f32333636363636362e2d2a251e170e050000000000000000000000000000000000050e171e252a2d2e3636363636363433302b241d242a2f32333636363636362e2d2a251e170e05000000000000000000000000000000000000000000040a0f161b1f2223272a2c2c2b2a2722211f1b150e0903000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005080a0b13131313131313090806030000000000000005101b252e373e4346464646464646464646464646464646464646464646433e372e251b10050000000000000000000000030613131313131313130d0c0a07020000000000000000000000000003060809131313131313130b0b090501000000000000000004111d2935414c56606d78839097a2aaa49a938b807a736f6a6968676869666d6f737a80879298a2aba39992857a6d61584e43372b1e14080000000005111e2a36424d5765727f8b98a2aea99c8f82756b60564c433c38332d2e34383c424b555f6a74818e9ba8aea3988c7f7266574d42372b1e12050000000000000000000000000000000000020b1c27333d4754616d7a86929fac9f93877b6e6153493f33271b0f03000000000000000000000000000000000714202d3a46525e697885919eabac9f93877c6f665c54514b4f4b5153555d60696e79818f949083909da9b3a4988b7e7165584b484a48443e352c21160b0000000714202d3a46525e6975828e99a3afa89f92867c6f6a605c5553514b4f4f4a5053535b60686e7a85919ea7afa3998e8175685e5246392d20130700000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000030b1218212a31363a4145474a4d505152525352514f4d4a4745403936313a4044454646464646463c3b38322b22190f0400000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171b1f252a2d2f34383a3c3f4142444545464645454443413f3d3b3a36312d2c28231c19130d0701000000000000000000000000000000000000000000000000000008131d262f363c40414646464646464646403e3b352e251c130a0100000000000000000000000000000000000000000000000000000000000000000000000000000000050d14191e20212929292929292726241f1a13191f23262729292929292921201e19140d0500000000000000000000000000000000000000050d14191e20212929292929292726241f1a13191f23262729292929292921201e19140d05000000000000000000000000000000000000000000000000040a0f1315161a1d1f201f1d1a1615130f0a040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c11151718202020202020201615130f0a0400000000000009131c252c33373939393939393939393939393939393939393939393937332c251c130900000000000000000000060c101220202020202020201a1917130e0800000000000000000000040a0f13151620202020202020181715110c06000000000000000713202c3945525d68727f8c95a0a9a69f93887f746d68625f585b5b5b545c6063676d737d869299a4aba2978e81756a5f54473b3025190d010000000714202d3a46525e697683909daaada196897d7063594f433a312b282223282c3039434e58626f7c8895a0acaa9d908477695f53463a2d2114070000000000000000000000000000000000000b13202d3a4653606d7985929eaba49a8c8073655b5044372b1f1207000000000000000000000000000000000815212e3b4854616e7b8797a1adaa9d9083776a5f544b4540424045474b51575f676d78828f9590959fabb0a3968a7d7063574a3d3d3c38332c231a10050000000814212e3b4754616e7b87939fabaca0958a7e716a5f58514b47454042423f44464950565e68707d8a95a0acab9f92867a6d6154473a2e21140700000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000030c151c2328333b42464c5254575a5c5e5e5f5f5f5e5c5a5753514b46423b454c50525353535353534948433d342b21160a000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f141a1e2123292c2d303234363738393939383837363533302e2d2a25201f1c17110d080100000000000000000000000000000000000000000000000000000000010b141d252b303334393939393939393933322f2a231c130a0100000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d1114141d1d1d1d1d1d1b1a17140e080e1317191a1d1d1d1d1d1d1414110d080200000000000000000000000000000000000000000002080d1114141d1d1d1d1d1d1b1a17140e080e1317191a1d1d1d1d1d1d1414110d0802000000000000000000000000000000000000000000000000000000030709090d11121312100d090806030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000911171d2124252d2d2d2d2d2d2d22211f1b150e060000000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b27211b130a010000000000000000030a11171c1f2d2d2d2d2d2d2d2d2726231f19120a0200000000000000070f161b1f22232d2d2d2d2d2d2d2524211d1811090000000000000714212d3a4754606d7a85929fa7ab9f948c7f726d605d56534e4f4e4e4a5053555d606b707d87939faaa99e93887c6f62564c41362a1e11050000000814212e3b4754616e7b87959fabab9e9184786c6053463d31281f1c17181c1f27313c47535f6a7784919daaaca095887b6e6155483b2e221506000000000000000000000000000000000005111d2a36414c5664707d8a97a1adac9e9184786c605346392f24180c000000000000000000000000000000000916222f3c4955626f7c8895a9b3a79a8d817467584e4239352f34383a40454d555c666d7a85919d9fa7b1afa396897c706356493d302f2c28211a1108000000000c1925323f4c5865727f8b99a4afaa9d9184786c60574e45403a38342f2e34383a3f444d56616b7783909daaafa3998b7e7265584b3f2f24180d01000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000b151e272e343f454d53565d606366696a6b6c6c6c6b696763605c55534d444f575c5f60606060606056544e463d32271b0f030000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214181c1f20232527292a2b2c2c2c2c2b2a2a28262421211e1a1312100c060000000000000000000000000000000000000000000000000000000000000000020b131a202427272d2d2d2d2d2d2d2d2625231e19120a01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010507081010101010100e0d0b08030002070a0c0d1010101010100807050100000000000000000000000000000000000000000000000000010507081010101010100e0d0b08030002070a0c0d101010101010080705010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b22292d3031393939393939392f2e2b26201810060000000000010910161b1e202020202020202020202020202020202020202020201e1b161009010000000000000000030c151c23282c393939393939393933322f2a241c140a00000000000007101920272b2e2f3939393939393932312e29221b12090000000006131f2b37434e5866727f8c97a2ada79c9083786c605b524c47434241413f44464c5159616b73808d98a2aea59b8f8275685e5246392d2014070000000b1824313e4b5764717e8a97a7b1a79a8e8174665b5044382b1f160f0b0c10151f2b37434e586773808d9aa6b1a7988b7e7165584b3e2d22170b00000000000000000000000000000000000713202d3946525e6875828f9ba9b3aca196897c6f63554b4035291d10040000000000000000000000000000000a1723303d4a5663707d8996a3b0a6998c7f7366594c402f2924292c2f353b434b545d68707d8a959fabb7afa396897c706356493d3023201c1610080000000004111d2935414c556975828f9cabb2a9988b7e72655b50453c342e2c292323282b2d333b444f5965727e8b98a9b3ab9b8f827568554b4035291d1004000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000007121c273039404451575f61686d7073767778797978777673706d67615e57505761686b6c6c6c6c6c6c6260584e43382c1f13070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205070c10131416191b1c1e1f1f20201f1e1e1d1b19171514120e090603000000000000000000000000000000000000000000000000000000000000000000000001080f14181a1b2020202020202020191916120d070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030608090f1112131313110f0c070705010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111b242d34393d3e464646464646463c3b37322a22180e04000000000000050a0f1213131313131313131313131313131313131313131313120f0a05000000000000000000000a151e262e34384646464646464646403f3b362e261c120800000000040f19222b32383b3c464646464646463e3d3a342d241b11060000000815222e3b4754606a7784919ea9aca095897d70655b5045413a3732342e34383a41454f59606d7a85929fabac9f92867a6e6154473b2e23180c0000010e1b2834414e5b6774818e9aa7b4aa978a7e7164544a3f3328190d040000040d1b26323d4a5764707d8a97aab4a79b8e81746853493f33271b0f03000000000000000000000000000000000714212e3a4754616d7a86929facb9b2a89a8e8174675d5145382c1f14080000000000000000000000000000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f2e23181c1f24293139424c56616c7683909da9b3afa396897c706356493d302316100b0500000000000613202c3945515d677885929eabada196887b6e6153493f3328231f1c18171c1f2227323e4855626e7b8897a2adab9e918578675d5145392c201306000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000c18232e39424a515b63696e747a7d808384858586858482807d79746e69605b536873787979797979796f6a6054483b2e22150900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040607090c0e0f1112121313121211100e0c0a080705020000000000000000000000000000000000000000000000000000000000000000000000000000000003080b0d0e13131313131313130d0c0a0602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002050708121313131313130a090704000000000000000000000000000000000000000000000000000000060b0e1011131313131313131313131313131313130b0a080400000000000000000000000000030a0f1215151c1e1f1f201f1e1c181413110d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17222d363e45494b535353535353534947433c342a20150a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c2630383f4453535353535353534d4b4740382e24190e020000000a16202b343d434749535353535353534b4a453f362d22180c0100000916222f3c4955626f7c8896a0acaa9d9084776b6053493f35302b262823282c2f353e45525d6874818d9aaaafa3998b7f7265544b4034281c10040005111e2a36414c566a7683909da9aea298887b6e6155483b2d221708000000000a15212e3b4854616e7b8798a2aeaa9d908377655b5044372b1f120500000000000000000000000000000006131f2b37434e5865727f8c99a3aeb7b8ab9f9285796d6053473b3025190e0200000000000000000000000000000a1723303d4a5663707d8996abb5a6998d807366544a403428211e1a181f27303a44505a64707d8a97a2adafa396897c706356493d3023160a000000000000000714212d3a4754606d7a8797a1adab9e918578695f5341382d211813100c0b101217202d394653606c7985929fabada196867a6d6053473a2d201407000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000004101c2834404a545c606d727b81868a8d8f9191929292918f8d8a85807b726c655c6b78858686868686867c6f6256493c2f2316090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214151f202020202020171614100b050000000000000000000000000000000000000000000000040b12171b1d1e20202020202020202020202020202020171714110c0500000000000000000000060e151b1f2122282a2b2c2c2c2b292521201d19130d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111d29343e485056586060606060606055534e463c32261b0f0300000000000000000000000000000000000307090a0e111213131211100e0b090706030000000000000000000c17232e38424a505f606060606060605a58524a40362a1f13070000030f1b27323d464e545660606060606060585650483f34291d110500000d192633404c5966737f8c99a8b2ab998c807366594f41382d241e1b1b171c1f242935414c5663707c8998a2aeab9c8f8276665c5145382c1f1306000713202d3946525e687885929fabac9f9285796c605346392d201306000000000714212d3a46535e697985929facac9f9285796c605346392d2013060000000000000000000000000000000815222e3b4754606a7783909dabacababaea2988a7e7164564c41362a1e110500000000000000000000000000000915222f3c4855626f7b8899a3afa89b8f8275665c51443a322d2b2627272628323e4653606d7985929fabafa396897c706356493d3023160a000000000000000915222f3c4855626f7b8895a9b3a99c8f827669574d422f261b0f070400000306121f2b3744505b657683909da9b2a995887b6e6255483b2f221508000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000030e18212c3844515c666d757f878d9298999c9d9e9f9f9f9e9c9a98928d867f776d666679869293939393887b6e6255483b2f22150800000000000000000000000000000000000000000000000000000003080c0e0e131313131313130f0e0c09040000000000000000000000000000000000000000000000000000000000000003070b0d0e131313131313130e0e0c08030000000000000000000000000000030608090f1112131313110f0c0707050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407090a131313131313120807050200000000000000000000060d141a1e21222c2d2d2d2d2d2c2423201c161008000000000000000000000000000000000000000000050e161d23272a2b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c171008000000000000000006101820262b2e2f3537383939393835322e2d2a251e19130c04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212d3945505a62646c6c6c6c6c6c6c625f584e43372b1f1306000000000000000000000000000000040b101316161a1d1f201f1e1e1d1a18151312100b0600000000000003101c28343f4a545c6c6c6c6c6c6c6c6c66635c52473b2f23170a000006131f2b38434e5860626c6c6c6c6c6c6c65625a50453a2e2115090005111d2935414c566976828f9ca9afa399897c6f6356493d2f261b130f0a0c101319242f3a4653606d7985929facac9f9285796d6053463a2d201307000714212e3a4754616d7a8798a2aeaa9d918477665b5044382b1f12060000000005121e2a36424d576a7784919daaaea298877a6e6154473b2e211408000000000000000000000000000004101c2834404b55626f7c8895a0a8a19e9fa2aa9c8f8275685e5246392d20150a00000000000000000000000000000714202d3a4753606d7a86929facab9e9285796d60564c443d3a373134333332323845515c6675828f9ca8afa396897c706356493d3023160a000000000000000916232f3c4956626f7c8995a2afa89b8e8275685b4f423128140a0000000000030f1b27333f49536976828f9ca9afa295897c6f6256493c2f231609000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000915202c38434f59606d78818c92999fa2aaa9a8aaa29f9e9e9e9fa29f98928c81786d6d798699a39f9f94877a6e6154473b2e2114080000000000000000000000000000000000000000000000000001090f14181a1b202020202020201c1b191510090200000000000000000000000000000000000000000000000000000001080e1317191a202020202020201b1a18140f090100000000000000000000030a0f1215151c1e1f1f201f1e1c181413110d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b101416172020202020201f1514120e090300000000000000060f181f262a2d2e38393939393939302f2c28211a110800000000000000000000000000000000000000040e1720282e3336373939393939393939393939393939393931302d28221a1208000000000000030e18222a31373a3c42444546464644423f3a39363029241e160e070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724303d4956626c7179797979797979766a5f53473b2e2115080000000000000000000000000002090e161b202223272a2c2c2c2b2a29272522201f1c17110a020000000006121f2c3844505c667679797979797979736e63584b3f3226190c00000815222e3b4754606a6f79797979797979716c62564a3d3124170b000713202d3946525e687885929eabac9f92867a6d6053473a2d20140a0200000308131f2c3844505c667683909ca9aea298887c6f6255493c2f221609000915222f3c4855626f7b8895aab4a99c8f837669544a3f33281c0f0300000000020e1a2531434f5c6976828f9ca9b4aa95887b6f6255483c2f221509000000000000000000000000000006131f2c3845515c6774808d9aa7a196919298a29f92867a6e6154473c31261b0f000000000000000000000000000006131f2c3945515d677783909dabada1978a7e71685e564f484742424140403f3f3f404b546673808c99a6afa396897c706356493d3023160a00000000000000091623303c4956636f7c8996a2afa79a8d8174675a4e4134271b080000000000000b17222d424e5b6875818e9ba8afa296897c6f6356493c30231609000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000020e1a26313b4854606b74808d939fa3ababa49f9b979892919192939a989d9f938f82786d7a8794abb4a094877a6d6154473a2e211407000000000000000000000000000000000000000000000000030b131a202427282d2d2d2d2d2d2d292825211b140c0300000000000000000000000000000000000000000000000000020b12191f2326272d2d2d2d2d2d2d282724201a130b030000000000000000060e151b1f2122282a2b2c2c2c2b292521201d19130d0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810161c2023242c2d2d2d2d2d2c22211e1a140d060000000000030d18212931363a3b454646464646463d3c38332c231a10070000000000000000000000000000000000000b16202932393f4344464646464646464646464646464646463e3c39332c241a100500000000000a15202a343c4347484f5152525352514f4b4746413a3530282019110800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e868686868686867c6f6255493c2f221609000000000000000000000000050d141a21272c2f30343738393938373634312f2d2b28231c140c020000000713202d3a4653606d78868686868686868073665a4d4033271a0d00000916232f3c4956626f7c868686868686867e7165584b3e3225180b000714212e3a4754616d7a8797a1adaa9e918477675d5145382c1f13020000000003101c28343f4a546774818e9aa7b4aa978b7e7164584b3e3125180b000a1723303d4a5663707d8996a3b0a89b8e8275685b4f422d22170b000000000000091c2835424f5b6875828e9ba8b0a396897d7063564a3d3023170a00000000000000000000000000000713202d3a4653606d7985929fab9e918485929fa3998c7f7265584e43372b1c11060000000000000000000000000004101d2935404b5566737f8c99a3aea99e91847a6d68615955534d4f4e4d4c4c4c4b4b4c5865727f8b98a5afa396897c706356493d3023160a000000000000000815222f3b4855626e7b8895aab4a79a8e8174675b4e412f24190d010000000000061b2835424e5b6875818e9ba8b4aa95887b6f6255483c2f221509000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000006121e2b37424e57636f7c87939fa5afa9a199938f8a878584848586888c90959e948d80747b8794a1ada093877a6d6054473a2d2114070000000000000000000000000000000000000000000000010b151d252b303435393939393939393534312c261e150c000000000000000000000000000000000000000000000000000b141d242b303334393939393939393534302b251d150b0100000000000006101820262b2e2f3537383939393835322e2d2a251e19130c04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a21282c2f30393939393939382e2d2a261f180f060000000009141f29333b424648525353535353534a48443e352c22190f060000000000000000000000000000000006121d28323b444b4f51535353535353535353535353535353534a49453e362c22170c00000000030f1b26313c464e53555b5d5e5f5f5f5e5c5854524c46413a322b231a1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b9393939393887c6f6255493c2f2216090000000000000000000000060f171f252a32383b3d4144454646454443413e3c3a38342e261e140a0000000713202d3a4653606d798693939393938d8073665a4d4033271a0d00000916232f3c4956626f7c8993939393938b7e7165584b3e3225180b000915222f3c4855626f7c8895a9b3a99c8f837669554b4035291d100400000000000c17232e3f4c5966727f8c99a5b2a6998c807366594d4033261a0d000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b060000000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a0000000000000000000000000005111e2a36424d5764717e8a97a2a99a8d80818e9baa9d9083776a5f5347382e23170b00000000000000000000000000000c18242f3b4854616e7b86929fa8ada19690827a706b65615f575c5a5a5959585858585865717e8b98a4afa396897c706356493d3023160a000000000000000814212e3b4754616e7a8798a2aea89b8f827568564c4135291d11070400010407101d2935404b556976828f9ca9aea398877a6e6154473b2e211408000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000814212e3a47535f6a76828f9aa4afaba1979287827d7a79787778797b7f838a9196928a7e7b8895a1ada093867a6d6053473a2d201407000000000000000000000000000000000000000000000009131d272f373c40414646464646464642413d3730271e0e050000000000000000000000000000000000000000000000030d1d262e363c3f414646464646464641403c372f271d13090000000000030e18222a31373a3c42444546464644423f3a39363029241e160e0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101a232c33383c3d464646464646453b3a36312921180d030000020e1a26313b454d53555f60606060605f57554f473e342b21180d040000000000000000000000000000000b17232e39444d565b5e60606060606060606060606060606060575550483e33281c110400000006121f2b37434e585f62686a6b6c6c6c6b6865615e56524c443d352c241a11080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b979f9f9f95887c6f6255493c2f22160900000000000000000000060f18212930363d4448494d505253525151504d4b4846443f3830261c110600000713202d3a4653606d7986939f9f9f998d8073665a4d4033271a0d00000916232f3c4956626f7c89959f9f9f988b7e7165584b3e3225180b000a1723303d4a5663707d8996a3b0a89b8e8275685b4f422f24180c000000000000061825323e4b5865717e8b98a4b1a79a8e8174675b4e4134281b0e000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b0a4978a7d7164574a3e3124170b000000000000000000000000000714202d3a46525e6976828f9ca9a297897d7d8a98a2a095887c6f62544a3f34281c1003000000000000000000000000000714202d3a46525e6974808d96a1a9a89f9590847d77726e696a6867666665656565646465717e8b98a4afa396897c706356493d3023160a000000000000000613202d394653606c7985929faba99d908376685d5245392c221813100c0d101318202c3945515d677783909daaac9f9286796d6053463a2d201307000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000815222f3b4855626e7b88949facaea39992857d75716e686b6b666d6e72767d84909492857d8996a3aca09386796d6053463a2d20130700000000000000000000000000000000000000000000030f1a252f3941484d4e535353535353534f4d4942393020170d02000000000000000000000000000000000000000000010b151f2e3840474c4d535353535353534e4d4841392f251a0f03000000000a15202a343c4347484f5152525352514f4b4746413a3530282019110800000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f19222c353e44484a535353535353524846423b33291f1409000005121e2a36424d575f616b6c6c6c6c6c6c6361594f463d332a1f160b0200000000000000000000000000000e1b27333f4b565f676a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d2114080000000815212e3a47535f6a6f7577787979797775726d68615d564f473e362c231a100600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4aca295887c6f6255493c2f221609000000000000000000020c18212a333b42464f54565a5d5f5f5f5e5d5c5a585553504a42382e23170b00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2aca4988b7e7165584b3e3225180b000b1724313e4a5764717d8a97a4b0a79a8e8174675b4e4134281b070000000000000b1724313e4a5764717d8a97a4b0a89c8f8275695c4f4236291c0f000b1825313e4b5864717e8b97a4b1a79a8d8074675a4d4134271a0e0100000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000814212e3b4754616e7b87939fab9e9285797985929fa79a8d8073665c5044382b1f13070000000000000000000000000005121e2a36424d57606d79849197a1a9a79f969189837f7b78767574737372727271717171717e8b98a4afa396897c706356493d3023160a0000000000000006121f2b3844505b6676828f9cabac9f92867a6d6054473e3429241f1c18181d202328323b4753606d7a86929faca99c908376665c5144382c1f1206000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000d192633404c5966737f8c99a6b0ac9f92877c6f6b64615e56545c6062656c707a8290949083909daaaca09386796d6053463a2d201307000000000000000000000000000000000000000000000814202b37414b53595b606060606060605c59544b4232291f140900000000000000000000000000000000000000000007121d2731404a52585a606060606060605b59534b41372b201408000000030f1b26313c464e53555b5d5e5f5f5f5e5c5854524c46413a322b231a12080000000000000000000000000000000000000000000000000000000000000000000000000000000000040d18212b343e474f55575f60606060605f55534d453b31261a0e02000714212d3a46535f696e78797979797979706b61584e453b31281d140a0000000000000000000000000000101d2a36434f5b67717779797979797979797979797979797979716c6155493c3023170a0000000915222f3c4855626f7c81848585868584827e7a746d68605950483e352c22180d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4afa295887c6f6255493c2f2216090000000000000000000a141e2a333b454d52596063676a6b6c6c6b6a69676462605c544a3f34281c1003000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000b1824313e4b5764717e8a97a4b1a79a8d8074675a4d4134271a0e0100000000000a1724313d4a5764707d8a97a3b0a99c8f8376695c504336291d10000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b00000000000000000000000007131f2c38434f5966727f8c99a4aa9b8e817475818e9baa9e9184796d6053463a2f24180d01000000000000000000000000020e1a25303b45515d676f7c8591979ea5a8a09e95908b8885838281807f7f7f7e7e7e7e7d7d808d9aa7afa396897c706356493d3023160a00000000000000030f1c28333f4a5466727f8c99a3aea3998a7d71645a50463d352f2c292324292c2e343b444f5963707d8a99a3aea6998d807366544a4034281c1004000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000005111e2a36424d576976838f9ca9b1a79a8d80736a605954524c4a5053555a61676d798290959095a0abaca09386796d6053463a2d201307000000000000000000000000000000000000000000000c1824303c48535d64686c6c6c6c6c6c6c68655d54443b3025190e0000000000000000000000000000000000000000000c18232f3943525c64676c6c6c6c6c6c6c68645d53483c3024180c00000006121f2b37434e585f62686a6b6c6c6c6b6865615e56524c443d352c241a1108000000000000000000000000000000000000000000000000000000000000000000000000000000020b16202a333d474f5961636c6c6c6c6c6c6b615f574d42362a1e1205000815222e3b4855616e7b858686868686867d706a60574d433a2f261b110600000000000000000000000000111e2b3744515e6a7784868686868686868686868686868686867e7164574a3e3124170b0000000a1724313d4a5764707d8a9091929292918f8b86807a706b615a50473e342a1f150b010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4afa295887c6f6255493c2f221609000000000000000006111c26303b454d575e616b70747778797978777674716f6d665c5044382b1f1206000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000b1824313e4b5764717e8a97a4b1a79a8d8074675a4d4134271a0e0100000000000a1724313d4a5764707d8a97a3b0a99d9083766a5d5043372a1d10000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b0e0100000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a0000000000000000000000000915222f3b4854606b7784919eaba2988a7d70707d8a98a2a197897d7063554b4135291d11040000000000000000000000000009141f2935414b555f6a6f7c858f939c9fa4a79f9d989892908f8d8d8c8c8b8b8b8b8a8a8a8d929da9afa396897c706356493d3023160a00000000000000000b17222d3b4754616e7b86929faaab9d9083766c61584e45403a38342f2f35393a40454d56606b75828f9babab9f94887b6f6255483c2e23180c00000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000714202d3a46525e697885929fabaca095877b6e61584f4746413f44464850555d676e7b85929da0a7b1aca09386796d6053463a2d201307000000000000000000000000000000000000000000000e1a2734404d59646f7479797979797979756f65564d42362a1c11060000000000000000000000000000000000000004101c2934404b55646e7479797979797979746f64594d4034271a0e0000000815212e3a47535f6a6f7577787979797775726d68615d564f473e362c231a100600000000000000000000000000000000000000000000000000000000000000000000000000000a141d28323c454f59616b70797979797979786e695f53463a2d211407000714212d3a46535f696f7c86929a939992867d6f695f554c41382d22170d04000000000000000000000000111e2b3744515e6a77849193939393939393939393939393938a7e7164574a3e3124170b0000000a1724313d4a5764707d8a979e9f9f9f9e9b98928d847d716c61594f463c31271d12070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4afa295887c6f6255493c2f22160900000000000000000b17232e38424d575f696e767c8083858685848483807e7c786d6053463a2d201307000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000b1724313e4a5764717d8a97a4b0a79a8d8174675a4e4134271b070000000000000b1724313e4a5764717d8a97a4b0a99d9083766a5d5043372a1d10000a1723303d4a5663707d8996a3b0a89b8e8175685b4e4235281b090000000000020f1b2835424e5b6875818e9ba8b0a3968a7d7063574a3d3024170a000000000000000000000004101d2935404b55636f7c8996a0ab9f9285796d6d7985929fa99b8e8175675d5145392c20140900000000000000000000000000020d18242f3a434e585f6a6f7a82898f93999c9fa2aaa29f9d9b9a999998989898979797979a9da4aeafa396897c706356493d3023160a00000000000000000614202d3946525e6874818e98a2ab9f958a7e716a6058514b47454042434045474b51575f696f7c89939eaaa4998f82766a5f53473a2e1c120700000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000814212e3b4754616e7b8798a2aeaa9d908377695e53463d393634383a3e434c555e69717e8b97a1adb9aca09386796d6053463a2d201307000000000000000000000000000000000000000000000e1b2835414e5b687481868686868686868175695e5246382d22170b0000000000000000000000000000000000000006131f2c3845515c677480868686868686868174685b4e4135281b0e0000000915222f3c4855626f7c81848585868584827e7a746d68605950483e352c22180d0300000000000000000000000000000000000000000000000000000000000000000000000006111c262f3a444d57606b707d868686868686857b6e6155483b2e2215080005121e2a36424d57606a707e88939fa29892857b6e675d53493f33271f160c010000000000000000000000111e2b3744515e6a7784919d9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b0000000a1724313d4a5764707d8a979e9ea2a9a9aaa39f9691877e716b61584e43392f23180c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204050606060504020b1825313e4b5864717e8b97a4afa295887c6f6255493c2f2216090000000000000003101c28343f4a545f696e7b82898d9092929291908f8d8b887e7164584b3e3125180b000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000a1724303d4a5763707d8a96a3b0a89b8e8175685b4e422e23180c0000000000000b1825313e4b5864717e8b97a4b1a99c8f8376695c504336291d10000916222f3c4955626f7c8895aab4a99c8f8276695c4f4330251a0e0200000000030f1c2936424f5c6975828f9ca8b5ab95897c6f6256493c2f23160900000000000000000000000613202c3945515d6774818e9aa8aa9b8e8175676775818e9baa9f92867a6d6054473b31251a0e020000000000000000000000000007131d28313c464e585f686d757c82878b8f929897999a9b9c9d9d9d9e9e9e9e9f9f9f9fa3abacb5afa396897c706356493d3023160a000000000000000005111e2a36414d56616e7b85929fa4a79f92867c6f6a605d5553514b4f4f4b5153545c60696e7b84919ea6a69f93877c6f63584e43372b1f0b0000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000091623303c4956636f7c8996aab4a79a8e817467574d42342d2a282b2d313a434d57606d7985929eabb8aca09386796d6053463a2d201307000000000000000000000000000000000000000000000916232f3c4956626f7c89959393939392867b6e61544a3f33281c0f030000000000000000000000000000000000000714202d3a4753606d7985929393939395897c6f6356493c302316090000000a1724313d4a5764707d8a9091929292918f8b86807a706b615a50473e342a1f150b0100000000000000000000000000000000000000000000000000000000000000000000040d17222d38424c565f696f7d869299939a92867c6f695f53463a2d21140700020e1a26313b454e58616c73808c949ea1979183796d655b50443d31281d13070000000000000000000000111e2b3744515e6a7784919daab0a69e9b98989898989898978a7d7164574a3e3124170b0000000a1724313d4a5764707d8a92919297979c9fa6a9a19992877d706a5f554b4034291f1409000000000000000000000000000000000000000000000000000000000000000000000000000000020608080c0f111213131312110f0c1825313e4b5864717e8b97a4afa295887c6f6255493c2f2216090000000000000006121f2b3844505c666e7b848f949a9d9e9f9f9e9d9c9a978b7e7164584b3e3125180b000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000916222f3c4955626f7c8895a9b3a99c8f827669544a4034281c100400000000000c1926333f4c5966727f8c99a5b2a89c8f8275695c4f4236291c0f000814212e3b4754616e7b8798a3aeaa9d9084776a574d42362a1e12050000000005111d2935414c566a7783909daaafa399877b6e6154483b2e21150800000000000000000000000714202d3a4753606d7a85929faca3988a7d716464707d8a98a2a2988b7e7165574d42362a1e120500000000000000000000000000010c161f2a343c464e565e616b6f757b7f8285888a8c8d8f8f9090919191919292929292999ba3acafa396897c706356493d3023160a0000000000000000020e1925303b46535e69717e8b929da4a29891847c726d6763605c555c5c555d6063666d727b839096a1a69f948d80736b6054463c31261a0f0000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f31261e1c1f2028313b45515c6673808d99aab4aca09386796d6053463a2d201307000000000000000000000000000000000000000000000915222e3b4854606a7783909daa9fa3998c7f73665b5044382b1f1409000000000000000000000000000000000006121f2b37434e5864717e8a97a29f9f9d9083776b6054483b2f2215090000000a1724313d4a5764707d8a979e9f9f9f9e9b98928d847d716c61594f463c31271d1207000000000000000000000000000000000000000000000000000000000000000000010c161f28333f4a545d686e7b859298a29f93887e706a60574d42362a1e1205000009141f29333d46505a606c77828f96a1a0958f82776c60594f433a2f24180c0300000000000000000000111e2b3744515e6a7784919daaaa9e938f8b8b8b8b8b8b8b8b8a7d7164574a3e3124170b0000000a1724313d4a5764707d87858585868a8f949fa2aaa39992867c6f675c51453b31261a0e0300000000000000000000000000000000000000000000000000000000000000000000000003090e121415191b1d1f1f201f1f1d1b191825313e4b5864717e8b97a4afa295887c6f6255493c2f221609000000000000000713202d3a4653606d788390969fa6aaababa5a1a0a0a1978b7e7164584b3e3125180b000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000814212e3b4754616e7a8797a2adaa9d918477665c5144382c1f120600000000000e1b2734414e5a6774818d9aa7b4a89b8e8175685b4e4235281b0f000713202d3a4653606d7986929facab9f928578695e52463a2d201407000000000713202d3946525d687885929eabac9f9286796d6053463a2d2013070000000000000000000005121e2a36424d5764717e8b98a2ac9f92867a6d60606d7985929faa9c8f8376695e53463a2d21160a0000000000000000000000000000040d18222a343c444c52596063696e7276797b7d7f81828383848484848585858585868b909ba7afa396897c706356493d3023160a00000000000000000008141f2a36424d57626c74808d929fa2a19691877f79736f6d676969696a676d6f73797f869095a0a49f949082796d60594f43342a20150a0000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1824313e4b5764717e8a97a4b0a4978a7d7164574a3e3124171012161f2834404b54626f7c8998a3aeaca09386796d6053463a2d2013070000000000000000000000000000000000000000000007131f2c38434e5865727e8b98a2aeab9e9184786c6053463b30251a0e00000000000000000000000000000000000814212e3a47535f6a7683909ca9aea2988b7f7265594f43382c1f13070000000a1724313d4a5764707d8a979e9ea2a9a9aaa39f9691877e716b61584e43392f23180c03000000000000000000000000000000000000000000000000000000000000000008131e28313a44505b666d7a849197a29e948c80736c61584e453b31261a0e020000030d18212b343e44505b656d7a849199a49e948c7f726b60554b4135291e150b00000000000000000000111e2b3744515e6a7784919daaa89b8f817f7f7f7f7f7f7f7f7f7b6e6155483b2e2215080000000714202d3a4753606d79797878787a7d828a9298a1a9a2989083796d60574d42362a20150a00000000000000000000000000000000000000000000000000000000000000000000060b0f151a1e212225282a2c2c2d2c2b2a28262225313e4b5864717e8b97a4afa295887c6f6255493c2f22160900000000000004101c2834404b5564717e8a959fa8b0a9a19e9894939394968b7e7164584b3e3125180b000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000714202d3946525e687885929fabac9f9286796d6053463a2d20130a0400000006121f2b37434e586976828f9ca9b4a79a8e8174675b4e4134281b0e0006121f2b3844505c667784909daaaea298877b6e6154483b2e21150a000000000714212e3a4754616d7a8797a1adaa9e918477665c5145382c1f1306000000000000000000000714212d3a46535f6976838f9caaaa9b8f8275675d5d6775828e9baa9f93877b6e6154483d32271b0f0000000000000000000000000000050e171e252a323a41464f54575e6165666d6f717374757676777777787878787879797e8b98a4afa396897c706356493d3023160a000000000000000000020e1a25313b45505a646e74808b92989fa199928c85807c797776757676777a7c80858b9298a09f9a938d82796d675d51473d3222180e030000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825313e4b5864717e8b97a4b0a396897d7063564a3d3023170a060d18232e3a4653606d7986929facaca09386796d6053463a2d20130700000000000000000000000000000000000000000000030f1b27323d4754606d7a85929facaca1968a7d7063574d42362a1c110600000000000000000000000000000004101c2934404b55626e7b88949fabac9f92867a6d6054473d32271b0f030000000a1724313d4a5764707d8a92919297979c9fa6a9a19992877d706a5f554b4034291f140900000000000000000000000000000000000000000000000000000000000000030d19242f3a434f59606c78828f96a0a1968f82776c605a50463d33291f140900000000060f192227333f49535e68707d87939fa69f92877d6f675d51453d30271d1207000000000000000000111e2b3744515e6a7784919daaa5998c7f7272727272727272726e695f53463a2d21140700000006131f2c3845515c676d6d676b676d70767e869297a1aaa0958c8073695f53463c31261a0f0300000000000000000000000000000000000000000000000000000000000000020a11171b1f262b2e2f32353738393939383735322f2e313e4b5864717e8b97a4afa295887c6f6255493c2f22160900000000000006131f2c3845515c6776828f9ca7b1aaa197928b88868687898b7e7164584b3e3125180b000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0005111e2a36414c56697683909ca9aea399897c6f6256493d32271b13100c090e1117212e3a47535f6a7885929eabb3a6998d8073665a4d4033271a0d0003101c28343f4a546875818e9ba8b3aa978a7d7064574a3d32271b0d04000001081623303d495663707c8996a9b3a89c8f827569544b4034281c1004000000000000000000030f1c28333f4a54616e7b87939faca2988a7e7164555564717e8a98a3a49a8c7f7366584e43372b1d1207000000000000000000000000020c1720293036393a3e3f44484d5354545c606264666768696a6a6a6b6b6b6b6c6c6c717e8b98a4afa396897c706356493d3023160a0000000000000000000009141f29333f48525c646e747e868e92999c9f97928d898684838282838486898d92979f9c99948f8780796d675d554b40342b211006000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa296897c6f6356493c302316090007131f2c3845515c667683909da9aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000a16202c3945515d6774818e9aa7b1a89b8f8275695e5246382e23170b00000000000000000000000000000006131f2c3845515c6774808d9aa6b0a79b8e8174685d5245392b21160a000000000a1724313d4a5764707d87858585868a8f949fa2aaa39992867c6f675c51453b31261a0e030000000000000000000000000000000000000000000000000000000000010b151f2935414c56606b737f8c949ea49991847a6d655b50483e342b21180d030000000000071017222d38414c56606b74808d96a0a3999184796d60594f42392e23180c020000000000000000111e2b3744515e6a7784919daaa5998c7f726665656565656565615f574d42362a1e120500000004101c2934404b555c60605c555d60646c717c859298a3a79f92867b6e61584e43372b1f1409000000000000000000000000000000000000000000000000000000000000060b141b22272b31373a3b3f4244454646464544423f3b3a373e4b5864717e8b97a4afa295887c6f6255493c2f2216090000000000000713202d3a4653606d7986929facaea39892857f7b79797b7c7f7c6f6256493c2f231609000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00010d192530404d5a6673808d99a9b2ab998c7f7266584e43372b251f1c181b1a1b2228343f4a54626f7c8897a2adb1a4978b7e7164584b3e3125180b00000b17232e3f4b5865727e8b98a8b2a69a8d807367584e43372b1f15100c090e131e2a36414c5666727f8c99a5b3aa998c7f7366594c402e23180c0000000000000000000006121f2b3844505b6673808c9aa4ac9f92867a6d605454606d7a86929fac9d9184776a605447392e23180c00000000000000000000000008131e29323a4146474b4c4d4e4f51524a50535557595a5c5c5d5d5e5e5e5e5f5f5f65717e8b98a4afa396897c706356493d3023160a00000000000000000000030d17212d36414a525c646c717b81868c8f92979e99999291908f8f90919299999e9892908c88827d746d675d554b43392f22190f00000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090004101c2834404b546875828f9ba8aca09386796d6053463a2d201307000000000000000000000000000000000000000000000004111d2935414b55626f7c88959fabac9f92877b6e61544a3f34281c100300000000000000000000000000000714202d3a4753606d7985929eabaca095897c6f63564c413529190f04000000000714202d3a4753606d79797878787a7d828a9298a1a9a2989083796d60574d42362a20150a000000000000000000000000000000000000000000000000000000000007121d27313945525d68707d87939fa69f93877d6f685e53493f362c22190f060000000000000006111b262f3a444f59606d7984919ea5a0968e81746b60544b4034281e13080000000000000000111e2b3744515e6a7784919daaa5998c7f72665958585858585855534d453b31261a0e02000000000c18232f39434b515353514b51535a616a6f7c86929fa7a3988e81756a5f53473b30251a0e0100000000000000000000000000000000000000000000000000000000080f181d262d33373c4247484c4e505252535252504e4c4847433e4b5864717e8b97a4afa295887c6f6255493c2f2216090000000000000916232f3c4956626f7c8999a3aeac9f92867c726e6d6d6e70726f6a6054473b2e221508000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000081623303c4956636f7c8997a1adaa9d9083776a6054473f36302c282328252a2d333c44505c6673808c99a9b3b3a996897c6f6356493c3023160900000615222f3c4855626f7b8896a0acaa9d9184776a6054473c31271f1c181b1a1e242d3946525e6876838f9ca9aea298897c706356493d30231607000000000000000000000613202d394653606c7884919eaca99b8e8175675d51515d6775828f9caba096897c6f62544b4034281c100400000000000000000000010d1925303a444c525457595a5b5c5d5e5b5953484a4c4e4f5050515151515252525965727f8c98a5afa396897c706356493d3023160a0000000000000000000000050f1b242f38414a525a62696e747b7f8285929faba39f9d9c9c9c9d9d9fa3ab9f928682807b766f6b605d554b433a31271d100700000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000c18232e414e5b6874818e9ba7aca09386796d6053463a2d2013070000000000000000000000000000000000000000000000010d18242f3a47535f6a7683909da9afa3998c7f73665c5044382b1f14090a0a0a0a0a0a0a0a0a0a0a0a0a0a121f2b37434e5864717e8b97a2adaa9d9083776b6054443a2f241907000000000006131f2c3845515c676d6d676b676d70767e869297a1aaa0958c8073695f53463c31261a0f03000000000000000000000000000000000000000000000000000000000c18232f39434f59606d7a849199a4a0968d80736b60564c41382d231a10070000000000000000000a141d28323d45515d67707d89939ea89d93897d70665c51453a3025190d0200000000000000111e2b3744515e6a7784919daaa5998c7f7266594c4c4c4c4c4c4846423b332a1f1409000000000007121d27313940454747454045475058606a727f8c959faa9f93877c6f62574d42362a1d120700000000000000000000000000000000000000000000000000000008111a212a2f383f44464d5355585b5d5f5f605f5e5d5b5955534e464b5864717e8b97a4afa295887c6f6255493c2f2216090000000000000a1724313d4a5764707d8a97abb5a79a8e81746a6160606163656260584e43372b1f1306000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000713202d3a4653606d7984919eaaab9f95897c6f625b5146413a38342e343136383f444d57606d7984919eabb7ada297877a6d6154473a2e21140700000815212e3a47535f6a7784919eabaca095887c6f62584e4339312c282327262b2f35414c56616d7a86929facab9f9285796d6053463a2d20130700000000000000000004111d2935414c5663707d8996a1aca1978a7d7063554b4b5564717e8b99a3a89a8d8174665c5145382c1f13080000000000000000000005111d2a36414c565e6164656768696a6b68655d534840414243434444444545454d596673808c99a6afa295897c6f6256493c2f231609000000000000000000000000091217232e38424a535b606a6f767c8084919eaaa7a4a2a1a0a0a1a2a4a7a99c8f837f7b756e6a625b514b433a31281f150b0000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090000071a2734404d5a6773808d9aa6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000007131d2b37434e5864717e8b97a2adab9e9184786d6053463b31251a16161616161616161616161616161616212e3a47535f6a7683909ca9aea2988b7f7265594f4332281e1308000000000004101c2934404b555c60605c555d60646c717c859298a3a79f92867b6e61584e43372b1f140900000000000000000000000000000000000000000000000000000004101c2934404b55606b74818e96a1a59d9184796d60594f443a2f261b110800000000000000000000020b16202935404b55606b75818e98a2a59d9184796d60564c41362a1f140800000000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3f3f3f3f3b3a36312a21180e030000000000010b151f272f34383a3a3835393e464e58606c7883909da6a49a8e8175695e5246392f23180c000000000000000000000000000000000000000000000000000008111a232c333c41495053575f6265686a6b6c6c6c6b6a6865625f5853505864717e8b97a4afa295887c6f6255493c2f2216090000000000000b1825313e4b5864717e8b97a4b1a4978a7e716458535354565856544e463d32271b0f03000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000006121f2b3844505c6673808d98a2aea79c8f82766d625b524c46454041414242464950575f69727e8b96a1adb8ab9e928578685e5246392d201307000006121f2b37434e586673808d99a3afa89b8e81756a5f554b433c38342e3431373a4145525d68737f8c99a3afa79b8e8175675c5145382c1f13060000000000000000000613202c3945525d6875818e9ba8ab9e9285796d6053464754616d7a86929fab9e9285796d6053463a3025190d010000000000000000000713202d3946525e686d71727374767778756f65594d3d323536373737383835404b556774818e9aa7b2a995887b6e6255483b2f2215080000000000000000000000020c162028343f4a545c656c737c82888c9196a09f9a97959493939495979a9e9f948f8b86817b726d645d534a40352c1f150b0100000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000000000000000000000000000000000000010f1b26323c4753606d7985929fabada1968a7d7063574d42362a23232323232323232323232323232323232934404b55626e7b88949fabac9f92867a6d6054473d3221160c010000000000000c18232f39434b515353514b51535a616a6f7c86929fa7a3988e81756a5f53473b30251a0e0100000000000000000000000000000000000000000000000000020d17212c3845515c67707d89939da89e93897d6f675c51473d32281d140a000000000000000000000000050e18242f39434f59616e7b86929fa9a0968c7f72685e52463b3025190e01000000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f333232322e2d2a261f180f0600000000000000030d151d23292c2d2d2c292c343d44505b666f7c89949eac9f92877b6e61554b4034291c1004000000000000000000000000000000000000000000000000060f1a232c353e454d535b6064696e72757778797979787775726e6a64605c5464717e8b97a4afa295887c6f6255493c2f2216090000000000000c1825323f4b5865727e8b98a5afa295897c6f6256494648494c4947433d342b20150a00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000003101c28343f4a54616e7b86929fa8ab9f948b7f726d615e5653514b4e4e4f4d53535b60696e7b85929fa8b2b5a89c8f827569564c4135291d11050000030f1a26313c4854616e7b87929faaac9f92877c6f675d554e46454041414142474c515b606d7a85929eabaca095897d7063554b4034281c10040000000000000000000714212d3a4754606d7a86929faca89a8d8174665c514446525d6876828f9caba2978a7d7064564c4135291d11050000000000000000000714212e3a4754616d7a7e7f8081828485817568584e43372e2c2823282c2f3945515d677783909daaada196877a6d6054473a2d211407000000000000000000000008131e28323a44505c666d777f878f94999e9f97928e8b8887868687888b8d92979e9c99928e867f746f645c52473e31271d120700000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000a151f2c3845515d6774808d9aa6b0a89c8f8275695e5346382e3030303030303030303030303030303030303845515c6774808d9aa6b0a79b8e8174685d5245392c2013040000000000000007121d27313940454747454045475058606a727f8c959faa9f93877c6f62574d42362a1d12070000000000000000000000000000000000000000000000000009141f2a36414c56606d7984919ea5a2988e81756b60554b40352b20160b020000000000000000000000000007121d27313d46525e6973808d97a2a89f92857a6d61564d41362a1e1308000000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326252522211e1a140e06000000000000000000030b12181c1f20201f1d2228333f4a54606b75828f9ca8a3998d8073675c5145382c1f14090000000000000000000000000000000000000000000000030e18212c353e474f575f656c71767b7f8183858586858583817f7b77716d665f64717e8b97a4afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea195887b6e6255483b3b3d3f3c3b37322b22190f0400000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000b17232e3846525e6973808d96a0aaa69f93877f746d6863605c545b5b5c575e61656c717b849198a2aebab3a9988c7f7265594c3f3025190d010000000a15212d3a46535e6975818e98a3aea3999083796d675f5853514b4e4e4e4d53555d606d74818e97a1ada69d9083776b605443392e23180c00000000000000000006121f2b37434e5865727e8b98a2aca096897c6f63544a40414c5665727e8b99a4a99b8f8275685e5246392d2015090000000000000000000815212e3b4854616e7b878c8d8e8f909184786a6054473f3a38342e34383a404b55606d7a86929facab9e918578675d5145392c20130600000000000000000000010d1924303a44505a606d78818c93999fa098928c85817e7b7a797a7a7b7e81858b92979f9f99928b81746e63594f43392f24180c00000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000004101d2935404b55626e7b88949fabac9f93877b6e61544a3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4753606d7985929eabaca095897c6f63564c4135291d110400000000000000010b151f272f34383a3a3835393e464e58606c7883909da6a49a8e8175695e5246392f23180c000000000000000000000000000000000000000000000000020e1a25303946525e68737f8c96a0a99f92867a6e61594f43392f23190e040000000000000000000000000000010b151f2a36424d57606d7a85929eaaa2978d8074685e52463a2f24190d010000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f332619191514120e0903000000000000000000000001070c10131414131017222d38424f5963707d8995a0ab9e9285796d6053473b31261a0e000000000000000000000000000000000000000000000009141f2a333e474f5961696e787e83888b8e909292939291908e8c88847e786e6a64717e8b97a4afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e30322f2e2b27201910070000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000006111c2a36424d56606d79849198a2aba499938b807a736f6d666968676869696e71787e859196a1aab3b9ada297887c6f6255493c2f2216080000000005121e2a36424d57616e7b86929fa6aba0958f82796f6a63605c555b5a5b575f62676d747f8c939ea9a99f948a7d7064594f4430271d12070000000000000000000814212e3a47535f6a7683909daaaa9e9184776b605442393b4754616e7b86939fac9f92867a6d6154473c31261a0e0000000000000000000714212d3a46535e697884919a9b9c9d96897c6f625a504a464440434044464b515c67717e8b98a3aeaa9b8f827568554b4135291d11040000000000000000000004111d2935414c56616c74808d939fa4a09591867f7a74716f6e6d6d6e6f7174797e8590959fa39f938d80736b61554b4035291d1004000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000c18242f3947535f6a7683909ca9afa4998c8073665c504949494949494949494949494949494949494949494e5864717e8b97a2adaa9d9083776b6054443a2f24190d010000000000000000030d151d23292c2d2d2c292c343d44505b666f7c89949eac9f92877b6e61554b4034291c1004000000000000000000000000000000000000000000000005121e2a36424d57616e7a86929fa8a1978c8073685e52473d31271d110700000000000000000000000000000000030d1a25303b45525d6873808c98a2a99f92867b6e61554c4135291d11040000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0807050200000000000000000000000000000000040607070606111c262f3d4854606b7784919daba2978a7e7164574d42362a1b1106000000000000000000000000000000000000000000020b1a26313b454f59616b707b838a9095989b9d9e9f9f9f9e9d9b9895908b837c6f6b717e8a97a4afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e232523221f1b150f07000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000000e1925303b45515d676f7c869299a2aaa49f928d86807c79767574747576787b7e838a9297a1a8b2bcb8ab9e9285796c605346392d20130600000000020e1a25313b46535f69737f8c949fa7a79f948f837c75706d676867676869696e737a818c919ca5aaa1978f82766c6155473d331e150b00000000000000000003101c28343f4a54626e7b88959faba7998c807366594f43303946525e687683909ca9a3998b7f7265574d42372b1b1106000000000000000005121e2a36424d576774818e9aa6a9a89b8e81756c605c5453514a504a5153555d606d7983919daaaea2988b7e7165584b3e2f24180d01000000000000000000000713202c3945525d68717e8a929da5a19791837b726d676462616060616264676d717a839096a1a59c928a7d70675d5145392c1f150a000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000007121d2b37434e5864717e8a97a1adab9e9184796d6056565656565656565656565656565656565656565656565f6a7683909ca9aea2988b7f7265594f4332281e130800000000000000000000030b12181c1f20201f1d2228333f4a54606b75828f9ca8a3998d8073675c5145382c1f140900000000000000000000000000000000000000000000000714202d3a46525e6974818d98a2aa9e92857a6d60564c41352b1f150b00000000000000000000000000000000000009141f2935414c56616d7a86929faca3988d8073675d5145392c20150a0000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000000000000000a141d2c38444f5965727f8c99a3a99c8f8276695f5346382d22170b0000000000000000000000000000000000000000000a141d2a36424d57616b707d8690959d9fa7a8aaaaa39f9e9e9e9fa3a09d9590867d6f717d8a97a4afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e22191615130f0a0400000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000009141f2935404b55606a707e879298a0a7a49d98928d898583828181828384878b90959ea1a9b2babeb2a99b8e8175665b5044382b1f1206000000000009141f2a36424d57606d78828f959fa7a69f959087817d79777574747476787b80858e939ca3aaa29892857b6e615a5044352b210c0300000000000000000006121f2c3844505c6673808d9aa7ab9f95887b6e6255483d3236414d5665727f8c98a7ab9d908376695f5347382d22170b0000000000000000020e1a25313c4855626f7c88949faaaa9e938a7e726d6662605c545d545c6062676d75808d95a0aca99f92867a6d6154473a2e2114070000000000000000000003101c28343f4a54606d7a85929ea4a79e91857b6e69605d55555453535455555c60686e7a84919ea8a49e9184796d6053473c31261b0f030000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000010f1a26313c4653606d7985929eacada1968a7d70646363636363636363636363636363636363636363636363636e7b88949fabac9f92867a6d6054473d3221160c01000000000000000000000001070c10131414131017222d38424f5963707d8995a0ab9e9285796d6053473b31261a0e0000000000000000000000000000000000000000000004111d2935414c56616e7b86929faaa2988c7f73675d51443b3023190d03000000000000000000000000000000000000020d19242f3a46525e6874808d9aa6aa9f92857a6d6054473c31261b0f0300000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000000000000020b1c27333d4754616d7a86929fac9f93877b6e6153493f33271b0f030000000000000000000000000000000000000006111b262f3846535f69707d8792989fa7aba8a09d9898929191919299989d9f9892867c707d8a96a3afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221509080603000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000000020c18242f39434e58616c707d8690959ea1a9a29f9a9892908f8e8e8f8f9196989da09f9da0a8b2b9ada1978a7d7063544a3f33281c0f030000000000030e1a26313b44505c666d7a8390959da5a7a099938e898683828181818385888c92979da5a7a09892867d70695e52483e3323190f000000000000000000000713202d3a4653606d7985919eabab9d908377695f53473a2b303b4854616e7b8795a0ab9f95887b6e6253493f33271b0f0300000000000000000915212e3b47535f6a76828f98a2aea59f92877f78726f6d666a696a666d6f7379818d929da7aca2978d8074685d5246392d2013070000000000000000000006121f2b3844505c66737f8c97a1ab9f958a7d70695f57514b4847464747484b51565e68717e8a96a0aca1968b7f7265584e43372b1f12060000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000009151f2c3845515c6673808d9aa4afa99c8f82757070707070707070707070707070707070707070707070707074808d9aa6b0a79b8e8174685d5245392c201304000000000000000000000000000000040607070606111c262f3d4854606b7784919daba2978a7e7164574d42362a1b11060000000000000000000000000000000000000000000713202c3945525d6874808d99a3ab9f92857a6d60554c4132291e1107000000000000000000000000000000000000000008131e2935414c56626f7b88949faba2988b7f7265584e43372b1f120600000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000000000000000b13202d3a4653606d7985929eaba49a8c8073655b5044372b1f1207000000000000000000000000000000000000000b17222d3841505a616e7b859299a2aaaba39f96918c888584848586888c90959e9891847a7d8996a3afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000000007121d27313d46505a616b707c838b91979c9fa3aaa29f9d9c9b9a9b9c9ea1a29f9a939196a0acb8ab9e9184796d6053463a2d22170b0000000000000009141f28343f4a545e686d7a838e929d9fa7a49f9b9892908e8e8d8e8f9197999ea1a9a29e9590867d706b60574d42362c22110800000000000000000005111d2a36414c5663707d8a97a1ada3998c7f7265574d42372b2d3a46535e697783909daaa7998d8073655b5044372b1f1207000000000000000006121f2b37434e58626f7c86929fa4aca399928b837f7b797777767777797c80858e939da4aea49a92857a6d61564c4135291d1105000000000000000000000713202d3a4653606d7984919ea9a99d9083766b61574d45403c3b3a3a3b3c40454c56606c7884919eaaa89d9184776a5f53473a2e2115080000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000004101c2834404b54616e7b87939facac9f93877d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d85929fabaca095897c6f63564c4135291d11040000000000000000000000000000000000000000000a141d2c38444f5965727f8c99a3a99c8f8276695f5346382d22170b0000000000000000000000000000000000000000000714212d3a4754606d7a86929faba69a8d8074685d52433a2f20170d000000000000000000000000000000000000000000010d1925303a47535f6a7683909cacaa9d9184776a5f53473a2e21150a00000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000000000000000000000000000005111d2a36414c5664707d8a97a1adac9e9184786c605346392f24180c000000000000000000000000000000000000030f1b27333f4953616c76828f97a2ababa399928c847f7b79787778797b7f838a9197968e817d8996a3afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000010b151f2b343e485059616a6e787e858a8f9299999b9d9e9f9f9f9e9e9c9998928e8684919daab0a69a8d8073665c5044382b1c110600000000000000030b17232e38424c565e686d79818990959b9fa2aaa39f9d9b9a9a9b9c9ea1a9a49f9c97928c837b706b60594f453b30241a10000000000000000000000713202d3946525e6875828f9ba9ac9f92867a6e6154473c31262a36424d5766737f8c99a7ab9e9184786c605346392f24180c0000000000000000030f1b26323c47535f6a717e8b939aa2aaa39f95918c8886848483838485898c92979ea5aaa39f93887d70685e52443a3024190d0100000000000000000000091623303c4956636f7c8996a1adab988b7f7265594f453c352f2e2d2d2e2e343b44505b6674808d9aa7aca095887b6f6255483c2f2215090000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9afa499938a89898989898989898989898989898989898989898989898989899297a2adaa9d9084776b6054443a2f24190d01000000000000000000000000000000000000000000020b1c27333d4754616d7a86929fac9f93877b6e6153493f33271b0f030000000000000000000000000000000000000006131f2b37434e5865727f8c98a2ab9f94887b6e62564c4131281e0e050000000000000000000000000000000000000000000008131e2b37434e5865727f8b9aa4aca095887b6f6255483c32261b0f03000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000000000000000713202d3946525e6875828f9ba9b3aca196897c6f63554b4035291d1004000000000000000000000000000000000005121f2b3744505b65717e8a949fa9aea39992877f78726e6c666b666d6f72777e859095938c7f8c99a6afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000000000030d19222c363e474f575f666d72797e82868a8c8e909192929292918f8d8a86817c838f9ca9aa9e93887b6e62544a3f34281c0a00000000000000000006111c26303a444c565e676d747c83898e9298999b9d9e9f9f9f9f9e9d9b999993908b857f786e6960594f473d33291f1208000000000000000000000714212e3a4754616d7a86929facaa9c8f8276685e5246392a2025313b4855626e7b8895a0aca196897d7063554b4035291d100400000000000000000a15202b37434e58616c727f8892989fa3a7a09d99999291909090919298999ea2a9a69f98928b7f726c61564c4132281e130800000000000000000000000c1926333f4c5966727f8c99a8afa499887b6e6255483e332924212020212328333f4a5464717d8a97a4b1a7988b7e7265584b3f3225180c0000000000000000000203101d2a3643505d69768390908376695d5043362a1d10030200000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000007121d2a36424d5764707d8a96a1adaba49f9796969696969696969696969696969696969696969696969696969fa2a9aea2988b7f7265594f4332281e130800000000000000000000000000000000000000000000000b13202d3a4653606d7985929eaba49a8c8073655b5044372b1f1207000000000000000000000000000000000000000815212e3b47535f6a7784919daaac9c8f83766a5f53443a301f160c0000000000000000000000000000000000000000000000020f1a26313c4754616e7b87939faca7998c807366584e43372b1f1306000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000000000000000714212e3a4754616d7a86929facb9b2a89a8e8174675d5145382c1f140800000000000000000000000000000000000613202d394653606c7883909da6b0a79f92877d726d6662605b545c6062656c717a8390969285929facafa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000007101a232c353e454e545c60676d71767a7d7f828385858686858482807d79757d89949faba69b8f82756a5f5342382e23170b000000000000000000000a141e28323a444c555c606b6f777d8185898c8e90919292929291908f8d8a86837e79726d665f574f473d352b20170d0000000000000000000006131f2b37434e5865727f8b99a3aea2988b7e7164564c41362a18212e3a47535f6a7784919daaa89b8e8174675d5145392c1f14090000000000000000040f1a26313c46505a636d727e868e92999da0a8aba39f9e9d9c9d9e9fa2aaaaa29f9b948f867e726d62594f443a3020160c0200000000000000000000020f1c2935424f5c6875828f9ba8ac9f9386796c605346392d20181413141418222d3c4956626f7c8995a2afa79a8e8174675b4e4134281b0e01000000000000050a0f12101d2a3643505d69768390908376695d5043362a1d10120f0a050000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000305101d2a3643505d69768390908376695d5043362a1d1005030000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000e1a26313b4653606d7984919eabb5afaca3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3abadb3ac9f92867a6d6054473d3221160c010000000000000000000000000000000000000000000005111d2a36414c5664707d8a97a1adac9e9184786c605346392f24180c000000000000000000000000000000000000000916222f3c4955626f7c8896a0aca49a8b7e7265574e4232281e0d040000000000000000000000000000000000000000000000000a15202d3a46525e697683909da9aa9e9184776a5f54473b2e221506000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000000000006131f2b37434e5865727f8c99a3aeb7b8ab9f9285796d6053473b3025190e02000000000000000000000000000000030f1c28333f4a5463707c8995a0acab9f958b7f726b605c5453504a5153555a61686e7a8491989298a2aeafa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0600000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000000000000008111a232c333c424a50555c6064676d707375767878797978777673716d7883909da6ac9e93887c6f62584e4330261c110600000000000000000000020c162029323a434b515960636b7075797c7f82838485868685858382807d7a76726d67605c544d453d352b23190e05000000000000000000000815222e3b47545f6a7783909dabac9f92867a6d6054473b3025191e2b37424e576673808c99a8ab9f9285796d6053473b3025190e0200000000000000000a15202a343e48515b636c717b81878c919597999c9d9e9e9f9f9f9e9d9b9998928e89827b716c625b51473e32281e0e04000000000000000000000003101d2a3643505d697683909ca9ab9e928578665b5044382b1f120707070715222e3b4855616e7b8894a1aea89b8f8275685c4f4235291c0f0200000000010910161b1e20202a3643505d69768390908376695d5043362a20201e1b16100901000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000060b0f12131d2a3643505d69768390908376695d5043362a1d13120f0b06000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a3afbbb9b1acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa7a9afb8bab1a79b8e8174685d5245392c20130400000000000000000000000000000000000000000000000713202d3946525e6875828f9ba9b3aca196897c6f63554b4035291d1004000000000000000000000000000000000006131f2b37434e586673808d99a8ac9f93877b6e6154473c3121160c0000000000000000000000000000000000000000000000000005111e2a36424d5765727f8c98a9aca096887c6f6255493c2d22170b000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000000000000000000000000000815222e3b4754606a7783909dabacababaea2988a7e7164564c41362a1e110500000000000000000000000000000006121f2b3844505b6674818e9ba7b1a99d9083786c6059504a46444044464850565e68707d89939fa2aab4afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0aca79a8d8174675a4e412d22170b00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000000000000000008111a212a30383f444b5153555d606366686a6b6c6c6c6b6b696668717e8b95a0aca49a8f82756a5f54463c311e140a000000000000000000000000050e172029313940454f54596063676d70727576787879797878777573706d6865605d55504a423c332b231911070000000000000000000004101c2834404b55626f7c8895a0aca99b8e8175675d514539291e141a26313c4955626f7c8896a0aca2988a7e7164564d42362a1e11050000000000000000030e18222d363f49515a61696e747b8084888b8d8f90919292929291908e8c8985817c766e69615a51493f352c20160c00000000000000000000000004111e2b3744515e6a7784919daaab9e9184786b554b4034281c100400000814212e3b4754616e7a8794a1ada99c908376695d5043362a1d1003000000010a131b21272b2d2d2d3643505d69768390908376695d5043362d2d2d2b27211b130a010000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000020a11171b1f202a2d3643505d69768390908376695d5043362d2a201f1b17110a0200000000000000000000000000101d2a3643505d69768390908376695d5043362a1d10000000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87929facb9b1a7a0939393939393939393939393939393939393939393939b9ea5afb8aca095897c6f63564c4135291d110400000000000000000000000000000000000000000000000714212e3a4754616d7a86929facb9b2a89a8e8174675d5145382c1f140800000000000000000000000000000000000815222e3b4754606a7784919eaaa99c908376685e5246392d20140400000000000000000000000000000000000000000000000000020e1a25303b4855616e7b8896a1ada8998c7f7366544a3f33281c0f030000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000000000004101c2834404b55626f7c8895a0a8a19e9fa2aa9c8f8275685e5246392d20150a0000000000000000000000000000000613202d394653606c7985929eabada1978a7d70655b50443f393834383a3e444c56606b75828f9ba8b1bcafa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0aca89b8e827568544a3f33281c0f03000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000000000000000030e1a242f3841474c4e4c474c515457595b5d5e5f5f5f5f5e59616d7a85929ea7a89f93877c6f62584e43342a200c0200000000000000000000000000050e171f272f343d43484f54555c606366686a6b6c6c6c6c6b6a686664615e5653514b443f38302a21191108000000000000000000000006131f2c3845515c6774808d9aa7ada1978a7d7063554b413529170d15212e3b47535f6a7784919eaaaa9c8f8276695e52463a2d20150a00000000000000000006101b242e373f4850575e61696e73777b7e80828484858686858583827f7d79756f6b625f5750483f372d231a0e0400000000000000000000000004111e2b3744515e6a7784919daaab9f928578675c5145382c1f130f0b0c1015222f3b4855626e7b8895a1aea99c8f8376695c504336291d100300000009131c252c33373939393943505d69768390908376695d50433939393937332c251c13090000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000020b141b22272b2d37393943505d69768390908376695d50433939372d2b27221b140b0200000000000000000000000811192a3643505d69768390908376695d5043362a1911080000000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000c17232e3846525e6975828f9ca8b2aca095898686868686868686868686868686868686868686868e939ea9b4aa9d9084776b6054443a2f24190d010000000000000000000000000000000000000000000006131f2b37434e5865727f8c99a3aeb7b8ab9f9285796d6053473b3025190e02000000000000000000000000000000000916222f3c4955626f7c8896a0aca8988c7f7265564d41362a1e110500000000000000000000000000000000000000000000000000000914212d3a46535f697884919eaba99c8f8276665b5044382b1f12060000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000000000006131f2c3845515c6774808d9aa7a196919298a29f92867a6e6154473c31261b0f0000000000000000000000000000000916222f3c4955626f7c8897a1adab9e9285796d6053493f342e2b282c2d323b444f59626f7c8995a0acb8afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0aca99c8f8376665b5044382b1f120700091623303c4956636f7c8996a2afa4988b7e7165584b3e3225180b00000000000000000008141f2b36414a52585a5954524c474a4c4f50525253534c56616b74818e97a1ada1968d81746a5f54463c3222180e000000000000000000000000000000050d151d232932383d44484b515356595b5d5e5f5f5f5a61646c6c6c6c66635c524739342e261e180f080000000000000000000000000713202d3a4653606d7985929eabab9e9285796d6053463a2f241807131f2b37434e586773808d9aa8ac9f93877b6e6154473c32261b0f0000000000000000000009121c252e363e454d52575f62666a6e71737577787879797978777573706d67636059534d453e362d251b11080000000000000000000000000003101d2a3643505d697683909ca9aea29886796d6053463a2f241f1c17181c1f262f3d495663707c8996a3afa89b8f8275685c4f4235291c0f02000005101b252e373e434646464646505d69768390908376695d504646464646433e372e251b100500000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000a141d262d33373943464646505d69768390908376695d50464646433937332d261d140a0000000000000000000009111a232b3443505d69768390908376695d5043342b231a110900000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000006111c2a36424d5763707d8a96a1acaa9d9083797979797979797979797979797979797979797979818e9ba7aea2988b7f7265594f4332281e130800000000000000000000000000000000000000000000000815222e3b4754606a7783909dabacababaea2988a7e7164564c41362a1e110500000000000000000000000000000003101c28343f4a546673808c99a8ada196887b6e6155483b3025190e02000000000000000000000000000000000000000000000000000005121e2a36424d576875828f9ba8ab9f9285796c605346392d2013060000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000000000713202d3a4653606d7985929fab9e918485929fa3998c7f7265584e43372b1c110600000000000000000000000000000c1926323f4c5965727f8c98a9b3a89b8e8175665c5041382d231f1c1f2029323d4854606a7784919daab7afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0acab9f9285796c605346392e23180d060a1723303d4a5663707d8996a3b0a4978b7e7164584b3e3125180b0000000000000000000b1724303c47525c646766615e56544e46454045453f49535d68707d8a939da9a59e91847a6d60584e43342a200f0600000000000000000000000000000000030b121821272c323839404546494c4f50514a505b636c7079797979736e63574b3f32231c150c0600000000000000000000000005111e2a36424d5664717d8a97a2ada89a8d8174665c514438281d13070f1b26323c4956626f7c8996a1ada4998c7f7265584e43372b1c1106000000000000000000000a131c242c333b42464d5355575f626466696a6b6b6c6c6c6b6a686663605d55544f47423c332d241b13090000000000000000000000000000020e1b2835414e5b6874818e9ba7b3aa96897c6f63554b40352f2b282223282c3038414e5865727f8c98a5b5ab9a8d8073675a4d4034271a0d0100000a16212c3740494f5353535353535d69768390908376695d5353535353534f4940372c21160a00000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000006111b262f383f444650535353535d69768390908376695d535353535046443f382f261b1106000000000000000006121b232c353d464e576976839090837669574e463d352c231b1206000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000e1a25303b4653606c7884919eabaca095897c6f6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7a86929facac9f92867a6d6054473d3221160c010000000000000000000000000000000000000000000004101c2834404b55626f7c8895a0a8a19e9fa2aa9c8f8275685e5246392d20150a00000000000000000000000000000006121f2b3844505c6676828f9ca9ab9e918478695f53463a2d1f1408000000000000000000000000000000000000000000000000000000020e1a26313f4c5965727f8c98abaea298887c6f6255483c2f2215090000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000000000000000000000005111e2a36424d5764717e8a97a2a99a8d80818e9baa9d9083776a5f5347382e23170b00000000000000000000000000020f1b2835424e5b6875818e9ba8b5ab988b7e7165544a3f2f261b12101217202c38434e586673808d99abb5afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0acada297887c6f62544a4034281f1612101724313e4a5764717d8a97a4b0a4978a7e7164574b3e3124180b0000000000000000000d1a2633404c58646e74736e6862605853514b464244505b656d7a84919ea5a79e938a7d70675d51463c3222190e00000000000000000000000000000000000001070c161b21272c2e34383a3d3f42444c545c606d727e868686868073665a4d4033271a0a03000000000000000000000000000714202d3a46525e6975828f9ca9aca096897c6f63544a403428160c010a13202d394653606c7884919eabab9d9084776a5f5347382e23170c00000000000000000000010a121a212930363c4247484e5355585a5c5d5e5f5f5f5f5e5d5b595653514b48433d37312a211b1209010000000000000000000000000000000c1925323f4c5865727f8b98a7b1a6998c8073675d5145403938332d2e34383a4149535f6a76828f9ca9afa4998a7e7164574b3e3124180b0000000f1b27333e49525a5f60606060606069768390908376696060606060605f5a52493e33271b0f00000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000b17222d38414950535d6060606060697683909083766960606060605d53504941382d22170b000000000000020a1117242d363e474f585f69768390908376695f584f473e362d2417110a0200000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000009141f2b3844505b66727f8c99a3aea79a8d8174675c606060606060606060606060605765717e8b98a2aea79b8e8174685d5245392c201304000000000000000000000000000000000000000000000006131f2c3845515c6774808d9aa7a196919298a29f92867a6e6154473c31261b0f0000000000000000000000000000000713202d3a4653606d7985929faba89b8e827568574d42362a1e0d0200000000000000000000000000000000000000000000000000000000091623303c4956636f7c8999a3aeaa988b7e7265584b3f322518070000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000000000714202d3a46525e6976828f9ca9a297897d7d8a98a2a095887c6f62544a3f34281c100300000000000000000000000005111d2a36414c566a7784909daaafa499887c6f6255483c2e22140a04060e1b27323d495663707c8999a4afafa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0acb3a9998c7f73665c51443b3128201f1c1f25323f4c5865727f8b98a5b0a3968a7d7063574a3d3024170a0000000000000000010e1b2734414e5a6774807f7a756f6a64605c55524d505a606c77828f96a1a9a0958e81756b61554c41342a2010070000000000000000000000000000000000000000040a0f161b1d23282c2d343d454d565d666d747f87929892857b6e6154473b2e21140800000000000000000000000000000814212e3b4754616e7b86929facaa9e9184776b605442392e2318040005121f2b3744505b6574808d9aa9aca095887c6f62544a3f34281c10030000000000000000000000080f171f252a31373a3c4247484b4d4f51515253535252504f4c4a4745403938322b2620180f0900000000000000000000000000000000000815222f3b4855626e7b88959fabab9e9185796d605a514b46443f42424045464c525b656e7b87939facac9f93867a6e6154473b2e211408000000121e2b37434f5a646c6c6c6c6c6c6c6c7683909083766c6c6c6c6c6c6c6c645a4f43372b1e1200000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000030f1b27333f49535b606a6c6c6c6c6c6c7683909083766c6c6c6c6c6c6a605b53493f33271b0f0300000000020b141b2227363f485059606a6f7b859191857b6f6a605950483f3627221b140b02000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000030f1c28333f4a54616e7a86929facab9f9285796d60535353535353535353535353535f697683909caaaca095897c6f63564c4135291d110400000000000000000000000000000000000000000000000713202d3a4653606d7985929fab9e918485929fa3998c7f7265584e43372b1c110600000000000000000000000000000916222f3c4955626f7c8898a2aeab988c7f7265594c3f31261a0e02000000000000000000000000000000000000000000000000000000000714202d3a4753606d7986929faca79b8e8174685b4e412e23180c0000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000000000814212e3b4754616e7b87939fab9e9285797985929fa79a8d8073665c5044382b1f13070000000000000000000000000713202d3946525e687985929facac9f93867a6d6053473a2d20140700000a14202d3a4753606d7a86939facafa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0acb8ab9e9184796d60574d433a322d2c282b2d36414c566774808d9aa7b3aa95897c6f6256493c2f2316090000000000000000020f1c2935424f5c6875828c86817c76716d67615e5759616c727f8c949ea9a2979083796d60594f433a2f22190e0000000000000000000000000000000000000000000000040b0c151d2328363e464f575f686d78818c939993877d70695e52463a2d2014070000000000000000000000000007131f2c38434f5966727f8c99a3afa7998c807366594f4330271c120700030f1b27333f495363707c8997a1ada79a8d8074665c5044382c1f1206000000000000000000000000050d141a1f262b2e31373a3b3e4042444545464646454442403d3a38352f2c27211a150e060000000000000000000000000000000000000814212e3a47535f6a7683909da6ada1978c80736c605c5553504a4e4f4b5153565d616c77828f99a4afa69c8f8276685e5246392d20140700000013202d3946535f6c767979797979797979839090837979797979797979766c5f5346392d201300000000000000000000101d2a3643505d69768390908376695d5043362a1d0a0000000000000000000005121f2b3744505b656c76797979797979798390908379797979797979766c655b5044372b1f1205000000000a141d262d334048505a616b6f7c8591979791857c6f6b615a504840332d261d140a000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000b17222d3846525e6875828e9ba8ada2978a7e7164574d42464646464646463f4a54626e7b88949fabaa9d9084776b6054443a2f24190d010000000000000000000000000000000000000000000005111e2a36424d5764717e8a97a2a99a8d80818e9baa9d9083776a5f5347382e23170b00000000000000000000000000000c1825323f4b5865727e8b98aaaea399897c6f6356493c30231609000000000000000000000000000000000000000000000000000000000006131f2c3845515c677784919eaaa99c90837669554b4034281c100400111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000007131f2c38434f5966727f8c99a4aa9b8e817475818e9baa9e9184796d6053463a2f24180d0100000000000000000000000714212e3a4754616d7a8798a2aeab9e918478675c5145382c1f1306000006131f2c3945515d677784919eaaafa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0acb9ada1968b7e71695e554c443e3a383437393e46525e687683909ca9aea298877a6e6154473b2e2114080000000000000000020f1c2935424f5c6875828f928e89837e79736e6963606b707e88939fa6a39992857b6e675d51473e31281e10070000000000000000000000000000000000000000000000060e161e272e344048505960696e7a828e939f948c7f736b60574d42362a1e1105000000000000000000000000000915222f3b4854606b7784919d9f9f9f95887b6e6255483d3222150b0000000b17222d3a4653606d7985929e9f9f9e9185796d6053463a2d2013070000000000000000000000000002090e151a1e21262b2e2f31333637383839393938373533302d2c29241d1b160e09030000000000000000000000000000000000000006121e2b37424e5764707d8a949fa9a99c928b7e746d6762605b545b5b555c6062686d75808d949eaba99e94897d7063564c41362a1e110500000013202d394653606c798686868686868686909494908686868686868686796c605346392d2013000000000000000000020b142a3643505d69768390908376695d504331261a0b020000000000000000000613202d394653606c798386868686868686909494908686868686868683796c605346392d20130600000006111b262f383f44515a626c707d8591938e8e9391857d706c625a51443f382f261b11060000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000006111c2a36414c5663707d8996a0aca99c8f8276695e5246382d393939393844505c6673808d99a6aea2988b7f7265594f4332281e130800000000000000000000000000000000000000000000000714202d3a46525e6976828f9ca9a297897d7d8a98a2a095887c6f62544a3f34281c1003000000000000000000000000020e1b2835414e5b6874818e9ba7ac9f9286796d6053473a2d201407000000000000000000000000000000000000000000000000000000000004101c2934404b556976828f9ca9ab9e918478675c5145382c1f130600111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000000000000000000000915222f3b4854606b7784919eaba2988a7d70707d8a98a2a197897d7063554b4135291d110400000000000000000000000915222f3c4855626f7b8895aab4a99d9083766a554b4034291c1004000004101d2935404b556976828f9ca9afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0acb1a8a09d92857b6e675e56504846443f4446484f58616d7a86929facab9f928578695e52463a2d2014070000000000000000020f1c2935424f5c6875828f999b95908b85807b756f6b6f7d86929aa4a49f92877d70695f554b41352c1f160c0000000000000000000000000000000000000000000000070f18202830394045525a616b6f7b838f949d968f82776c60594f453b30251a0e0200000000000000000000000000091623303c4956636f7c8996939393939083776a5f53473a2e21140300000006121f2b3844505c6674818e93939393978a7d7063574a3d3024170a00000000000000000000000000000003090e12151a1e21222527292a2b2c2c2c2c2b2a282623201f1d18120f0a04000000000000000000000000000000000000000000020e1a26313c4955616c76828f97a1aaa49f93888079736f6c6669686869676d6f747a818d929ca6aaa1978f82766b6055443b3025190e0200000013202d394653606c798693939393939393969696969393939393939386796c605346392d20130000000000000000000a141d2b37434e586976839090837669584e43372b1d140a00000000000000000005121f2b3744505b656f7c899393939393939c9f9f9c939393939393897c6f655b5044372b1f12050000000b17222d384149505b636c717e8692928c81818c9292867e716c635b504941382d22170b0000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000d1925303b4854606b7784919daaac9f93877b6e6153493f33272d2d2d3a4653606d7984919eabac9f92867a6d6054473d3221160c0100000000000000000000000000000000000000000000000814212e3b4754616e7b87939fab9e9285797985929fa79a8d8073665c5044382b1f130700000000000000000000000004101c2934404b55697683909ca9aa9e918477675c5145382c1f13060000000000000000000000000000000000000000000000000000000000000c18232f414e5b6774818e9aa7ac9f9386796d6053463a2d20130700111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000004101d2935404b55636f7c8996a0ab9f9285796d6d7985929fa99b8e8175675d5145392c20140900000000000000000000000a1623303d495663707c8996a3afa89c8f8275695c4f422f23180c000000000c18242f414e5a6774818d9aa7afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508000000000000000000000713202d3a4653606d798693a0acaca09591959082796d68615a5553504a50535459616a73808c99a3afa99c8f827669564d42362a1e11050000000000000000000d1a2633404d59667380878c91979c97928c86827c777c859298a2a49a938b7f726b60574d433a2f231a0d0400000000000000000000000000000000000000000000071019212a323a434b515b636c717d8591959f9991847a6d655b50473d33291f140900000000000000000000000000000e1b2834414e5b677481868686868686867f7265574e42372b1e120600000003101c28343f4a5463707d868686868686868175685b4f4235281c0f00000000000000000000000000000000000206090e121415181a1c1e1e1f20201f1f1d1c19171413100c07010000000000000000000000000000000000000000000000000915202d3944505a616e7b859298a1a9a49a938d85807b79767575757677797c81858e939ca4a9a19892857b6e61594f4432291e14080000000013202d394653606c798693928d8989898989898989898989898d929386796c605346392d2013000000000000000006111b262f3847535f6a7683909083766a5f53473d2f261b11060000000000000000030f1b27333f4953606b75828f99a39f9f9fa9ababa99f9f9fa3998f82756b6053493f33271b0f030000030f1b27333f49535b606d737e8792928b807474808b9292877e736d605b53493f33271b0f0300000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000008141e2c38444f5965727f8c98a3aea4998c7f73655b5044372b1f2a36414c5663707d8a97a1ada79b8e8174685d5245392c201304000000000000000000000000000000000000000000000007131f2c38434f5966727f8c99a4aa9b8e817475818e9baa9e9184796d6053463a2f24180d01000000000000000000000006131f2c3845515c677885919eaba99c8f827669554b4034291c1004000000000000000000000000000000000000000000000000000000000000071926333f4c5966727f8c99a5afa49a887b6e6255483b2f22150800111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000613202c3945515d6774818e9aa8aa9b8e8175676775818e9baa9f92867a6d6054473b31251a0e02000000000000000000000a1724313d4a5764707d8a97a3b0a89b8e8175685b4e4235281b0700000000071a2633404d596673808c99a6afa295887c6f6255493c2f2216090000000000000c1925323f4c5865727f8b98a5aea194887b6e6155483b2e221508080400000000000000000713202d3a4653606d798693a0acaa9d9184919590837a716c6662605c545b6061646b707c87929fabb0a6998c7f7266594c3f3025190e020000000000000000000c1926323f4b57636e737b80858a90949a99928e8984869297a2a49a93887f726d62594f453b3128221c140b020000000000000000000000000000000000000000040f19222b333c444c555c606d737e869297a09f92877c6f685d53493f352b20170d0200000000000000000000000000000d1a2733404c59646f7479797979797979726d6256453c31261a0e02000000000b17232e384855616b7079797979797979756f65594d4034271b0e0000000000000000000000000000000000000000020608080b0d0f11121213131312110f0d0a07060400000000000000000000000000000000000000000000000000000003101c28333e46525e696f7c8692979fa6a49f97918c888583828182828386898d92989ea5a69f9792867c6f695e52473d3320170d020000000013202d394653606c7986938d807d7d7d7d7d7d7d7d7d7d7d7d808d9386796c605346392d201300000000000000000b17222d38414f59626f7c879292877c6f62594f41382d22170b0000000000000000000b17222d38414f59616e7b86929fa9b3acb6b7b7b6acb3a99f92867b6e61594f41382d22170b00000005121f2b3744505b656c747f8b9292877e736d6d737e8792928b7f746c655b5044372b1f120500000b1825323e4b5865717e8b98a4aca295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000002101c27333d4754616d7a86929facab9e9184786c6053463a2f242d3946525e6875828f9ba9aca095897c6f63564c4135291d110400000000000000000000000000000000000000000000000915222f3b4854606b7784919eaba2988a7d70707d8a98a2a197897d7063554b4135291d110400000000000000000000000714202d3a4753606d7a86939faca79a8e8174675b4e412f23180c000000000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b6ac96897d7063564a3d3023170a00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000000000714202d3a4753606d7a85929faca3988a7d716464707d8a98a2a2988b7e7165574d42362a1e1205000000000000000000000b1724313e4a5764717d8a97a4b0a79a8d8174675a4e4134271b0e010000000c1926323f4c5965727f8c98a5afa295887c6f6255493c2f2216090000000000050c1925323f4c5865727f8b98a5aea194887b6e6155483b2e22171614100b050000000000000713202d3a4653606d798693a0aca4978a7e85929590847e77726f6d666b656c6e71767d859299a3aeac9f94887b6e6155483b2e221509000000000000000000000a17232f3b47525c63696e73797e83888d92989b95909298a2a99f93887f726d625b514c47433c332d261d140a00000000000000000000000000000000000000000a16212b343d454d565e676d757f8a9298a19e938b7f726a60564c41382d23190e050000000000000000000000000000000b1824303c48535d64676c6c6c6c6c6c6c65625b5146332a201509000000000006111c2c38444f5961636c6c6c6c6c6c6c68655d53483d3125180c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222a36424d57606a6f7c858f949ea1a8a19e999892908f8e8e8f9092999a9fa2a8a09e948f857c6f6a60564d42352c210e05000000000013202d394653606c7986938b7e7270707070707070707070727e8b9386796c605346392d201300000000000000030f1b27333f4953606b75828f99998f82756b6053493f33271d1207000000000000000006111b262f3d46535f6974808d97a2adbac3c4c4c3b9ada2978d8073695f53473d2f261b11060000000613202d394653606c77808c9192867d716c63636c717d8692918c80776c605346392d20130600000b1825323e4b5865717e8b989f9f9f95897c6f6256493c2f23160900000d1a2733404d5a6673808d999f9f9f9386796d6053463a2d201307000000000000000000000000000000000000000000000000000000000000000000000b16202d3946525d6875818e9ba7aca096897c7063554b4135292e3a4754616d7a86929facaa9d9084776b6054443a2f24190d010000000000000000000000000000000000000000000004101d2935404b55636f7c8996a0ab9f9285796d6d7985929fa99b8e8175675d5145392c20140900000000000000000000000815222f3b4855626e7b889aa4afa5998c7f7266594c3f3326190700000000000000000000000000000000000000000000000000000000000000091623303c4956636f7c8996a2afa4978b7e7164584b3e3125180b00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000000000000000005121e2a36424d5764717e8b98a2ac9f92867a6d60606d7985929faa9c8f8376695e53463a2d21160a000000000000000000000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e010000000c1825323f4b5865727e8b98a5afa295887c6f6255493c2f221609000000000810171c25323f4c5865727f8b98a5aea194887b6e6155483b2e262423201c17100800000000000713202d3a4653606d798693a0aca4978a7e7e8b9296918a837f7b79787778797b7e828a9297a2abafa49a8f8276695f53473a2d2114080000000000000000000007131f2a35404a52575e61666d71767c81869196a09d9fa2aaa6998c8075706b65605d55534e443f382f261c1106000000000000000000000000000000000000030f1b27323d464e575f686d79818c929fa3a0958e81756d62584e443a2f261b1108000000000000000000000000000000000814202b36414a53595b60606060606060595651493f3521180e03000000000000101c28333e474f5557606060606060605b59534b41372c2014080000000000000000000000000000000000000000000000000406070a0d0f11121313131212100e0c0906060300000000000000000000000000000000000000000000000000050e1a25303b454e58606a6f7b828b91969c9fa3aaa29f9d9c9b9b9c9d9fa3aba39f9b96918a827b6f6a60584e443b30231a0f00000000000013202d394653606c7986938b7e7265636363636363636365727e8b9386796c605346392d2013000000000000010c161f2b3744505b65707d89949e9e94897d70655b5044392e23180c0100000000000000000a141d2b37424d57606d7a85929fa8b2bdc8c8bdb2a89e92857a6d60574d42352b1d140a000000020f1b2835424e5b6875818d9292857c706b625a5a626b707c8592928d8175685b4e4235281b0f02000b1825323e4b5865717e8b9393939393897c6f6256493c2f2316110b0b101a2733404d5a6673808d939393939386796d6053463a2d2013070000000000000000000000000000000000000000000000000000000000000000000005111d2935414c56636f7c8995a0aca89b8e8174675d5145392c37434e5865727f8b99a3aea2988b7f7265594f4332281e130800000000000000000000000000000000000000000000000613202c3945515d6774818e9aa8aa9b8e8175676775818e9baa9f92867a6d6054473b31251a0e02000000000000000000000a1724303d4a5763707d8a96acb6a4978a7e7164574b3e3124180b000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8895a2afa5988b7e7265584b3f3225180c00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000000714212d3a46535f6976838f9caaaa9b8f8275675d5d6775828e9baa9f93877b6e6154483d32271b0f000000000000000000000b1825313e4b5864717e8b97a4b1a79a8d8074675a4d4134271a0e010000000b1825323e4b5865717e8b98a4afa295887c6f6255493c2f22160900000008121a22282d323f4c5865727f8b98a5aea194887b6e6155483b333331302d28221a1108000000000713202d3a4653606d798693a0aca4978b7e74818e949e95908c888685848585878b8f949fa2a9aea59f93877c6f62574d42372b1e120600000000000000000000020e19242e3840454d52545c60646a6f747b84919eaba39f9da09f9287827d77726d67625f58504a42382d22170b00000000000000000000000000000000000007131f2c38434e5860696e7a828e939ca4a2989183796d605b51463d32281d140a0000000000000000000000000000000000030f1a252f3841484c4e535353535353534c4a463f372d230f06000000000000000b16212c353e44484a535353535353534f4d4841392f251a0f0400000000000000000000000000000000000000000001070c10131416191c1d1f1f20201f1e1d1b191613120f0b0600000000000000000000000000000000000000000000000009141f29333d464e5860696e767e848a8f9299999b9d9e9f9f9f9f9e9d9b9999928f8a847e766e6960584e463d32291f110800000000000013202d394653606c7986938b7e7265585656565656565865727e8b9386796c605346392d201300000000000008131e2834404b54606c7883909da6a69d9083786c60544b4034281e13080000000000000000020b1a26313c45525d68727f8c96a0acb9c2c7b8aca0968b7f72685d52453b3123190b02000000000b1724313e4a5764717e869293877f746d665d5d666d747f879392867e7064574a3d3124170a00000b1825323e4b5865717e868686868686867c6f6256493c2f23221d16161b202733404d5a66738086868686868686786d6053463a2d20130700000000000000000000000000000000000000000000000000000000000000000000010d1924303a4854606b7783909daaac9f92857a6d6054473c313b4754606a7783909dabac9f92867a6d6054473d3221160c0100000000000000000000000000000000000000000000000714202d3a4753606d7a85929faca3988a7d716464707d8a98a2a2988b7e7165574d42362a1e1205000000000000000000000b1825313e4b5864717e8b97a4afa296897c6f6356493c30231609000000000000000000000000000000000000000000000000000000000000000815222f3b4855626e7b8895a1aea5988c7f7265594c3f3226190c00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000000030f1c28333f4a54616e7b87939faca2988a7e7164555564717e8a98a3a49a8c7f7366584e43372b1d12070000000000000000000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e010000000b1825323e4b5865717e8b98a4afa295887c6f6255493c2f221609000005101a242c33393c3f4c5865727f8b98a5aea194887b6e6155484040403d3c39332c231a10050000000713202d3a4653606d798693a0aca5988b7e7278828e939f9d999a939291919298979c9fa6adaba39f938d80736a6054453c31261a0e0200000000000000000000030e18212a31373e434b51575e666c727c849196a1a0999290959b99928f89847f7a746f6a605b544a3f33281c0f0300000000000000000000000000000000000915222e3b4854606a6f7b8490949ea5a49f92867c6e675d51493f342b20160b0200000000000000000000000000000000000008131d262f363c4041464646464646463f3e3a352d251b11000000000000000005101a232c33383c3d4646464646464642403d372f271e13090000000000000000000000000000000000000000040a0f12181c1f202326282a2b2c2c2c2c2b2a282523201f1c17110f0a03000000000000000000000000000000000000000000020d17212b343d464e565e616c71787e82868a8c8f90919292929291908e8c8986827d78716c615e574e463d342b20170d0000000000000013202d394653606c7986938b7e7265584b4a4a4a4a4b5865727e8b9386796c605346392d20130000000000010d19242f3845515c66717e8a959fabab9f958a7e71665c51453a2f24190d02000000000000000009141f2935414c56606d7984919ea6b0bebeb0a69e9184796d60564c41332a1f100700000000000a1623303c4955616c717d8692938c80786d67676d78808c9392867d706c6155493c3023160a00000b1724313d4a56626c71797979797979796f6a6054473b36332e272021272c2f303f4b58636e737979797979797976665c5044382c1f1206000000000000000000000000000000000000000000000000000000000000000000000008131e2c38434f5965727f8b98a2aea2988b7e7165574d4237404b55626f7c8895a0aca79b8e8174685d5245392c201304000000000000000000000000000000000000000000000005121e2a36424d5764717e8b98a2ac9f92867a6d60606d7985929faa9c8f8376695e53463a2d21160a000000000000000000000c1825323f4b5865727e8b98a5afa295887c6f6255493c2f221609000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8794a1aea6998c7f7366594c403326190d00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000006121f2b3844505b6673808c9aa4ac9f92867a6d605454606d7a86929fac9d9184776a605447392e23180c0000000000000000000b1724313e4a5764717d8a97a4b0a79a8d8174675a4e4134271b0e010000000c1825323f4b5865727e8b98a5afa295887c6f6255493c2f22160900000c17222c363e45494a4d5865727f8b98a5aea194887b6e61554d4d4d4d4a49443e362c22170b0000000713202d3a4653606d798693a0aca5988b7f726d78818b92989fa29f9e9e9e9fa3aaa9a9aaa29f99928b81786d60584e43332a1f1509000000000000000000000009151f2a333c42474f555c60696e787f879196a09f95918684898e92989b95918b85817c766c665b5044382b1f120600000000000000000000000000000000000916232f3c4956626f7c85919693939393928a7e716a5f554b40372d22190e0400000000000000000000000000000000000000010b141d252b3033343939393939393932312e29231b130900000000000000000008111a21282c2f30393939393939393534312c251e150c02000000000000000000000000000000000000040a0f161b1d23292c2d303335373839393939383635322f2d2b28221c1b150e09030000000000000000000000000000000000000000050f19222b343c444d525a61666d71757a7d80828385858686858483827f7d7a75716d66615a524d453d342b22190e050000000000000013202d394653606c7986938b7e7265584b3f3d3d3f4b5865727e8b9386796c605346392d2013000000000004111d2935414c56606d7984919ea7b1b1a79e9184796d60564c4135291f14090000000000000000030d1924303a44515c66707d8a949facb6b6ac9f948a7d70665c51443a3021180e0000000000000814212d3944505a616b707c8591928d82796e6e79828e9291857c706b615a5044392d20140800000915212e3a45505a62656c6c6c6c6c6c6c6260584e4344433f3932292b32383b3d4647525c63666c6c6c6c6c6c6c6c5c544a3f34281c10030000000000000000000000000000000000000000000000000000000000000000000000020f1b27323d4754606d7a86929facaa9c908376695f53473845515c6774808d9aa7aca095897c6f63564c4135291d110400000000000000000000000000000000000000000000000714212d3a46535f6976838f9caaaa9b8f8275675d5d6775828e9baa9f93877b6e6154483d32271b0f000000000000000000000c1926323f4c5965727f8c98a5aea195887b6e6255483b2f221508000000000000000000000000000000000000000000000000000000000000000714212e3a4754616d7a8794a0ada6998d8073665a4d4033271a0d00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000000000000000613202d394653606c7884919eaca99b8e8175675d51515d6775828f9caba096897c6f62544b4034281c100400000000000000000a1724303d4a5763707d8a96a3b0a89b8e8175685b4e4235281b07000000000c1926323f4c5965727f8c98a5afa295887c6f6255493c2f2216090005111c28333e48505557595965727f8b98a5aea194887b6e615959595959575550483e33281c100400000713202d3a4653606d798693a0aca5998c7f72666d757f868d92989a9c9e9e9f9f9e9d9c9998928d867f746d665c50463d3221180e0300000000000000000000020e1a26313c454d535961676d727b828c92999f99928d837c777c81868c91969c98928d8882786c605346392d20130600000000000000000000000000000000000d1a2633404d59667380868686868686868680746c61574e43392f251b1007000000000000000000000000000000000000000000020b131a202427282d2d2d2d2d2d2d2625221e18110901000000000000000000000810161c2023242d2d2d2d2d2d2d282725201a130c03000000000000000000000000000000000000060b151b21272c2f34383a3d40424445464646454543413f3c3938332d2b26201a150b060000000000000000000000000000000000000000071019222b323b424650545c6064676d70737577787979797878767573706d6764605c545046423b332b22191007000000000000000013202d394653606c7986938b7e7265584b3f3d3d3f4b5865727e8b9386796c605346392d201300000000040e18222c3945525d68727f8b96a0acb9b9aca0968b7f72685d52453b30251a0e04000000000000000008131e2834404a54616c7682909aa4afafa49a9082766c61544a4032281e0f0600000000000004101c28333e485059606a6f7b8490948f837a7a838f9490847b6f6a605950483e33281c1004000005111d29343f485056586060606060606056544e5353514f4a443b32353d44484953535352585a606060606060605f504a42382e23170c000000000000000000000000000000000000000000000000000000000000000000000000000a16202c3945515d6774818e9aa7ab9f94887b6e62544a3f4653606d7985929fabaa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000000030f1c28333f4a54616e7b87939faca2988a7e7164555564717e8a98a3a49a8c7f7366584e43372b1d12070000000000000000000d192633404c5966737f8c99a6aea194877b6e6154483b2e211508000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0ada79a8d8074675a4d4134271a0e00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000004111d2935414c5663707d8996a1aca1978a7d7063554b4b5564717e8b99a3a89a8d8174665c5145382c1f130800000000000000000916232f3c4956626f7c8995acb6a89c8f8275695c4f422e23180c000000000d1a2633404d596673808c99a6afa295887c6f6255493c2f221609000814212d3945505a6164666666727f8b98a5aea194887b6e66666666666664615a5044392d20140800000713202d3a4653606d798693a0aca6998c7f7366606d727b80858a8d8f9192929291908f8c8985807b726d605c544a3f342b200f06000000000000000000000006121e2b37424d575f616b70797f868f949f9d948f8780796f6a6f747a7f84898f93999a9486796d6053463a2d20130700000000000000000000000000000000000c1925323f4b57636d737979797979797979746e645a50453c31281d1209000000000000000000000000000000000000000000000001080f14181a1b20202020202020191816120d0700000000000000000000000000050b10141617202020202020201c1b18140f09020000000000000000000000000000000000020a111720262b323839404547494c4f50525253535251504e4c4946443f3837312b262017110a0200000000000000000000000000000000000000071019202930363e424a5053555d606366686a6b6c6c6c6c6b6a686663605d5553504a423e3630292119100700000000000000000013202d394653606c7986938b7e7265584b4a4a4a4a4b5865727e8b9386796c605346392d2013000000000a15202a36424d57606d7a85929ea8b2bdbdb2a89e92857a6d60574d42362a20150a0000000000000000020c18232e3942505a626f7c87939faaaa9f93877c6f625a5042392e20160c00000000000000000b17222c363e474f585f696e7a839094908484909490837a6e695f584f473e362c22170b000000010c18222d363f454a4b5353534c525f6060606060605d5b554d44393d474f54566060606060605a58535353535353443f3830261c11060000000000000000000000000000000000000000000000000000000000000000000000000004111d2935414c55626f7c88959faba6998d8073665c50444d5764717e8a97a2ada2988b7f7265594f4332281e1308000000000000000000000000000000000000000000000006121f2b3844505b6673808c9aa4ac9f92867a6d605454606d7a86929fac9d9184776a605447392e23180c0000000000000000000d1a2734404d5a6773808d9aa6ada094877a6d6154473a2e211407000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0ada79a8d8074675a4d4134271a0e00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000613202c3945525d6875818e9ba8ab9e9285796d6053464754616d7a86929fab9e9285796d6053463a3025190d01000000000000000815222e3b4855616e7b889aa4afa99d9083766a554b4034281c10040000010e1b2834414e5b6774818e9aa7afa295887c6f6255493c2f221609000a1723303c4955616c71737373737f8b98a5aea194887b73737373737373706c6155493c3023160a00000713202d3a4653606d798693a0aca6998d8073665b62686e74797d808284858685858482807d7a746e69625b504a42382e22190f0000000000000000000000000814212d3a47535f696e757d848c92989395908a827c736d676062686d72787d82878d929786796d6053463a2d20130700000000000000000000000000000000000a16232f3b47525b63666c6c6c6c6c6c6c6c67645c52483e332a1f160c000000000000000000000000000000000000000000000000000003080b0d0e131313131313130c0b090601000000000000000000000000000000000407090a131313131313130f0e0c0804000000000000000000000000000000000000040b141c222832373d43484b515356595b5d5e5f5f5f5f5e5d5b585653504a47433c373127221b140b0300000000000000000000000000000000000000070e171f252a30383f44464c515457595c5d5e5f5f5f5f5e5d5b595653514b46443f38302a251f170f070000000000000000000013202d394653606c7986938b7e7265585757575757575865727e8b9386796c605346392d2013000000020b1b26313a46525e6973808d97a1adbac4c4b9ada1978d8073695e52463c31261b0b02000000000000000007121c27303e4754606a75818e98a2a2988e81756a6054483e30271c0e04000000000000000005101a242c353d464e575f686e7a828f949191948f827a6e685f574e463d352c241a10050000000006111b242d343a3d3e46414c565e6c6c6c6c6c6c6c6a675f554a3f444f5960636c6c6c6c6c6c67645c534846464638342e261e150a0000000000000000000000000000000000000000000000000000000000000000000000000000010d19242f3a47545f6a7783909da9ab9e9184796d605346525e6976828f9ca9ac9f92867a6d6054473d3221160c0200000000000000000000000000000000000000000000000613202d394653606c7884919eaca99b8e8175675d51515d6775828f9caba096897c6f62544b4034281c100400000000000000000e1a2734414d5a6774808d9aa7ada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000714212e3a4754616d7a8794a0ada6998d8073665a4d4033271a0d00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000000000714212d3a4754606d7a86929faca89a8d8174665c514446525d6876828f9caba2978a7d7064564c4135291d1105000000000000000714202d3a4753606d7a86939facab9e918478675c5145382c1f1306000004111d2935414c566976828f9ca9afa295887c6f6255493c2f221609000b1724313e4a5764717e80808080828f9ca8b3a79a8d80808080808080807e7064574a3d3124170a00000713202d3a4653606d798693a0aca6998d8073665a565e61666d7073757778797978777673706d67615e5751443f3830261c10070000000000000000000000000815222e3b4855616e7b8286868686868686837d766f6a605c55565d61656c70757b80858a867a6d6053473a2d201407000000000000000000000000000000000007131e2a35404952575960606060606060605a58524a40362c21180d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161d262d333c43474f54555c606366686a6b6c6c6c6c6b69686562605b54534e47423c332d261d150d0300000000000000000000000000000000000000050d14191e262e34383a4145474a4d4f50525253535251504f4c4a4745403a38342e261e1a140d05000000000000000000000013202d394653606c7986938b7e7265646464646464646465727e8b9386796c605346392d20130000000a141d2b37434e58616e7b86929fa9b3becccabeb3a99f92867b6e61584e43372b1d140a0000000000000000000b151e2b37434e58616e7b86929f9f92867b6e61584e43362c1e150b0000000000000000000008121a232b343c454d565e686d79828e93938e82796d685e564d453c342b231a120800000000000009121b22292e31323946525e68767979797979797771675b4f434854606b70797979797979746e64584c4039392c28231c150c0300000000000000000000000000000000000000000000000000000000000000000000000000000008131e2b37434e5865717e8b97a2ada1968a7d7063564c54616e7b87939faca79b8e8174685d5245392c201304000000000000000000000000000000000000000000000004111d2935414c5663707d8996a1aca1978a7d7063554b4b5564717e8b99a3a89a8d8174665c5145382c1f130800000000000000000e1a2734414d5a6774808d9aa7ada093867a6d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8794a1aea6998c7f7366594c403326190d00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000000000006121f2b37434e5865727e8b98a2aca096897c6f63544a40414c5665727e8b99a4a99b8f8275685e5246392d2015090000000000000006131f2c3845515c677885919eabac9f9286796d6053463a2d20130600000713202c3945525d687884919eabafa295887c6f6255493c2f221609000f1c2835424f5b6875828c8c8c8c8f949eaab5a99d928d8c8c8c8c8c8c8c8174685b4e4135281b0e02000713202d3a4653606d798693a0aca6998d8073665a4d52545c606367696b6b6c6c6b6a696663605d55534d453f342e261e140a000000000000000000000000000814212d3a47535f696e757979797979797976706b625f58514b4c52535b6063696e73797e83796d6053473a2d2014070000000000000000000000000000000000020d19242e3740474b4d53535353535353534d4c4740382f241a0f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000010406070a0d10111213131211100d0a07060400000000030505060606060606000000000000000000000000000000000000030c161f282f383f444e54596063676d707375777879797978787674726f6c66625f58534d443f382f271f150d030000000000000000000000000000000000000002090c151c23282c2f35393a3d4042444546464645454342403d3a39352f2b28231c140c090200000000000000000000000013202d394653606c7986938b7e7270707070707070707070727e8b9386796c605346392d2013000006111b262f3847535f6a74818e98a2aebbb9b9b9b9baaea2988e81746a5f53473d2f261b11060000000000000000030c1b27323c46525e6973808d97978c8073695e52463c32241a0c030000000000000000000000081119222a333c444d565d676d78818d8d81786d675d564d443c332a2219110800000000000000000911181d21212e3b4754616e7a86868686868683776a5d5144495663707d8686868686868074675a4e4134271f1c17110a0300000000000000000000000000000000000000000000000000000000000000000000000000000000010f1b26323c4753606d7985929faba99b8e8275685d525966737f8c99a4aca095897c6f63564c4135291d110400000000000000000000000000000000000000000000000613202c3945525d6875818e9ba8ab9e9285796d6053464754616d7a86929fab9e9285796d6053463a3025190d01000000000000000d1a2734404d5a6773808d9aa6ada094877a6d6154473a2e211407000000000000000000000000000000000000000000000000000000000000000815222f3b4855626e7b8895a1aea5988c7f7265594c3f3226190c00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000000000814212e3a47535f6a7683909daaaa9e9184776b605442393b4754616e7b86939fac9f92867a6d6154473c31261a0e0000000000000004101c2934404b55697683909ca9afa399887b6f6255483c2e23170b00010714212d3a4754606d7a8796a1acafa295887c6f6255493c2f221609000f1c2835424f5b6875828e9999999c9ea6b0b9aea49d9a9999999999998e8174685b4e4135281b0e02000713202d3a4653606d798693a0aca6998d8073665a4d464b5153575a5c5e5f5f5f5e5d5c595654514b46423b3328231c140c020000000000000000000000000006121e2b37424d575f61696c6c6c6c6c6c6c6a636159534e45404146495053575e61666d71766d675d5145392c1f130600000000000000000000000000000000000007121c252e353b3f404646464646464646413f3c362f261d1208000000000000000000000000000000000000000000000000000000000000000000000000000000000001080d111314171a1d1e1f1f201f1e1c1a171413100c07010c0f11121313131313130909070300000000000000000000000000000b151e283139424a50585f626b6f75797d7f828385858686858483817f7c79746f6a625f575049413931271f150b010000000000000000000000000000000000000000030a11171c1f24292c2d30333537383939393938373533302d2c29241f1c17110a02000000000000000000000000000013202d394653606c7986938d807d7d7d7d7d7d7d7d7d7d7d7d808d9386796c605346392d201300000b17222d38414f59626f7c87939faab4acacacacacacb4aa9f93877c6f62594f41382d22170b0000000000000000000a15202a36424d57606d7a85919185796d60574d42342b20110800000000000000000000000000071019212a323b444c555d666d748080746d665d554c443b322a2118100700000000000000000000060c1114212e3b4754616e7a87939393939084776a5d5144495663707c89939393938d8174675a4e4134271b100c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2c3945515d6774808d9aa6ac9f92867a6d6154606b7784919eabaa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000000000714212d3a4754606d7a86929faca89a8d8174665c514446525d6876828f9caba2978a7d7064564c4135291d1105000000000000000d192633404c5966737f8c99a6aea194877b6e6154483b2e211508000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8895a2afa5988b7e7265584b3f3225180c00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000003101c28343f4a54626e7b88959faba7998c807366594f43303946525e687683909ca9a3998b7f7265574d42372b1b1106000000000000000c18232f414d5a6774808d9aa7b5ab988b7e7165544a3f34281c100b0e131c2834404a5464707d8a97a8b2afa295887c6f6255493c2f221609000f1c2835424f5b6875828e9b9f9fa0acaeb5bdb1a9a3a19f9f9f9f9f9b8e8174685b4e4135281b0e02000713202d3a4653606d798693a0aca6998d8073665a4d404045464a4d4f5152535252514f4d4a4745413a3631292117110a020000000000000000000000000000020e1a26313c454d53555c606060606060605d57554f47433c3435383f44464d53545c606469605d554b4035291d1004000000000000000000000000000000000000000a131c242a2f323339393939393939393433302b241d140b0000000000000000000000000000000000000000000000000000000000000000000000000000000003090e13191d20212427292b2b2c2c2c2b292724201f1c18120e181c1e1f2020202020201615130f0a04000000000000000000000007121d273039434b545b606a6f767c8185898c8e90919292929291908e8b8985817c756e69605b534b433931271d120700000000000000000000000000000000000000000000060c1013191d20212426292a2b2c2c2c2c2b2a282623201f1d1812100b060000000000000000000000000000000013202d394653606c798693928d8a8a8a8a8a8a8a8a8a8a8a8a8d929386796c605346392d201300030f1b27333f4953606b76828f99a49f9f9f9f9f9f9f9f9f9fa4998f82756b6053493f33271b0f030000000000000000040e1a25303b45515d67727e8b8b7e71675d51453b3022190f000000000000000000000000000000070f182029323a434b545c606e73736e605c544b433a322920180f07000000000000000000000000010814212e3b4754616e7a87949f9f9d9084776a5d5144495663707c89969f9f9a8d8174675a4e4134271b0e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101d2935404b55626f7b88949faba3998b7e726557636f7c8996a0aca2988b7f7265594f4332281e1308000000000000000000000000000000000000000000000006121f2b37434e5865727e8b98a2aca096897c6f63544a40414c5665727e8b99a4a99b8f8275685e5246392d201509000000000000000c1926323f4c5965727f8c98a5aea195887b6e6255483b2f22150800000000000000000000000000000000000000000000000000000000000000091623303c4956636f7c8996a2afa4978b7e7164584b3e3125180b00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000006121f2c3844505c6673808d9aa7ab9f95887b6e6255483d3236414d5665727f8c98a7ab9d908376695f5347382d22170b00000000000000071824313e4b5764717e8a97a7b1a79b8e8174665c5044382b221b171a1d242c3844515c6674818d9aa7b4afa295887c6f6255493c2f221609000f1c2835424f5b6875828e939393939fa3abb5a99f98949393939393938e8174685b4e4135281b0e02000713202d3a4653606d798693a0aca6998d8073665a4d4034383a3d404244454646454443403d3a39352f2a251f170f06000000000000000000000000000000000009151f2a333c4247484f53535353535353504a48443e373129292d33373b42464b5153575d53514b43392f24180c0000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d2726241f19130b02000000000000000000000000000000000000000000000000000000000000000000000000000000060e141a1e24292c2d3033363738393939383634302d2c29231d1a24282b2c2d2d2d2d2d2d23221f1b160f07000000000000000000040d18232e39434b555d666c737c83898e9298999b9d9e9f9f9f9f9e9c9b9897918d88827b736c655d554b43392f24180e05000000000000000000000000000000000000000000000003080d111314171a1c1d1f1f20201f1e1d1c19171413100c070300000000000000000000000000000000000013202d394653606c798693939393939393939393939393939393939386796c605346392d20130005121f2b3744505b65707d8994939393939393939393939393939394897d70655b5044372b1f120500000000000000000009141f2935414b55606d788383786d60554b4033291f100700000000000000000000000000000000060e1720283139424a505c636767635c504a4239312820170e0600000000000000000000000000000814212e3b4754616e7a8794a1aa9d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18242f3947535f6a7683909ca9ab9d908376695f6774818e9aa8ac9f92867a6d6054473d3221160c0200000000000000000000000000000000000000000000000814212e3a47535f6a7683909daaaa9e9184776b605442393b4754616e7b86939fac9f92867a6d6154473c31261a0e000000000000000c1825323f4b5865727e8b98a5afa295887c6f6255493c2f221609000000000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b6ac96897d7063564a3d3023170a00111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000000000713202d3a4653606d7985919eabab9d908377695f53473a2b303b4854616e7b8795a0ab9f95887b6e6253493f33271b0f030000000000000814212e3b4754616e7b8795a0acab9e9285796d6053463e342b2722262a2f35404b55606d7985929eabb8afa295887c6f6255493c2f221609000f1c2835424f5b68758186868686868b99a3aea3988d88868686868686868174685b4e4135281b0e02000713202d3a4653606d798693a0aca6998d8073665a4d40332c2d3034363838393938373633302d2c29241d1a140d05000000000000000000000000000000000000030e18212a31373a3b4246464646464646433d3c38332b26201b22272b3136394045464b504745403931271d120700000000000000000000000000000000000000000000070d1316191a20202020202020201a1a17130e0801000000000000000000000000000000000000000000000000000000000000000000000000000000070f181f262a2f35393a3d404344454646454443403d3a38342f2a252f3437383939393939392f2e2c272119100700000000000000010c161f2834404b555d676d78808790949b9fa2a9a29e9c9b9a9a9b9d9fa3a9a19e9a948f877f776d675d554b40352920170d02000000000000000000000000000000000000000000000000010406070a0d0f11121313131212100f0d0a07060400000000000000000000000000000000000000000013202d394653606c798686868686868686868686868686868686868686796c605346392d2013000613202d394653606c798386868686868686868686868686868686868683796c605346392d201306000000000000000000030d18242f3a44505c66707d7d70665c50433a2f21170d000000000000000000000000000000000000050d161f2730383f4452585a5a5852443f3830271f160d050000000000000000000000000000000814212e3b4754616e7a8794a1a99d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d2b37434e5864717e8a97a1ab9f95887b6e616d7985929faba79b8e8174685d5245392c201304000000000000000000000000000000000000000000000003101c28343f4a54626e7b88959faba7998c807366594f43303946525e687683909ca9a3998b7f7265574d42372b1b11060000000000000b1825313e4b5864717e8b97a4afa296897c6f6356493c30231609000000000000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c99a5afa49a887b6e6255483b2f22150800111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000005111d2a36414c5663707d8a97a1ada3998c7f7265574d42372b2d3a46535e697783909daaa7998d8073655b5044372b1f12070000000000000714202d3a46525e697784909dabada1978a7d70635a50463d37332d31363a4045515d67717e8b97a1adb9afa295887c6f6255493c2f221609000e1b2834414d59656f75797979797987929faca194887b79797979797979746f64594d4034271a0e01000713202d3a4653606d798693a0aca6998d8073665a4d403327202427292b2c2c2c2b2a29262321201d18130e09030000000000000000000000000000000000000000060f181f262b2d2e363939393939393937302f2c28211b1511171b1f252a2e34383a3e433a39352f271f150b01000000000000000000000000000000000000000000000002070a0c0d13131313131313130e0d0b0703000000000000000000000000000000000000000000000000000000000000000000000000000000030b1218212a31363a4145474a4d505152525352514f4d4a4745403936313a4044454646464646463c3b38322b22190f0400000000000008131e28313a45515c676d79828d92999fa6a39f9a97928f8e8d8e8e9092989b9fa3a69e99928c82796d675d51453f32291e140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013202d3946535f6c767979797979797979797979797979797979797979766c5f5346392d20130005121f2b3744505b656c77797979797979797979797979797979797979776c655b5044372b1f12050000000000000000000007131d28343f4a54606b70706b60544a3f31281d0f0500000000000000000000000000000000000000040d151e262e3440474b4d4d4b4740342e261e150d04000000000000000000000000000000000814212e3b4754616e7a87949c9c9c9084776a5d5144495663707c89969c9c9a8d8174675a4e4134271b0e01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1a26313c4653606d7985929eaca7998c7f7366717d8a98a2aca095897c6f63564c4135291d1104000000000000000000000000000000000000000000000006121f2c3844505c6673808d9aa7ab9f95887b6e6255483d3236414d5665727f8c98a7ab9d908376695f5347382d22170b0000000000000a1724303d4a5763707d8a96acb6a4978a7e7164574b3e3124180b000000000000000000000000000000000000000000000000000000000000010e1b2834414e5b6774818e9aa7ac9f9386796d6053463a2d20130700111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000713202d3946525e6875828f9ba9ac9f92867a6e6154473c31262a36424d5766737f8c99a7ab9e9184786c605346392f24180c00000000000005111e2a36424d5666737f8c99a3afa99c9083766c61584f46443f414142464b515b606d7984919ea9afb8afa295887c6f6255493c2f221609000c1925313d48535d65686c6c6c677683909da9a194887b6e6c6c6c6c6c6c68645d53483c3024180c00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a171a1c1e1f201f1f1e1c1a171413110d07010000000000000000000000000000000000000000000000060e151a1e2122292d2d2d2d2d2d2d2a2423201c160f0a060b0f141a1d23282c2d31362d2c29241d150d030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151c2328333b42464c5254575a5c5e5e5f5f5f5e5c5a5753514b46423b454c50525353535353534948433d342b21160a0000000000010d19242f3a43505a606d79828f949fa3a7a099928e898583818181828386898e92999fa7a39f948f82796d605b51443b3025190e0200000000000000000000000000000000000000000000000002070b0d0d131313131313130f0e0c0804000000000000000000000000000000000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e1200030f1b27333f49535b606a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a605b53493f33271b0f0300000000000000000000010b17232e38424f5960636360594f42382e1f160c000000000000000000000000000000000000000000030c151c2328363b3f40403f3b3628231c140c0300000000000000000000000000000000000814212e3b4754616e7a878f8f8f8f8f84776a5d5144495663707c898f8f8f8f8d8174675a4e4134271b0e01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2c3845515c6773808d9aa4aa9d9184776a75828e9baaaa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000000000713202d3a4653606d7985919eabab9d908377695f53473a2b303b4854616e7b8795a0ab9f95887b6e6253493f33271b0f0300000000000815222f3b4855626e7b889aa4afa5998c7f7266594c3f3326190700000000000000000000000000000000000000000000000000000000000004101d2935404b556976838f9ca9ab9e918478675c5145382c1f130600111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000000000714212e3a4754616d7a86929facaa9c8f8276685e5246392a2025313b4855626e7b8895a0aca196897d7063554b4035291d10040000000000020e1925303b4854616e7b87929fabab9f948a7e716a60595350494e4e4d53555d606d74808d969b9ea5afafa295887c6f6255493c2f221609000915202c37424b53595b6060606774808d9aa7a194887b6e6160606060605b59534b41372b20140800000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d0d0f111213131211100d0a07060401000000000000000000000000000000000000000000000000000003090e1214151c202020202020201d171614100b0500000003090e12181c1f20242a201f1d18120b03000000000000000000000000000000000000000000000000000000000000000000010406070a0d10111213131211100d0a07060400000000030505060606060606000000000000000000000000000000000b151e272e343f454d53565d606366696a6b6c6c6c6b696763605c55534d444f575c5f60606060606056544e463d32271b0f030000000004111d2935414c56616c74818e949ea6a69f959087817c79767474747577797d818790959ea5a69e948e81756d62564c41362a1e14080000000000000000000000000000000000000000000001080e1317191a202020202020201b1b18140f0901000000000000000000000000000000000000000000000f1b27333e49525a5f60606060606060606060606060606060606060605f5a52493e33271b0f00000b17222d38414950535d6060606060606060606060606060606060605d53504941382d22170b00000000000000000000000006111c26303d474f555656554f473d30261c0d0400000000000000000000000000000000000000000000030a1117242a2f323434322f2a2417110a020000000000000000000000000000000000000714212d3a4754606d7a8283838383838174675b4e414855626f7c8283838383827f7265584c3f3225190c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c2834404b55616e7b87939faca095887b6f7985929faca3988b7f7265594f4332281e1308000000000000000000000000000000000000000000000005111d2a36414c5663707d8a97a1ada3998c7f7265574d42372b2d3a46535e697783909daaa7998d8073655b5044372b1f120700000000000714202d3a4753606d7a86939faca79a8e8174675b4e412f24180c00000000000000000000000000000000000000000000000000000000000006131f2c3845515d677784919eaaa99c90837669554b4034281c100400111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000006131f2b37434e5865727f8b99a3aea2988b7e7164564c41362a18212e3a47535f6a7784919daaa89b8e8174675d5145392c1f14090000000000000914202d3a46525e6975818e99a3afa69f92857c706b62605b535a5b575f61676d747f8b92938f939eaaafa295887c6f6255493c2f22160900040f1b25303942484d4f53535764717e8a97a9a194887b6e6155535353534e4d4841392f251a0f0300000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d01030505060605040300000000000000000000000000000000000000000000000000000000000000000000020608080f13131313131313100a0907040000000000000000070c101313181d1413100c0701000000000000000000000000000000000000000000000000000000000000000001080d111314171a1d1e1f1f201f1e1c1a171413100c07010c0f111213131313131309090703000000000000000000000007121c273039404451575f61686d7073767778797978777673706d67615e57505761686b6c6c6c6c6c6c6260584e43382c1f1307000000000613202c3945525d68717e8a939da6a89f948f837c746f6c6668676768666d70757c838f939ea7a69e938b7f72685e52463b3025190d010000000000000000000000000000000000000000020a12191f2326272d2d2d2d2d2d2d282724201a130b030000000000000000000000000000000000000000000a16212c3740494f535353535353535353535353535353535353535353534f4940372c21160a000006111b262f383f4446505353535353535353535353535353535353535046443f382f261b1106000000000000000000000000000a141e2c353d44484a4a48443d352c1e140a00000000000000000000000000000000000000000000000000060c191f2326272726231f190b0600000000000000000000000000000000000000000713202c3945525d686d767676767676746f64584c4047535f6a6f767676767676726d62564a3e3125180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9a7998c7f737d8a98a2ac9f92867a6d6054473d3221160c0200000000000000000000000000000000000000000000000713202d3946525e6875828f9ba9ac9f92867a6e6154473c31262a36424d5766737f8c99a7ab9e9184786c605346392f24180c000000000006131f2c3845515d677885919eaba99c8f827669554b4035291d100400000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a86929faca79b8e8174685b4e412e23180c0000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000000000815222e3b47545f6a7783909dabac9f92867a6d6054473b3025191e2b37424e576673808c99a8ab9f9285796d6053473b3025190e02000000000005121e2a36424d57626e7c87929fa7ada29792857d756f6c6568676869696e7379818b91948f828f9ba8afa295887c6f6255493c2f221609000009141e2730373d4142464854616e7b8796a1a194887b6e61554846464641403c372f271d13090000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060606060606060400000000000000000000000000000406070b1007060400000000000000000000000000000000000000000000000000000000000000000003090e13191d20212427292b2b2c2c2c2b292724201f1c18120e181c1e1f2020202020201615130f0a040000000000000000000c18232e39424a515b63696e747a7d808384858586858482807d79746e69605b536873787979797979796f6a6054483b2e22150900000004111d2935414c55606d7a85929ea5aca0968f82796e6a62605b545a5b545c60636a6e78818f959faba59f92857a6e61564c41362a1e110500000000000000000000000000000000000000010a141c242b2f3334393939393939393534312c251d150b01000000000000000000000000000000000000000005101b252e373e4346464646464646464646464646464646464646464646433e372e251b10050000000a141d262d33373944464646464646464646464646464646464646443937332d261d140a0000000000000000000000000000020c1a232c33383c3d3d3c38332c231a0c020000000000000000000000000000000000000000000000000000080e1317191a1a1917130e0800000000000000000000000000000000000000000004111d2935414c565d6069696969696967645c53483c434e585f6269696969696965625b51463a2e22160900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d2b37424d5764717d8a97a1aa9d908377818e9baaa79b8e8174685d5245392c2013040000000000000000000000000000000000000000000000000714212e3a4754616d7a86929facaa9c8f8276685e5246392a2025313b4855626e7b8895a0aca196897d7063554b4035291d10040000000004101d2935404b55697683909ca9aa9e918477675d5145382c1f13060000000000000000000000000000000000000000000000000000000000091623303c4956636f7c8999a3afaa988b7e7265584b3f322518070000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000004101c2834404b55626f7c8895a0aca99b8e8175675d514539291e141a26313c4955626f7c8896a0aca2988a7e7164564d42362a1e11050000000000020e1a25303b47535f6a73808d95a0a8a9a1979288817c797674747476787b7f858d929790827d8996a3afa295897c6f6256493c2f2316090000020c151e252c3134353a46535e697884919ea194887b6e6155483b39393534302b251d150b010000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060e141a1e24292c2d3033363738393939383634302d2c29231d1a24282b2c2d2d2d2d2d2d23221f1b160f070000000000000004101c2834404a545c606d727b81868a8d8f9191929292918f8d8a85807b726c655c6b78858686868686867c6f6256493c2f2316090000000613202c3945515d6773808d97a1ada69e91847a6d675f5853504a4e4e4b5153585f666d79839099a3ada2978d8174685e5246392d2014090000000000000000000000000000000000000008121c262e363b3f404646464646464642403d372f271d130900000000000000000000000000000000000000000009131c252c33373939393939393939393939393939393939393939393937332c251c130900000000020b141b22272b2d37393939393939393939393939393939393939372d2b27221b140b0200000000000000000000000000000008111a21272c2f30302f2c27211a11080000000000000000000000000000000000000000000000000000000002070a0d0d0d0d0a070200000000000000000000000000000000000000000000010d1924303a444c52545c5c5c5c5c5c5b58534a41363c464e53555c5c5c5c5c5c585651493f34291e1206000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26313c4653606d7984919eaba095887b85929faba095897c6f63564c4135291d1104000000000000000000000000000000000000000000000006131f2b37434e5865727f8b99a3aea2988b7e7164564c41362a18212e3a47535f6a7784919daaa89b8e8174675d5145392c1f140900000000000c18242f414e5b6874818e9ba7ac9f92867a6d6053473a2d20140700000000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c99abaea298887b6f6255483c2f2215090000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000006131f2c3845515c6774808d9aa7ada1978a7d7063554b413529170d15212e3b47535f6a7784919eaaaa9c8f8276695e52463a2d20150a00000000000009141f2b37434e58606d79839096a0a8a9a19a938e8985828181818284888c91979992857b7c8996a2afa296897c6f6356493c30231609000000030c141b2025282a36424d576875828e9ba194887b6e6155483b2e2d282724201a130b03000000000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000406070a0d0f11121313131212100e0c090606030000000000000000000000000000000000000000000000000000000000070f181f262a2f35393a3d404344454646454443403d3a38342f2a252f3437383939393939392f2e2c27211910070000000000030e18212c3844515c666d757f878d9298999c9d9e9f9f9f9e9c9a98928d867f776d666679869293939393887b6e6255483b2f2215080000000714212d3a4754606d7a85929fa9aa9e94897d70685d554e46443f41414045464e545c676f7c87929faca99f92867a6e6154473c31261a0e020000000000000000000000000000000000020e19242e3840474c4d535353535353534e4d4841392f251a0f040000000000000000000000000000000000000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b27211b130a010000000000020a11171b1f202a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2a201f1b17110a020000000000000000000000000000000000080f161c2023232323201c160f08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131e28323a4145475050505050504e4c4841382f343c4347485050505050504c4a463f372d23180d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a4a79c8f828f97a2aa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000000000815222e3b47545f6a7783909dabac9f92867a6d6054473b3025191e2b37424e576673808c99a8ab9f9285796d6053473b3025190e0200000000071925323f4c5865727f8b98aaafa399897c6f6356493c302316090000000000000000000000000000000000000000000000000000000006121e2b37424d576875828f9ba8ab9f9285796c605346392d2013060000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000000000713202d3a4653606d7985929eabab9e9285796d6053463a2f241807131f2b37434e586773808d9aa8ac9f93877b6e6154473c32261b0f000000000000030f1a26313c45515c676e7b8491969fa4aca49f9b97928f8e8d8e8f9196999e9892877d707b8895a2aea396897c706356493d3023160a0000000002090f15191a25313f4c5965727f8c989f94887b6e6155483b2e221b1a18140f090100000000000713202d3a4653606d7986939f9f9f998d8073665a4d4033271a0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001070c10131416191c1d1f1f20201f1e1d1b191613120f0b0600000000000000000000000000000000000000000000000000030b1218212a31363a4145474a4d505152525352514f4d4a4745403936313a4044454646464646463c3b38322b22190f04000000000915202c38434f59606d78818c92999fa2aaa9a8aaa29f9e9e9e9fa29f98928c81786d6d798699a39f9f94877a6e6154473b2e211408000005111e2a36424d5765727f8b98a2aea99c8f82756b60564c433c38332d2e34383c424b555f6a74818e9ba8aea3988c7f7266574d42372b1e1205000000000000000000000000000000000007131f2b36404a52585a606060606060605b59534b41372c201408000000000000000000000000000000000000000000010910161b1e202020202020202020202020202020202020202020201e1b161009010000000000000000060b0f12131d2020202020202020202020202020202020201d13120f0b060000000000000000000000000000000000000000050b10141617171614100b050000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d090500000000000000000000000000020c1620283035393a43434343434341403c362f262a32373b3c4343434343433f3e3a342d251b1107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87939fac9e948f949ea9a3988b7f7265594f4332281e1308000000000000000000000000000000000000000000000004101c2834404b55626f7c8895a0aca99b8e8175675d514539291e141a26313c4955626f7c8896a0aca2988a7e7164564d42362a1e1105000000000916222f3c4955626f7c8898a2aeab988c7f7265594c3f31261a0e020000000000000000000000000000000000000000000000000000000814212d3a47535f697885919eaba99c8f8276665b5044382b1f12060000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000005111e2a36424d5664717d8a97a2ada89a8d8174665c514438281d13070f1b26323c4956626f7c8996a1ada4998c7f7265584e43372b1c11060000000000000a15202934404b555e696e7b848e939a9fa3aba9a19e9c9b9a9b9c9ea09d9590867d706e7b8894abb5a396897d7063564a3d3023170a0000000000000409091623303c4956636f7c89999393887b6e6155483b2e2215080c0803000000000000000713202d3a4653606d798693939393938d8073665a4d4033271a0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f12181c1f202326282a2b2c2c2c2c2b2a282523201f1c17110f0a03000000000000000000000000000000000000000000030c151c2328333b42464c5254575a5c5e5e5f5f5f5e5c5a5753514b46423b454c50525353535353534948433d342b21160a000000020e1a26313b4854606b74808d939fa3ababa49f9b979892919192939a989d9f938f82786d7a8794abb4a094877a6d6154473a2e21140700000714202d3a46525e697683909daaada196897d7063594f433a312b282223282c3039434e58626f7c8895a0acaa9d908477695f53463a2d21140700000000000000000000000000000000000b17232f3b47525c64676c6c6c6c6c6c6c68655d53483d3124180c0000000000000000000000000000000000000000000000050a0f1213131313131313131313131313131313131313131313120f0a0500000000000000000000000003050611131313131313131313131313131313131313110605030000000000000000000000000000000000000000000000000407090a0a0907040000000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1c1d20201c1c1915100a02000000000000000000000000040e161e24292c2d3636363636363433302b251d20262b2e2f36363636363632312e29231b1309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17232e3846535e6975828f9ca8a69e9c9ea6ac9f92867a6d6054473d3221160c02000000000000000000000000000000000000000000000006131f2c3845515c6774808d9aa7ada1978a7d7063554b413529170d15212e3b47535f6a7784919eaaaa9c8f8276695e52463a2d20150a000000000713202d3a4653606d7985929faca89b8f827568574d42362a1e12050000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8897a1ada8998c7f7366544a3f33281c0f030000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000714202d3a46525e6975828f9ca9aca096897c6f63544a403428160c010a13202d394653606c7884919eabab9d9084776a5f5347382e23170c000000000000030c18232f39434d575e696e7981878f92999b9d9e9f9f9f9e9d9b9895908b837c706b6d7a8799a49f9f978a7d7064574a3d3124170a00000000000000000713202d3a4653606d7987868686867b6e6155483b2e221508000000000000000000000713202d3a4653606d78868686868686868073665a4d4033271a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f161b1d23292c2d303335373839393939383635322f2d2b28221c1b150e0903000000000000000000000000000000000000000b151e272e343f454d53565d606366696a6b6c6c6c6b696763605c55534d444f575c5f60606060606056544e463d32271b0f03000006121e2b37424e57636f7c87939fa5afa9a199938f8a878584848586888c90959e948d80747b8794a1ada093877a6d6054473a2d21140700000814212e3b4754616e7b87959fabab9e9184786c6053463d31281f1c17181c1f27313c47535f6a7784919daaaca095887b6e6155483b2e22150600000000000000000000000000000000000d1926333f4c58646e7379797979797979756f65594d4034271b0e01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d151c2226292a2d2d292825211b140c04000000000000000000000000040c13191d2021292929292929282724201a13151b1f21222929292929292525221e181109010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040906111c2a36424d5763707d8a96a1acaaa8aab0a79b8e8174685d5245392c20130f0c07010000000000000000000000000000000000000000000713202d3a4653606d7985929eabab9e9285796d6053463a2f241807131f2b37434e586773808d9aa8ac9f93877b6e6154473c32261b0f0000000006121f2b3844505c6676838f9ca9ab9e918578695f53463a2d211409000000000000000000000000000000000000000000000000000005121e2a36424d5766727f8c99a9aca096887c6f6255493c2d22170b000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000000814212e3b4754616e7b86929facaa9e9184776b605442392e2318040005121f2b3744505b6574808d9aa9aca095887c6f62544a3f34281c100300000000000007121d27313b454d575e676d747c82868b8e909192929291908e8b88837e786f6a606c798693939393938a7e7164574b3e3124180b000000000000000006131f2c3845515c6775797979797976695f53463a2d2114070000000000000000000006121f2c3844505c667679797979797979736e63584b3f3226190c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b151b21272c2f34383a3d40424445464646454543413f3c3938332d2b26201a150b06000000000000000000000000000000000007121c273039404451575f61686d7073767778797978777673706d67615e57505761686b6c6c6c6c6c6c6260584e43382c1f130700000814212e3a47535f6a76828f9aa4afaba1979287827d7a79787778797b7f838a9196928a7e7b8895a1ada093867a6d6053473a2d20140700000b1824313e4b5764717e8a97a7b1a79a8e8174665b5044382b1f160f0b0c10151f2b37434e586773808d9aa6b1a7988b7e7165584b3e2d22170b00000000000000000000000000000000010d1a2734404d5a677380868686868686868175685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000000000060a0e1011131313131313100f0d0a0500000000000000000000000000000000000000000000000000000000060a0e1011131313131313100f0d0a05000000000000000000000000000005090d0f101313100f0d0a050000000000000000000000000000000000000000000000000000000000000000000000000000000000030d161f272d32353639393635322c261e160c0200000000000000000000000002080d1113141d1d1d1d1d1d1b1a18140f080a0f1215151d1d1d1d1d1d191816120d07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1d1a25313b4653606c7884919e9f9f9f9f9fa095897c6f63564c4135291d1e1c18130c050000000000000000000000000000000000000005111e2a36424d5664717d8a97a2ada89a8d8174665c514438281d13070f1b26323c4956626f7c8996a1ada4998c7f7265584e43372b1c110600000003101c28343f4a546673808c99a8ada197887b6e6155483b30251a0e02000000000000000000000000000000000000000000000000000714212d3a46535e697783909daaaa9e9184776a5f53473b2e1c1106000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c000000000000000000000007131f2c38434f5966727f8c99a3afa7998c807366594f4330271c120700030f1b27333f495363707c8997a1ada79a8d8074665c5044382c1f1206000000000000010b151f29333b454d555d606a6f757a7e8183858586858583817f7b77716d665f5b6678848686868686867f7265584c3f3225190c000000000000000004101c2834404b555c6a6c6c6c6c6c6c5f574d42372b1e12050000000000000000000003101c28343f4a545c6c6c6c6c6c6c6c6c66635c52473b2f23170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a111720262b323839404547494c4f50525253535251504e4c4946443f3837312b262017110a020000000000000000000000000000000c18232e39424a515b63696e747a7d808384858586858482807d79746e69605b536873787979797979796f6a6054483b2e22150900000815222f3b4855626e7b88949facaea39992857d75716e686b6b666d6e72767d84909492857d8996a3aca09386796d6053463a2d20130700010e1b2834414e5b6774818e9aa7b4aa978a7e7164544a3f3328190d040000040d1b26323d4a5764707d8a97aab4a79b8e81746853493f33271b0f03000000000000000000000000000000010d1a2734404d5a6773808d93939393938e8175685b4e4235281b0f020000000000000000000000000000000000000000000000000000000000040b11161a1d1e2020202020201d1c1916100a03000000000000000000000000000000000000000000000000040b11161a1d1e2020202020201d1c1916100a0300000000000000000000020a1015191c1c20201d1c1a16110a030000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2831383e4243464643413d3830281e140a0000000000000000000000000000010407071010101010100e0d0b08030000030608091010101010100c0b09060100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121a20262a2c2d2b3844505b66737f8c999393939393939084776b6054443a30242c2b28241e170f070000000000000000000000000000000000000714202d3a46525e6975828f9ca9aca096897c6f63544a403428160c010a13202d394653606c7884919eabab9d9084776a5f5347382e23170c000000000b17232e3c4956626f7c8996a0aca9988c7f7265574d42362a1e1205000000000000000000000000000000000000000000000000000815212e3b4854616e7b87959faba8998c807366584e43372b1f0a00000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000915222f3b4854606b7784919d9f9f9f95887b6e6255483d3222150b0000000b17222d3a4653606d7985929e9f9f9e9185796d6053463a2d20130700000000000000030d172129333b434b51586062686e71747678797978787675726e6a64605c5454687278797979797979726d62564a3e3124180b0000000000000000000c18232e39434b51535f6060606055534d453c31261a0e0200000000000000000000000c17232e38424a505f606060606060605a58524a40362a1f130700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b141c222832373d43484b515356595b5d5e5f5f5f5f5e5d5b585653504a47433c373127221b140b030000000000000000000000000004101c2834404a545c606d727b81868a8d8f9191929292918f8d8a85807b726c655c6b78858686868686867c6f6256493c2f23160900000d192633404c5966737f8c99a6b0ac9f92877c6f6b64615e56545c6062656c707a8290949083909daaaca09386796d6053463a2d2013070005111e2a36414c566a7683909da9aea298887b6e6155483b2d221708000000000a15212e3b4854616e7b8798a2aeaa9d908377655b5044372b1f1205000000000000000000000000000000010d1a2734404d5a6773808d9a9f9f9f9b8e8175685b4e4235281b0f0200000000000000000000000000000000000000000000000000000000050d151c2227292a2d2d2d2d2d2d292926211c150d0400000000000000000000000000000000000000000000050d151c2227292a2d2d2d2d2d2d292926211c150d040000000000000000040c141b212528292d2d2a2926221c150d040000000000000000000000000000000000000000000000000000000000000000000000000005111c27313a434a4e5053534f4e49423a30261b1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242b3236393939333f4a54616e7a8786868686868686867f7265594f433239393837342f2921190f0500000000000000000000000000000000000814212e3b4754616e7b86929facaa9e9184776b605442392e2318040005121f2b3744505b6574808d9aa9aca095887c6f62544a3f34281c10030000000615222e3b4754606a7784919eaaa99d908376695e52463a2d20150a00000000000000000000000000000000000000000000000006131f2b37434e5865727f8c98a7aca095887c6f6255483c32261b0f00000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0000000000000000000000091623303c4956636f7c8996939393939083776a5f53473a2e211417110b0b10121f2b3844505c6674818e93939393978a7d7063574a3d3024170a0000000000000000050f172129313a40454e54565e6164686a6b6c6c6c6b6a6865625f5753504a5660686b6c6c6c6c6c6c65625b51463a2e22160900000000000000000007121d27303940454653535353534846423c332a1f140900000000000000000000000006111c2630383f4453535353535353534d4b4740382e24190e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d161d262d333c43474f54555c606366686a6b6c6c6c6c6b69686562605b54534e47423c332d261d150d030000000000000000000000030e18212c3844515c666d757f878d9298999c9d9e9f9f9f9e9c9a98928d867f776d666679869293939393887b6e6255483b2f2215080005111e2a36424d576976838f9ca9b1a79a8d80736a605954524c4a5053555a61676d798290959095a0abaca09386796d6053463a2d201307000713202d3946525e687885929fabac9f9285796c605346392d201306000000000714212d3a46535e697985929facac9f9285796c605346392d201306000000000000000000000000000000010d1a2734404d5a6773808d9aa6aca89b8e8175685b4e4235281b0f02000000000000000000000000000000000000000000000000000000040d171f272e3336373939393939393635322d261f160d030000000000000000000000000000000000000000040d171f272e3336373939393939393635322d261f160d03000000000000020c161e262c32353639393635322d271f160d030000000000000000000000000000000000000000000000000000000000000000000000000a16222d38434c545a5d60605c5a544c42382c211509000000000000000000000000000000000000030608090b0d0f1112121313121211100e0c0a070604010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f1a242d363d42454646464646525e686e797979797979797979726d625647454646464544403a332b21170c0100000000000000000000000000000007131f2c38434f5966727f8c99a3afa7998c807366594f4330271c120706040f1b27333f495363707c8997a1ada79a8d8074665c5044382c1f120600000006131f2b37434e586673808d99a8ac9f93877b6e6154483c31261b0f0200000000000000000000000000000000000000000000020c15212e3b47535f6a7683909da9aa9d9184776a5f53473a2a20150a00000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000e1b2834414e5b677481868686868686867f7265574e42372b2a27221d16161b202228343f4a5463707d868686868686868175685b4f4235281c0f000000000000000000050f171f282f353d43474c5254585b5d5e5f5f5f5e5d5b5855534e46443f4e565c5e606060606060585651493f34291e1206000000000000000000000b151e272e34383a46464646463b3a37312a21180e03000000000000000000000000000a151e262e34384646464646464646403f3b362e261c1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c161f282f383f444e54596063676d707375777879797978787674726f6c66625f58534d443f382f271f150d03000000000000000000000915202c38434f59606d78818c92999fa2aaa9a8aaa29f9e9e9e9fa29f98928c81786d6d798699a39f9f94877a6e6154473b2e211408000714202d3a46525e697885929fabaca095877b6e61584f4746413f44464850555d676e7b85929da0a7b1aca09386796d6053463a2d201307000714212e3a4754616d7a8798a2aeaa9d918477665b5044382b1f12060000000005121e2a36424d576a7784919daaaea298877a6e6154473b2e211408000000000000000000000000000000010d1a2734404d5a6773808d9aa6aca89b8e8175685b4e4235281b0f020000000000000000000000000000000000000000000000000000000b151f2931393f424446464646464643423e3831281f150a00000000000000000000000000000000000000000b151f2931393f424446464646464643423e3831281f150a0000000000000a141e2830383d4143464643423e3831281f150a0000000000000000000000000000000000000000000000000000000000000000000000010d1a26323e4a545e66696c6c69665e54493d3225190d00000000000000000000000000000003070a0f121515181a1c1e1e1f1f201f1f1e1d1b19161413110d08040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915202b363f484e5253535353514d565e616c6c6c6c6c6c6c6c6c65625b514b5253535352504c453d33291e13070000000000000000000000000000000915222f3b4854606b7784919d9f9f9f95887b6e6255483d3222151b1313100c17222d3a4653606d7985929e9f9f9e9185796d6053463a2d201307000000030f1b27323d4955626f7c8896a0aca49a8b7f7265584e43372b1e13080000000000000000000000000000000000000000000008131e2a36414c56626f7c88959faba2988c7f7265584e43372b1f120600000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000d1a2733404c59646f7479797979797979726d6256453c313736332e272021272c2f302e384855616b7079797979797979756f65594d4034271b0e00000000000000000000050d161d242932373b4146474b4e505252535252504e4c4847423c3834454b50515353535353534c4a463f372d23180d0100000000000000000000030c151d23282c2d39393939392e2d2b261f180f060000000000000000000000000000030c151c23282c393939393939393933322f2a241c140a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151e283139424a50585f626b6f75797d7f828385858686858483817f7c79746f6a625f575049413931271f150b010000000000000000020e1a26313b4854606b74808d939fa3ababa49f9b979892919192939a989d9f938f82786d7a8794abb4a094877a6d6154473a2e211407000814212e3b4754616e7b8798a2aeaa9d908377695e53463d393634383a3e434c555e69717e8b97a1adb9aca09386796d6053463a2d201307000915222f3c4855626f7b8895aab4a99c8f837669544a3f33281c0f0300000000020e1a2531434f5c6976828f9ca9b4aa95887b6f6255483c2f221509000000000000000000000000000000010d1a2734404d5a6773808d9a9f9f9f9b8e8175685b4e4235281b0f02000000000000000000000000000000000000000000000000000006111c27313b434a4f51535353535353504e49423a31261c100500000000000000000000000000000000000006111c27313b434a4f51535353535353504e49423a31261c10050000000005101b26303a42494e4f5353504e4a433a31271c110500000000000000000000000000000000000000000000000000000000000000000000030f1c2935424e5a66707679797670665a4e4135281c0f00000000000000000000000000040a0f13151b1f21222527292a2b2c2c2d2c2b2b2a28262321201d1913100c07010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e1a26323d4851595e606060605e575552545f606060606060606058565053585f6060605f5c574f453a2f24180c000000000000000000000000000000091623303c4956636f7c8996939393939083776a5f53473a2e2d2d28201f1c18121f2b3844505c6674818e93939393978a7d7063574a3d3024170a000000000a15212e3b47535f6a7784919daaac9c9083766a5f53473a3025190d010000000000000000000000000000000000000000010d1924303946525e6874818e9aa7aa9f92857a6d6054473c31261b0f0300000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000b1824303c48535d64676c6c6c6c6c6c6c65625b5146464644433f3932292b32383b3d4646444f5961636c6c6c6c6c6c6c68655d53483d3125180c0000000000000000000000040c131820272b3036393b3e4143454646454543423f3b3a37312c283a4043454646464646463f3e3a342d251b1106000000000000000000000000030b12181c1f202c2d2d2d2d22211e1a140e0600000000000000000000000000000000030a11171c1f2d2d2d2d2d2d2d2d2726231f19120a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d273039434b545b606a6f767c8185898c8e90919292929291908e8b8985817c756e69605b534b433931271d1207000000000000000006121e2b37424e57636f7c87939fa5afa9a199938f8a878584848586888c90959e948d80747b8794a1ada093877a6d6054473a2d21140700091623303c4956636f7c8996aab4a79a8e817467574d42342d2a282b2d313a434d57606d7985929eabb8aca09386796d6053463a2d201307000a1723303d4a5663707d8996a3b0a89b8e8275685b4f422d22170b000000000000091c2835424f5b6875828e9ba8b0a396897d7063564a3d3023170a000000000000000000000000000000010d1a2734404d5a6773808d93939393938e8175685b4e4235281b0f0200000000000000000000000000000000000000000000000000000a16222e39434d555b5d6060606060605c5a544c42382d21160a0000000000000000000000000000000000000a16222e39434d555b5d6060606060605c5a544c42382d21160a000000000915212c38424c545a5c60605d5a544c43382d22160a0000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768286868276695c4f4336291c100000000000000000000000040b10161b1f22262b2e2f3233353738383939393837373532302d2c29241f1d18120b060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004111d2a36424e59636b6c6c6c6c6b64615a534d53535353535353534d535b60656c6c6c6c6b6861574c4034281c0f0300000000000000000000000000000e1b2834414e5b677481868686868686867f7265574e4237393939352d2c28231d1c28343f4a5463707d868686868686868175685b4f4235281c0f0000000006131f2b37434e5865727f8c98a2ab9f94887c6f62564c4135291e1308000000000000000000000000000000000000000005111d2935414c56616e7a86929faca3988d8074685d5245392a20150a0000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c00000000000000000000000814202b36414a53595b6060606060606059565153535353514f4a443b32353d444849535353534f5557606060606060605b59534b41372c20140800000000000000000000000001070d151b1e252a2d2e31353738393939383735322f2e2b261f282f34373839393939393932312e29231b1309000000000000000000000000000000070c10131320202020201514120e090300000000000000000000000000000000000000060c101220202020202020201a1917130e0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d18232e39434b555d666c737c83898e9298999b9d9e9f9f9f9f9e9c9b9897918d88827b736c655d554b43392f24180e05000000000000000814212e3a47535f6a76828f9aa4afaba1979287827d7a79787778797b7f838a9196928a7e7b8895a1ada093867a6d6053473a2d201407000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f31261e1c1f2028313b45515c6673808d99aab4aca09386796d6053463a2d201307000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b060000000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a000000000000000000000000000000010d1a2734404d5a677380868686868686868175685b4e4235281b0f0200000000000000000000000000000000000000000000000000010e1a27333f4a555f676a6c6c6c6c6c6c69665e54493e3226190d0100000000000000000000000000000000010e1a27333f4a555f676a6c6c6c6c6c6c69665e54493e3226190d010000000d1925323d49545e66696c6c69665e544a3e32261a0d0100000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000000000000000000060c161b21272c2f31373a3c3e4042444545464645454443413f3d3a39352f2c29241d17110a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006131f2c3945525e6b757979797978706c615f57514b434646424b51575f656c71787979797873685c5044372b1e110500000000000000000000000000000d1a2733404c59646f7479797979797979726d6256453c45464646413a38342e271e232e384855616b7079797979797979756f65594d4034271b0e00000000030f1b26323c4754606d7a86929faaa69a8d8174685e52463a2f24190d02000000000000000000000000000000000000040d1a232d3946525d6873808d98a3aa9f92867b6e61564c413529180e040000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326190c0807050200000000000000030f1a252f3841484c4e53535353534c525f6060606060605d5b554d44393d474f54566060606060605a585353535353534f4d4841392f251a0f040000000000000000000000000000040a0f14191e202125282a2b2c2c2c2b2a282522211e1a151d23272a2b2d2d2d2d2d2d2524221e1811090100000000000000000000000000000000000406071313131313080705020000000000000000000000000000000000000000000000030613131313131313130d0c0a070200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c161f2834404b555d676d78808790949b9fa2a9a29e9c9b9a9a9b9d9fa3a9a19e9a948f877f776d675d554b40352920170d020000000000000815222f3b4855626e7b88949facaea39992857d75716e686b6b666d6e72767d84909492857d8996a3aca09386796d6053463a2d201307000b1824313e4b5764717e8a97a4b0a4978a7d7164574a3e3124171012161f2834404b54626f7c8998a3aeaca09386796d6053463a2d201307000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b0a4978a7d7164574a3e3124170b000000000000000000000000000000000d1926333f4c58646e7379797979797979756f65594d4034271b0e010000000000000000000000000000000000000000000000000003101d2936424f5b6771777979797979797670665a4e4235291c0f030000000000000000000000000000000003101d2936424f5b6771777979797979797670665a4e4235291c0f030000000f1c2835414e5a66707679797670665a4e4235291c0f0300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000000000000030a111721272c32383b3c4347484b4d4f5151525253525251504e4c494745413a39352f28221c140b06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202d394653606c7987868686847d756e69605c554f46454f545c60696e777e8586868685786b5f5245382c1f120500000000000000000000000000000b1824303c48535d64676c6c6c6c6c6c6c65625b514c50525353534e464540393029202c38444f5961636c6c6c6c6c6c6c68655d53483d3125180c00000000000a15202c3945525d6874808d98a3ac9f92867a6d61564c4135291f14090000000000000000000000000000000000010c161f2a36424d57616d7a85929faaa2988d8074695e52433a2f241906000000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f332619191514120e090300000000000008131d262f363c4041464646414c565e6c6c6c6c6c6c6c6a675f554a3f444f5960636c6c6c6c6c6c67645c534846464642403d372f271e1309000000000000000000000000000000000002080e111414181b1d1f1f201f1f1d1b191514120e0912171b1e1e202020202020191816120d060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008131e28313a45515c676d79828d92999fa6a39f9a97928f8e8d8e8e9092989b9fa3a69e99928c82796d675d51453f32291e14080000000000000d192633404c5966737f8c99a6b0ac9f92877c6f6b64615e56545c6062656c707a8290949083909daaaca09386796d6053463a2d201307000b1825313e4b5864717e8b97a4b0a396897d7063564a3d3023170a060d18232e3a4653606d7986929facaca09386796d6053463a2d201307000b1825313e4b5864717e8b97a4b1a79a8d8074675a4d4134271a0e0100000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b000000000000000000000000000000000b17232f3b47525c64676c6c6c6c6c6c6c68655d53483d3124180c000000000000000000000000000000000000000000000000000004111e2a3744515d6a77838686868686868276695c504336291d10030000000000000000000000000000000004111e2a3744515d6a77838686868686868276695c504336291d1003000000101c2936434f5c69768286868276695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000000000000030c151c232832383d4348494e5355585a5c5d5e5f5f605f5e5e5d5b595654514c47454039332d261d181008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e889396918a827b736d67615953525960666d737b828b929792877e7064574a3d3124170a0000000000000000000000000000000814202b36414a53595b606060606060605956514f575d5f6060605b53514b423a322a28333e474f5557606060606060605b59534b41372c201408000000000004111d2935414c56616e7b86929faaa2988c8073685d52453b30251a0d030000000000000000000000000000000007121d28313946535e6973808d98a2a89f92857a6d61564d4231281e1308000000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3326252522211e1a140e060000000000010b141d252b30333439393946525e68767979797979797771675b4f434854606b70797979797979746e64584c4039393534312c251e150c0200000000000000000000000000000000000000020507080b0e101213131212100f0c0808060200070b0f11121313131313130c0b09060100000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a0500000000000000000000000000000000000000000000000000000000000000000000020608080b0e1011121313121211100d0b080705020000000000000000000000000000000000000000000000010d19242f3a43505a606d79828f949fa3a7a099928e898583818181828386898e92999fa7a39f948f82796d605b51443b3025190e020000000005111e2a36424d576976838f9ca9b1a79a8d80736a605954524c4a5053555a61676d798290959095a0abaca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa296897c6f6356493c302316090007131f2c3845515c667683909da9aca09386796d6053463a2d201307000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b0000000000000000000000000000000007131f2b36404a52585a606060606060605b59534b41372c201408000000000000000000000000000000000000000000000000000004111e2a3744515d6a778490939393938f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a778490939393938f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000000000000030d151e262e343d44484f5456585f626566686a6b6b6c6c6c6b6a6a686563605d5553514b443f382f2a221a11080000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724303d4956626c717f8b919e948f868079706b615f5d606b6f797f868f949f93887e716c6155493c3023160a000000000000000000000000000000030f1a252f3841484c4e535353535353534c4a4c5761696b6c6c6c68605c544c443c342c2c353e44484a535353535353534f4d4841392f251a0f040000000000010d19242f3a46525e6974808d98a2aa9f92857a6d60574d42362a1f150b010000000000000000000000000000050e18242f39434f59616e7b86929faaa0968c7f72685e52443b301f160c01000000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f333232322e2d2a261f180f060000000000020b131a202427282d2e3b4754616e7a86868686868683776a5d5144495663707d8686868686868074675a4e41342d282725201a130c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a0300000000000000000000000000000000000000000000000000000000000205090e121415181b1d1e1f20201f1f1e1c1a181514120e090502000000000000000000000000000000000000000004111d2935414c56616c74818e949ea6a69f959087817c79767474747577797d818790959ea5a69e948e81756d62564c41362a1e1408000000000714202d3a46525e697885929fabaca095877b6e61584f4746413f44464850555d676e7b85929da0a7b1aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090004101c2834404b546875828f9ba8aca09386796d6053463a2d201307000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b0e0100000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a00000000000000000000000000000000020e19242e3840474c4d535353535353534e4d4841392f251a0f04000000000000000000000000000000000000000000000000000004111e2a3744515d6a7784909d9f9f9c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909d9f9f9c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000000020b151f2730383f444f54596063676a6f7173757778787979787877767472706d6764605d55504a423c342c231a100700000000000000000000000000000000000000000000000000000000000000000000000000000000000815212d3945505a626d727f8b919c98928c847d756e69686d747c838c92989c918b7f726c625a5044392d2014080000000000000000000000000000000008131d262f363c4041464646464646463f44505d697378797979746d665e564e463e35282c33383c3d4646464646464642403d372f271e13090000000000000008131e2a36424d57616d7a85929fa8a2978d8073695e52463d31271d120700000000000000000000000000020b17202935404b55606b75828f98a3a59d9184796d60564c4132291f0d0400000000000000111e2b3744515e6a7784919daaa5998c7f7266594c3f3f3f3f3f3b3a36312a21180e03000000000001080f14181a1b212e3b4754616e7a87939393939084776a5d5144495663707c89939393938d8174675a4e4134271c1b18140f090200000000000000000000000000000000000000000000020507080b0e111112131312110f0c0908060300000000000000000406070b0f1213131211100e0c0b09060100000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d04000000000000000000000000000000000000000000000000000002080e11151a1e21222528292b2c2c2c2c2b2b29272522211e1a14120e09020000000000000000000000000000000000000613202c3945525d68717e8a939da6a89f948f837c746f6c6668676768666d70757c838f939ea7a69e938b7f72685e52463b3025190d010000000814212e3b4754616e7b8798a2aeaa9d908377695e53463d393634383a3e434c555e69717e8b97a1adb9aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000c18232e414e5b6874818e9ba7aca09386796d6053463a2d201307000a1723303d4a5663707d8996a3b0a89b8e8175685b4e4235281b090000000000020f1b2835424e5b6875818e9ba8b0a3968a7d7063574a3d3024170a00000000000000000000000000000000020e1a26313c454e53556060606060606055534e463c31261b0f03000000000000000000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000000000a141d273139424a505960636b6f74787b7e8082848485858685858483817f7c7a75716d67605b544e463e352c23190d040000000000000000000000000000000000000000000000000000000000000000000000000000000005111d29343e48505a626d727f8c929c9f96918a827b73717a818891959f9d928c7f736d625a50483e33281c100400000000000000000000000000000000010b141d252b303334393939393939393845525f6b788586868681786d685f584f473f342e272c2f30393939393939393534312c251e150c0200000000000000010e1a25303b46525e68727f8c96a0a99f92867b6e61594f43392f24180e040000000000000000000000000a141d29323a45515d67707d89939ea89d93897d70675c51443a3020170d0000000000000000111e2b3744515e6a7784919daaa5998c7f7266594c4c4c4c4c4c4846423b332a1f14090000000000000003080b0814212e3b4754616e7a87949f9f9d9084776a5d5144495663707c89969f9f9a8d8174675a4e4134271b0e0c08040000000000000000000000000000000000000000000003090e121415181b1d1e1f201f1f1d1b191515120f0a0401000000070c101313181c1e1f201f1e1d1b181815120d060000000000000000000000000000030d161f272d32353639393635322d271f160d03000000000000000000000000000000000000000000000002080d14191e20262b2e2f323436383939393938373634322e2d2b26201e1a140e090200000000000000000000000000000004111d2935414c55606d7a85929ea5aca0968f82796e6a62605b545a5b545c60636a6e78818f959faba59f92857a6e61564c41362a1e1105000000091623303c4956636f7c8996aab4a79a8e817467574d42342d2a282b2d313a434d57606d7985929eabb8aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090000071a2734404d5a6773808d9aa6aca09386796d6053463a2d201307000916222f3c4955626f7c8895aab4a99c8f8276695c4f4330251a0e0200000000030f1c2936424f5c6975828f9ca8b5ab95897c6f6256493c2f2316090000000000000000000000000000000006121e2b37424e575f6c6c6c6c6c6c6c6c625f584e43372b1f1206000000000000000000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000006111b262f39434b545c606b70767c8184888b8d8f9091929293929191908e8c8986827e79716c665f584f473e352b1f160c01000000000000000000000000000000000000000000000000000000000000000000000000000000000c17222d363f48515b636d737f8c929ca09e948f867f7d848d939aa09d938d80736d635b51483e362c22170b000000000000000000000000000000000000020b131a202427282d2d2d2d2d2d2d323f4c5965727f8c93938e827a6f6a615951444039302823242d2d2d2d2d2d2d282725201a130c0300000000000000000009141f2a36414c56606d7984919da5a2988e81756b60554b40352920160b020000000000000000000006111c262f3a444f59606d7984919ea5a1968e81746b60554b4032291e0e050000000000000000111e2b3744515e6a7784919daaa5998c7f72665958585858585855534d453b31261a0e020000000000000000000814212e3b4754616e7a8794a1aa9d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000040a0f141a1e212125282a2b2c2c2c2b2a282622211f1b15110d08030b12181c1f2025292b2c2c2c2b2a272524221d181109010000000000000000000000000a151f2831383e4243464643423e3831281f150a00000000000000000000000000000000000000000000040c13191f252a2d31373a3b3e41434445464645454443403e3b3a37312d2a251f1a140d0500000000000000000000000000000613202c3945515d6773808d97a1ada69e91847a6d675f5853504a4e4e4b5153585f666d79839099a3ada2978d8174685e5246392d2014090000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f31261e1c1f2028313b45515c6673808d99aab4aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000814212e3b4754616e7b8798a3aeaa9d9084776a574d42362a1e12050000000005111d2935414c566a7783909daaafa399877b6e6154483b2e211508000000000000000000000000000000000814212e3a47535f6a7679797979797979766a5f53473a2e211508000000000000000000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000000000b17222d38414b555c666d737d82898e919698999b9d9e9e9f9f9f9e9d9d9b9898928f8a857e786f6a61594f473d31281e13080000000000000000000000000000000000000000000000000000000000000000000000000000000006101b242d363f49515b636d73808d929da49e98928c8a91969fa49e938e81746e645b51493f362d241a10050000000000000000000000000000000000000001080f14181a1b20202020202025313e4a56626d75818f969490847c706b625b514a423a322a21192020202020201c1b18140f090200000000000000000000020d1925303a45515c67707d89939da89e93897d70675d51453d32281d140a000000000000000000071017222d38424c56606b74808d96a0a3999184796d60594f43392e20170d000000000000000000111e2b3744515e6a7784919daaa5998c7f726665656565656565615f574d42362a1e12050000000000000000000814212e3b4754616e7a8794a1a99d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e01000000000000000000000000000000000000000000060c161b1f252a2d2e31343738393939383735322f2e2b26201d19130c151d23282c2d32353839393838363432312e29231b1309000000000000000000000005111c27313a434a4e505353504e4a433a31271c11050000000000000000000000000000000000000000080e161e25293036393c4247484b4e50515253535252514f4d4b4846423c3a36302a251f170f08000000000000000000000000000714212d3a4754606d7a85929fa9aa9e94897d70685d554e46443f41414045464e545c676f7c87929faca99f92867a6e6154473c31261a0e0200000b1824313e4b5764717e8a97a4b0a4978a7d7164574a3e3124171012161f2834404b54626f7c8998a3aeaca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000713202d3a4653606d7986929facab9f928578695e52463a2d201407000000000713202d3946525d687885929eabac9f9286796d6053463a2d201307000000000000000000000000000000000815222f3b4855626e7b868686868686867c6f6255483c2f22140a000000000000000000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000000030f1b27333f49535c676d7880888f949a9ea1a8a6a9a19e9d9d9c9d9d9ea1a9aaa39f9b97918b837c706b61594f433a2f24190d010000000000000000000000000000000000000000000000000000000000000000000000000000000009121b242d373f49525b636e74808d929da5a39f99979ea1a69e948e81786c605c524940372d241b11080000000000000000000000000000000000000000000003080b0d0e131313131316222e3a46515b606d7a8491989691867d726d605c544c443c332b2317110a1313130f0e0c08040000000000000000000000000008131e2834404b55606b74818e96a1a59d9184796d60594f443a2f261b110600000000000000060f192228333f4a545e68707d88939fa69f92877d6f675d51473d30271d0e05000000000000000000111e2b3744515e6a7784919daaa5998c7f7272727272727272726e695f53463a2d2114070000000000000000000814212e3b4754616e7a87949c9c9c9084776a5d5144495663707c89969c9c9a8d8174675a4e4134271b0e0100000000000000000000000000000000000000030a111720272b31363a3b3e4144444546464544423f3c3b37322c29241e191e272e34383a3e42454646454443413f3d3a342d251b1106000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a000000000000000000000000000000000000020a121a202830353b4146474e5355585b5c5e5f5f5f5f5e5e5c5a5855534d4846423b363029211a120a020000000000000000000005111e2a36424d5765727f8b98a2aea99c8f82756b60564c433c38332d2e34383c424b555f6a74818e9ba8aea3988c7f7266574d42372b1e120500000b1825313e4b5864717e8b97a4b0a396897d7063564a3d3023170a060d18232e3a4653606d7986929facaca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070006121f2b3844505c667784909daaaea298877b6e6154483b2e21150a000000000714212e3a4754616d7a8797a1adaa9e918477665c5145382c1f1306000000000000000000000000000000000714212d3a4754606d7a879893939393897d7063564a3d2f261b11060000000000000000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000005121f2b3744505b656d79828d939a9fa6a7a09d999697929090909090929795999da0a7a19e9590867d706b60564c4135291d1307000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b252d374049525c646e74808d939da59f9f9f9fa79f948f82786d665b504a40372e251b1209000000000000000000000000000000000000000000000000000001010606060606121e29353f45525d686f7c86929f9892877f746d665d564d453d3528231c140c0300020100000000000000000000000000000000020c18232e39434f59606d79849199a3a0968d80736b60564c41382d221710070000000000030d18212b343d44505b666d7a85919aa49e948c7f726b60554b41352b1e150b00000000000000000000111e2b3744515e6a7784919daaa89b8f817f7f7f7f7f7f7f7f7f7b6e6155483b2e2215080000000000000000000814212e3b4754616e7a878f8f8f8f8f84776a5d5144495663707c898f8f8f8f8d8174675a4e4134271b0e01000000000000000000000000000000000000030c151c232832373b4246484b4e505152535252504e4c4847433c39352f28222b30394045464b4f5152535251504e4b4a463f372d23180d010000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d0100000000000000000000000000000000020b141c242c323a41464d5254575f626567696b6c6c6c6c6b6a696765615f5754524d46423b332c241c140a020000000000000000000714202d3a46525e697683909daaada196897d7063594f433a312b282223282c3039434e58626f7c8895a0acaa9d908477695f53463a2d21140700000b1825323e4b5865717e8b98a4afa296897c6f6356493c302316090007131f2c3845515c667683909da9aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070003101c28343f4a546875818e9ba8b3aa978a7d7064574a3d32271b0d04000001081623303d495663707c8996a9b3a89c8f827569544b4034281c1004000000000000000000000000000000000613202c3945525d687985929f9f9f998c7f7366584e41382d2217110a02000000000000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000005111e2a36414c56606c77818e949fa4a7a09d95908c89878584838383848587898c90959ea1a7a09892867d6f685d52453a2f24180d01000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252e37404a525c606c77818e93939393939393959082796d665c544a3f382e251c1309000000000000000000000000000000000000000000000000000000000000000000010d18232935414c565f6a727e8b939e99938c81786d685f574f473f342e261e150c030000000000000000000000000000000000000007121d27303d45515d676f7d87929fa69f93877d6f685e53493f332722190f060000000009141f29333d46505a606c78828f97a1a0958f82776c60594f433a2f23190c0300000000000000000000111e2b3744515e6a7784919daaaa9e938f8b8b8b8b8b8b8b8b8a7d7164574a3e3124170b0000000000000000000714212d3a4754606d7a8283838383838174675b4e414855626f7c8283838383827f7265584c3f3225190c000000000000000000000000000000000000030d151e262e343d43474d5354585b5d5e5f5f5f5e5d5b5955534e4745413a3129343c424b5153585c5e5f5f5f5e5d5a585651493f34291d12060000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f03000000000000000000000000000000010b141d262e363e444c52565e61666a6e717476777879797878777673716e6966615e57524d453e362e261c140a0000000000000000000814212e3b4754616e7b87959fabab9e9184786c6053463d31281f1c17181c1f27313c47535f6a7784919daaaca095887b6e6155483b2e22150600000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090004101c2834404b546875828f9ba8aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000b17232e3f4b5865727e8b98a8b2a69a8d807367584e43372b1f15100c090e131e2a36414c5666727f8c99a5b3aa998c7f7366594c402e23180c000000000000000000000000000000000004111d2935414c566976838f9caca99d9083766a6053493f3327221b140b040000000000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000713202d3946525e68727f8c939ea6a59d959089837f7c7a787776767677787a7c7f838a9297a1a9a29891847a6d60554b4135291d11040000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c252e384044505b656c7881868686868686868683796d675d544a42382d261c130a0100000000000000000000000000000000000000000000000000000000000000000000070d19242f3a434e58626d75818e95a09f928e827a6e69605951443f3830271e150b00000000000000000000000000000000000000000b151e2935414b55606b727f8c949ea49991847a6d655b50443e342b21180d030000020e1a26313b454e58616c73808d949ea19791837a6d655b50473d31281d11070000000000000000000000111e2b3744515e6a7784919daab0a69e9b98989898989898978a7d7164574a3e3124170b0000000000000000000713202c3945525d686d767676767676746f64584c4047535f6a6f767676767676726d62564a3e3125180b0000000000000000000000000000000000010b151f2730383f444e54575e6164676a6b6c6c6c6b6a6865625f5854524c433f353c464e545c6065686b6c6c6b6b696765625b51463a2e221509000000000000000003101d2a3643505d69768286868276695d5043362a1d100300000000000000000000000000000009131d262f38404850565e61686e73777b7e81838485868685858482807e7b77736e69615e57504840382e261c130900000000000000000b1824313e4b5764717e8a97a7b1a79a8e8174665b5044382b1f160f0b0c10151f2b37434e586773808d9aa6b1a7988b7e7165584b3e2d22170b00000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000c18232e414e5b6874818e9ba7aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000615222f3c4855626f7b8896a0acaa9d9184776a6054473c31271f1c181b1a1e242d3946525e6876838f9ca9aea298897c706356493d302316070000000000000000000000000000000000010d19242f3f4c5966727f8c9aa4ab9f95897c6f655b50443e332d261d160e0600000000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100004101c2834404a54616d7a85929fa5a69d938e837d77736f6d686a6a696a6a676d6f73787e859196a1aaa1968d8073675d5145392c201306000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a131c2627333f49535b666c757979797979797979776d675d554b42392f261c140a0100000000000000000000000000000000000000000000000000000000000000000000000008131e28313c46515b606d79839198a29d948f847b706b625b504a423930271d120700000000000000000000000000000000000000030c18242f3a434f59606c77828f95a0a1968f82776c605a50463d33291f1409000005121e2a36424d57606a717e8a929ca29892857b6e685d53493f352b1f160c000000000000000000000000111e2b3744515e6a7784919d9f9f9f9f9f9f9f9f9f9f9f9f978a7d7164574a3e3124170b00000000000000000004111d2935414c565d6069696969696967645c53483c434e585f6269696969696965625b51463a2e221609000000000000000000000000000000000007121d273139424a50586062696e71747777787979787775726f6a66605d56504540454e5860666d717578797978777674726d62564a3d3124180b000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000007101b252f38404a525a61686d747b8084888b8e8f919292929291918f8d8b8884807b746e69615a524a40382e251b0f06000000000000010e1b2834414e5b6774818e9aa7b4aa978a7e7164544a3f3328190d040000040d1b26323d4a5764707d8a97aab4a79b8e81746853493f33271b0f03000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090000071a2734404d5a6773808d9aa6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000815212e3a47535f6a7784919eabaca095887c6f62584e4339312c282327262b2f35414c56616d7a86929facab9f9285796d6053463a2d2013070000000000000000000000000000000000000815222f3b4855626e7b87939faba79c9082776c605a50443f382f282017110a020000000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100006121f2c3844515c6674808d98a2aa9e948e8179706b6663605d565d5d5d555d6062656c717b84919ea8a99f92857a6d6054473a2d21140700000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a1417222d38414a545b60686c6c6c6c6c6c6c6c6a605d554c433930271d140a0200000000000000000000000000000000000000000000000000000000000000000000000000010c161f2a343f45515d676e7c86929fa59f9691857d726d605c544b42392e23180c000000000000000000000000000000000000000007131d28313d44505b656d7a839197a19e948c80736c61584e453b31261a0e02000714212d3a46535f696f7c869293939992867c6f695f564c41382d23190d04000000000000000000000000111e2b3744515e6a77849193939393939393939393939393938a7d7164574a3e3124170b000000000000000000010d1924303a444c52545c5c5c5c5c5c5b58534a41363c464e53555c5c5c5c5c5c585651493f34291e120600000000000000000000000000000000020c18242f39434b545c606a6f757b7e8183848586858583817f7c78726d68625a514b4d57606a6f797e82848586858483817f7265584b3f3225180c000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000030c19222d37404a525c636c717a81868c9196989a9c9e9f9f9f9f9e9d9c9a9895918d86817b716c645c524a40372d21180e03000000000005111e2a36414c566a7683909da9aea298887b6e6155483b2d221708000000000a15212e3b4854616e7b8798a2aeaa9d908377655b5044372b1f1205000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000006121f2b37434e586673808d99a3afa89b8e81756a5f554b433c38342e3431373a4145525d68737f8c99a3afa79b8e8175675c5145382c1f13060000000000000000000000000000000000000814212e3a47535f6975828f99a3ab9f948c7f726c615a5049413a3227221b140b0400000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000713202d3a4653606d7885929fa9a2988f82786d6760595654524c5050504c5154535b6069707d8a96a0aca2988a7e7164574a3e3124170b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111b262f38424a50535b60606060606060605d54514c433a31271e150b02000000000000000000000000000000000000000000000000000000000000000000000000000000040d18222935404b555f6a717e8a939da7a09792877f746d665c544b4034281c100400000000000000000000000000000000000000010c161f27333f49535d686e7b859298a29f93887e706a60574d42362a1e1205000815222e3b4855616e7b858686868686867d706a60574d433a2f261b110700000000000000000000000000111e2b3744515e6a7784868686868686868686868686868686867d7164574a3e3124170b0000000000000000000008131e28323a4145475050505050504e4c4841382f343c4347485050505050504c4a463f372d23180d01000000000000000000000000000000000a141e2935404b555d666d747c82878b8e909192929291908e8c88847f7a716d605d55535f696f7c848b8f9192929291908d86796c605346392d2013000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000a151e2b343f49525c646e737e858d92999da0a8a9a29f9d9c9b9c9d9fa2aaa7a09d99928e857e736e645c52493f332a1f140900000000000713202d3946525e687885929fabac9f9285796c605346392d201306000000000714212d3a46535e697985929facac9f9285796c605346392d201306000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000030f1a26313c4854616e7b87929faaac9f92877c6f675d554e46454041414142474c515b606d7a85929eabaca095897d7063554b4034281c100400000000000000000000000000000000000006121e2b37424d57626f7c87929fa7a69f93877e716c605b534c443d332d261d160e06000000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000a1723303d4a5663707d899297979992857b6e665c554f49474541434343414547495057616b7784919daaaa9a8d8174675a4e4134271b0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262f383f44464e5353535353535353504745413a31281f150c030000000000000000000000000000000000000000000000000000000000000000000000000000000000071018242f39434e58616c74818e95a0a9a299928b80786d665c5145382c1f13060000000000000000000000000000000000000000040d17222d38414c565f696f7d869299939a92867c6f695f53463a2d211407000714212d3a46535f696e78797979797979706b61584e453b31281d140a0000000000000000000000000000101d2a36434f5b67717779797979797979797979797979797979716c6155493c3023170a00000000000000000000020c1620283035393a43434343434341403c362f262a32373b3c4343434343433f3e3a342d251b11070000000000000000000000000000000006111c26303845515d676d7880898f93999a9d9e9f9f9f9e9d9b9896918c857e756d675d58626e7b8691969b9e9f9f9e9e9c9386796c605346392d2013000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000006111c26303d46515b646e74808a92979fa3a9a19e999792908f8f8f909298989d9fa7a39f97928a80736e635b51453b31261a0e04000000000714212e3a4754616d7a8798a2aeaa9d918477665b5044382b1f12060000000005121e2a36424d576a7784919daaaea298877a6e6154473b2e211408000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000a15212d3a46535e6975818e98a3aea3999083796d675f5853514b4e4e4e4d53555d606d74818e97a1ada69d9083776b605443392e23180c00000000000000000000000000000000000000020e1a26313c4754606a73808d959fa8a49992877e736c655e564f443f382f2820180f070000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000a1724313d4a5764707d8285878a8c8d8073685e544b433d3a39352f362f35393a3f444f596774818d9aa7a99c908376695d5043362a1d1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141d262d333839424646464646464646443a39352f281f160d030000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d28313c46505a606d7983909893939393928d82796d6053463a2d20130700000000000000000000000000000000000000000006111b262f3a434d57606a707d868686868686857b6e6155483b2e2215080005121e2a36424d575f616b6c6c6c6c6c6c6361594f463d332a1f160b0200000000000000000000000000000e1b27333f4b565f676a6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d2114080000000000000000000000040e161e24292c2d3636363636363433302b251d20262b2e2f36363636363632312e29231b130900000000000000000000000000000000000b17232e3842505a606d79828d929b9fa4ababa39f9d9c9b9c9d9fa19e97928b82796d685f6a76828f98a1a8aaa39f9995949386796c605346392d2013000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000c17232e38424f59626d74808d929ea1a9a39f97918c8885838282838385888b90959ea1a8a29f928d80736d62574d42362a20160a000000000915222f3c4855626f7b8895aab4a99c8f837669544a3f33281c0f0300000000020e1a2531434f5c6976828f9ca9b4aa95887b6f6255483c2f221509000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000005121e2a36424d57616e7b86929fa6aba0958f82796f6a63605c555b5a5b575f62676d747f8c939ea9a99f948a7d7064594f4430271d120700000000000000000000000000000000000000000915202b37434e58606d79839096a0a7a39992877f776d6860595049413a322a2119100700000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000a1623303c4955616c7076787b7d80827c6f62564d4239302d2c29242a24292c2d33404c5966737f8c99a6aa9d9184776a5e5144372b1e110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c22282b2d353939393939393939372d2c29241e160d040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c161f2a343e45515c676e7b8586868686868686867a6e6154473b2e211408000000000000000000000000000000000000000000000a141d28313b454e58616b70797979797979786e695f53463a2d21140700020e1a26313b454d53555f60606060605f57554f473e342b21180d040000000000000000000000000000000b17232e39444d565b5e60606060606060606060606060606060575550483e33281c1104000000000000000000000000040c13191d2021292929292929282724201a13151b1f21222929292929292525221e181109010000000000000000000000000000000003101c28343f4a54616c74818e949da4aca7a09d9992908f8f8f9192999a9e9f948f837a6d666f7c88949faaaea398928c88878886796c605346392d2013000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000003101c28343f4a54606b727f8c929ca4aaa299928c84807b787675757677797b7f838a91969fa6a49c928b7f72695f53463d32271b0f030000000a1723303d4a5663707d8996a3b0a89b8e8275685b4f422d22170b000000000000091c2835424f5b6875828e9ba8b0a396897d7063564a3d3023170a000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000020e1a25313b46535f69737f8c949fa7a79f948f837c75706d676867676869696e737a818c919ca5aaa1978f82766c6155473d331e150b000000000000000000000000000000000000000000030f1b27323c45515d676e7a8490959ea6a399938c827a6f6b605b534c443c332b22191107000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000814202d39444f59616469696e7073756f6a5f53443b302721201f2023282c2f353a424d566673808c99a6aa9e9184776b5e5144382b1e11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171c1f20282d2d2d2d2d2d2d2d2a21201d19130c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d18222934404b555f696e78797979797979797976685e5246392d20140700000000000000000000000000000000000000000000020b161f2a333d464f5961636c6c6c6c6c6c6b615f574d42362a1e1205000009141f29333b424648525353535353534a48443e352c22190f060000000000000000000000000000000006121d28323b444b4f51535353535353535353535353535353534a49453e362c22170c000000000000000000000000000002080d1113141d1d1d1d1d1d1b1a18140f080a0f1215151d1d1d1d1d1d191816120d0700000000000000000000000000000000000006121f2b3844505c66717e8b939ea6aea59d95908a86838282838486898d92979f959083786d73808d99a6b0a89f9286807c7a7b7d7063574a3d3024170a000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000006121f2c3844505c666f7c87929fa4aba29892878079736f6a6a696869656c6e72777d848f949fa6a49f92867b6e61584e43382b1f13060000000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b060000000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000009141f2a36424d57606d78828f959fa7a69f959087817d79777574747476787b80858e939ca3aaa29892857b6e615a5044352b210c03000000000000000000000000000000000000000000000a15202935404b555e686e7b838f949fa3a49f948f847d726c655d564d453d342b23190f060000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100004101c28333e474f5557575e61646669625f584e4332292122282b2d2e34383a40454c545e6975828f9ba8aa9d9083776a5d5044372a1d110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b0f12131b20202020202020201d1413110d0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f18232f39434d575f616c6c6c6c6c6c6c6c6c6c5e564c41362a1e11050000000000000000000000000000000000000000000000040d18212b343e474f55575f60606060605f55534d453b31261a0e020000030d18212931363a3b454646464646463d3c38332c231a10070000000000000000000000000000000000000b16202932393f4344464646464646464646464646464646463e3c39332c241a100500000000000000000000000000000000010407071010101010100e0d0b08030000030608091010101010100c0b090601000000000000000000000000000000000000000713202d3a4653606d7884919ea5afa69d938e837d797776757677797c80858c9298958e81747683909ca9aca0958a7e736f6e6e706b6155483c2f231609000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000003101c28343f4a54606d78839099a3afa39992867d736d67625f585c5c535b6061656c707a828f949fa9a2988f82766a6054473b2e2215080000000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b0a4978a7d7164574a3e3124170b000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000030e1a26313b44505c666d7a8390959da5a7a099938e898683828181818385888c92979da5a7a09892867d70695e52483e3323190f0000000000000000000000000000000000000000000000040c18242f39434c565e696e7a828c9299a1a69e9691877f776d685f574e463d352b21180c0300000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000b17212c353e44494a4d535457595c55534e463c312a2d2d3338393c4045464b51565d666e7b86929faca89c8f8275695c4f4236291c0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306060f1313131313131313110706040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d27313c454d53555f60606060606060605f524c443b3025190e02000000000000000000000000000000000000000000000000060f19222c353e44484a535353535353524846423b33291f140900000000060f181f262a2d2e38393939393939302f2c28211a110800000000000000000000000000000000000000040e1720282e3336373939393939393939393939393939393931302d28221a120800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8a96a0acac9f948e8179716d67696869676d70747a7f869095938a7e7885929fabaa9d9184776c6261616361594f44382c201407000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000006121f2c3844505c66727f8b95a0aba89f92877d706b605d55534e4f4f495053555a61686d79829097a1a49f94897c6f6256493c2f2316090000000b1825313e4b5864717e8b97a4b1a79a8d8074675a4d4134271a0e0100000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000009141f28343f4a545e686d7a838e929d9fa7a49f9b9892908e8e8d8e8f9197999ea1a9a29e9590867d706b60574d42362c22110800000000000000000000000000000000000000000000000007121d27313b444d565e686d777f8791979fa6a199928c827a6e6960584f473d332a1e150a00000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000005101a232c33393c3d4246484a4d4f4847433c3431363a3b3f4446494b5153555d60686d78828f98a2aea7998c7f7366594c403326190d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151f2a333c4246485253535353535353535346413b32291e1408000000000000000000000000000000000000000000000000000007101a232c33383c3d464646464646453b3a36312921180d030000000000060d141a1e21222c2d2d2d2d2d2c2423201c161008000000000000000000000000000000000000000000050e161d23272a2b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c171008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000106090b0c1313131313130d0c0a070200000000000005121e2a36424d576875818e9ba8afa49a8f82786d66605d555c555c6063676d727b838f9391857b8797a2ada79a8d8074675a545557554f473e33281c1004000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000713202d3a4653606d7984919ea7ada1968d80736b6059514b474342423f44464850565d676d7a85929b9993908c8275685c4f4235291c0f0200000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000030b17232e38424c565e686d79818990959b9fa2aaa39f9d9b9a9a9b9c9ea1a9a49f9c97928c837b706b60594f453b30241a1000000000000000000000000000000000000000000000000000010b151f29323b444d565d656c727d858f949fa3a39f948f847b6f6a60594f453c30261c1106000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000008111a21282d3031363a3b3d40423c3a37373b3c4246484a505355555c6063676d727a818f949eaaab9f95887c6f6255493c2f22160900000000000000000000000000000000000000000000000000000003080c0e0e131313131313130f0e0c09040000000000000000000000000000000000000000000000000000000000000003070b0d0e131313131313130e0e0c08030000000000000000000000000000000000000000000000000000000000030d18212a31373a3b4546464646464646463b3936302920170d0200000000000000000000000000000000000000000000000000000008111a21282c2f30393939393939382e2d2a261f180f060000000000000003090e1214151f202020202020171614100b050000000000000000000000000000000000000000000000040b12171b1d1e20202020202020202020202020202020171714110c0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d121618192020202020201a1917130e0800000000000714202d3a46525e697885919eabac9f93877c6f665c54514b4f4b5153555d60696e79818f949083909da9b3a4988b7e7165584b484a48443e352c21160b00000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000004101d2935404b5564717d8a96a1acaa9e9184796d60594f45403937312d3337393e444c555e68717e8b8e8a86837f7c6f6255483c2f2215090000000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b0e0100000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000006111c26303a444c565e676d747c83898e9298999b9d9e9f9f9f9f9e9d9b999993908b857f786e6960594f473d33291f12080000000000000000000000000000000000000000000000000000030d172029323b444c535b606b707a828c9299a1a69e9691857d6f6b60574d42382e23170c020000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000000000810171c2023252a2d2e31333036393c4347494d5354545b606266676d7074797e858f939ea6aea49d9083776a6054473b2e2215080000000000000000000000000000000000000000000000000001090f14181a1b202020202020201c1b191510090200000000000000000000000000000000000000000000000000000001080e1317191a202020202020201b1a18140f090100000000000000000000000000000000000000000000000000000000060f181f262b2d2e3939393939393939392e2d2a251e170e0500000000000000000000000000000000000000000000000000000000000810161c2023242c2d2d2d2d2d2c22211e1a140d060000000000000000000002050708121313131313130a090704000000000000000000000000000000000000000000000000000000060b0e1011131313131313131313131313131313130b0a080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010911181e2225252d2d2d2d2d2d2726231f19120a020000000815212e3b4854616e7b8797a1adaa9d9083776a5f544b4540424045474b51575f676d78828f9590959fabb0a3968a7d7063574a3d3d3c38332c231a100500000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000613202c3945515d6775828f9ba8aea3988b7e71675d51473d352f2b2622272b2d323a434c56606d7883817e7a76736f6a5f53473b2e2115080000000a1723303d4a5663707d8996a3b0a89b8e8175685b4e4235281b090000000000020f1b2835424e5b6875818e9ba8b0a3968a7d7063574a3d3024170a000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000000000000000a141e28323a444c555c606b6f777d8185898c8e90919292929291908f8d8a86837e79726d665f574f473d352b20170d00000000000000000000000000000000000000000000000000000000050e172029323a4149505960686d777f879297a0a8a09792867d6f695f544a3f34281e13080000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000000050b1014161a1e21282f353a4146474e5455575e6165666c6f7276797d81858b91979ea5afa69d92897d7063584e43372b1f1306000000000000000000000000000000000000000000000000030b131a202427282d2d2d2d2d2d2d292825211b140c0300000000000000000000000000000000000000000000000000020b12191f2326272d2d2d2d2d2d2d282724201a130b0300000000000000000000000000000000000000000000000000000000060e141a1e21222c2d2d2d2d2d2d2d2d21201e19140d0500000000000000000000000000000000000000000000000000000000000000050b101416172020202020201f1514120e09030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131b23292e313239393939393933322f2a241c140a0000000916222f3c4955626f7c8895a9b3a79a8d817467584e4239352f34383a40454d555c666d7a85919d9fa7b1afa396897c706356493d302f2c28211a11080000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000714202d3a4753606d7a86929facac9f92867a6d60554b403529241d1a171b1f2028313a44515c666d7775716d6866625f584e43372b1f12060000000916222f3c4955626f7c8895aab4a99c8f8276695c4f4330251a0e0200000000030f1c2936424f5c6975828f9ca8b5ab95897c6f6256493c2f231609000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000020c162029323a434b515960636b7075797c7f82838485868685858382807d7a76726d67605c544d453d352b23190e050000000000000000000000000000000000000000000101020000000000050e1720282f383f444f565e656c727d859196a0a9a29892857b6e665c50443a3025190d0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000000000000000409121b232b323a41454c525458606266696e7175797c7f8285898d92979ea1a9ada59e948d80746b6054463c32271b0f030000000000000000000000000000000000000000000000010b151d252b303435393939393939393534312c261e150c000000000000000000000000000000000000000000000000000b141d242b303334393939393939393534302b251d150b010000000000000000000000000000000000000000000000000000000003090e1214151f20202020202020201414110e0802000000000000000000000000000000000000000000000000000000000000000000000407090a13131313131312080705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070a0c0d13131313090907030005090d0f101313131312100d0903000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a0500000000000000000000000000000007111b252d343a3e3f464646464646403f3b362e261c120800000a1723303d4a5663707d8996a3b0a6998c7f7366594c402f2924292c2f353b434b545d68707d8a959fabb7afa396897c706356493d3023201c161008000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000a1723303d4a5663707d8998a3aea89b8e8275675d51433a2f23181d1d1d1d1d161f2834404a545c606a6864615e5655534e463c32261b0f030000000814212e3b4754616e7b8798a3aeaa9d9084776a574d42362a1e12050000000005111d2935414c566a7783909daaafa399877b6e6154483b2e211508000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000000050e1720353f474e524f54596063676d70727576787879797878777573706d6865605d55504a46423c332a1f14090000000000000000000000000000020507080a0b0c0c0d0e0f090907030000050d161d262d333d444c535b606b6f7b849196a1aaa2979083786d60564c41362a1b110600000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000000000009121b242d353d444c52565e61666a6f73777b7e8285888c8f92989a9fa2a9aca9a19e938e82786d60594f44342b20150a00000000000000000000000000000000000000000000000009131d272f373c40414646464646464642413d3730271e0e050000000000000000000000000000000000000000000000030d1d262e363c3f414646464646464641403c372f271d13090000000000000000000000000000000000000000000000000000000000000205070812131313131313131308070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e1317191a202020201615130f0a1015191c1d202020201f1d19140e07000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a03000000000000000000000000010d18232d373f464a4c5353535353534d4b4740382e24190e02000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f2e23181c1f24293139424c56616c7683909da9b3afa396897c706356493d302316100b0500000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000d1a2733404d5a6673808d99aab4aa978b7e7164554c4131282a2a2a2a2a2a2a2a2a232e39424a51535d5b5754524c4847433c342a20150a000000000713202d3a4653606d7986929facab9f928578695e52463a2d201407000000000713202d3946525d687885929eabac9f9286796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700000000000000010e1a26313d4751595e5f606060555c606366686a6b6c6c6c6c6b6a686664615e566060606055534d453c31261a0e02000000000000000000000002090e111414171818191a1b1c1615130f0a0400040b141b2227323a4149505960696e7b849199a3a99f958c7f73685e5246382d22170b00000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000000000006101b242d373f474f565d60686d72777c8084878b8e9297999c9fa2aaababa8a19e96918a81796d665c51473d3322190e040000000000000000000000000000000000000000000000030f1a252f3941484d4e535353535353534f4d4942393020170d02000000000000000000000000000000000000000000010b151f2e3840474c4d535353535353534e4d4841392f251a0f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000106090b0c1313131313130d0c0a07020000000000000000000000000000000000000000000000010a12191f2326262d2d2d2d23221f1b161b212628292d2d2d2c2b29251f19110800000000000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d04000000000000000000000006121e29343f495156586060606060605a58524a40362a1f1307000a1723303d4a5663707d8996abb5a6998d807366544a403428211e1a181f27303a44505a64707d8a97a2adafa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000004101c2834404b546976828f9ca9aea398887b6f6255483c2f3737373737373737373737373039404446514e4b4746413c3b37322a261f180f0600000006121f2b3844505c667784909daaaea298877b6e6154483b2e21150a000000000714212e3a4754616d7a8797a1adaa9e918477665c5145382c1f1306000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000004111d2a36424e59636a6c6c6c6c6b636059595b5d5e5f5f5f5f5e5d5c5a575f626a6c6c6c6c6c5f574d42372b1e120500000000000000000000050d14191e20212324252627282823221f1b160f0700020a111720292f383f444f575f696f7d87929fa9a79f92867a6d6153493f33271b0f03000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000000040e18222d363f49515960686d737a7f84888d9196989b9ea2a9a9acaaaaa29f9b96918c847e746d675c544a40352b2110070000000000000000000000000000000000000000000000000814202b37414b53595b606060606060605c59544b4232291f140900000000000000000000000000000000000000000007121d2731404a52585a606060606060605b59534b41372b2014080000000000000003060809131313131313130b0a08050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010406070f111213131312110e0b0706040000000000000000000000000000000000070d121618192020202020201a1917130e08000000000000000000000000000000000000000000000a131c242a2f323339393939302f2c2721262d323536393939393835312a231a11070000000000000000000000000000000000030d161f272d32353639393635322d271f160d03000000000000000000000916222e3a46515b62656c6c6c6c6c6c66635c52473b2f23170a000915222f3c4855626f7b8899a3afa89b8f8275665c51443a322d2b2627272628323e4653606d7985929fabafa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000006131f2c3845515c667884919eabac9f9286796d6053464444444444444444444444444444444444444444444444444444443b3a36312a21180e03000003101c28343f4a546875818e9ba8b3aa978a7d7064574a3d32271b0d04000001081623303d495663707c8996a9b3a89c8f827569544b4034281c1004000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b98a4aca295897c6f6256493c2f23160906040d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070000000000000006121f2c3845525e6a757979797978706b605c544d5152535352524b515a61696e777979797976695f53463a2d211407000000000000000000050e171f252a2d2e30313233343435302f2c27211910070000060e171d262d333d454d57606b73808d97a2ada2988c8073655b5044372b1f1205000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000000000a15202a343e48515b626b707a80868c9196999da0a8a8abaaa7a7a09d9a98928e8a847f79716c605c554b42392e231a0f000000000000000000000000000000000000000000000000000c1824303c48535d64686c6c6c6c6c6c6c68655d54443b3025190e0000000000000000000000000000000000000000000c18232f3943525c64676c6c6c6c6c6c6c68645d53483c3024180c0000000000040a0f13151620202020202020181715110c060000000000000000000000000000000000000000000000000000000000000000000000000000000001080d1113141c1e1f1f20201f1e1b181413100c0701000000000000000000000000010911181e2225252d2d2d2d2d2d2726231f19120a020000000000000000000000000000000000000007121c262e353b3f40464646463c3b38322b30383e41434646464645413c352c23190e03000000000000000000000000000000000a151f2831383e4243464643423e3831281f150a000000000000000000000b1825313e4a56626d72797979797979736e63584b3f3226190c000714202d3a4753606d7a86929facab9e9285796d60564c443d3a373134333332323845515c6675828f9ca8afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000713202d3a4653606d7986939facaa9d908477665c50505050505050505050505050505050505050505050505050505050504846423b332a1f14090000000b17232e3f4b5865727e8b98a8b2a69a8d807367584e43372b1f15100c090e131e2a36414c5666727f8c99a5b3aa998c7f7366594c402e23180c00000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b989f9f9f95897c6f6256493c2f231b1313100c1a2733404d5a6673808d999f9f9f9386796d6053463a2d201307000000000000000613202c3946535f6c7987868686847d736d665f5751464146454d555c606c717b83868686867b6e6155483b2e2215080000000000000000020d17202930363a3b3d3e3f3f4041423c3b38322b23190f040000050b141b2227333b454f59606d7a85929fabaa9e9185786c605346392d201306000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000000030f1b26313c46505a626d727d848d92989ea0a8aaaba8a8a09e9a9795908d8985817d78726d67615a514b433930271c1108000000000000000000000000000000000000000000000000000e1a2734404d59646f7479797979797979756f65564d42362a1c11060000000000000000000000000000000000000004101c2934404b55646e7479797979797979746f64594d4034271a0e00000000060e151b1f21222d2d2d2d2d2d2d2524211d1711090000000000000000000000000000000000000000000000000000000000000000000000000000040c13191d2021292a2c2c2d2c2c2a2824201f1c18120b03000000000000000000000009131b23292e313239393939393933322f2a241c140a000000000000000000000000000000000000020e19242e3840474b4d535353534948433d353a42494e5053535353514d473e352a1f140900000000000000000000000000000005111c27313a434a4e505353504e4a433a31271c11050000000000000000000c1925323f4c5865727f8686868686868073665a4d4033271a0d0006131f2c3945515d677783909dabada1978a7e71685e564f484742424140403f3f3f404b546673808c99a6afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000815212e3b4854616e7b879aa4afa99c90837669545d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d55534d453b31261a0e0200000615222f3c4855626f7b8896a0acaa9d9184776a6054473c31271f1c181b1a1e242d3946525e6876838f9ca9aea298897c706356493d3023160700000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e8b9393939393897c6f6256493c2f2d28201f1c181a2733404d5a6673808d939393939386796d6053463a2d20130700000000000000000b1825323e4b5865717e8b9296918780786e69625b524c4550575f676d747e869095948d8074695f53463a2d211407000000000000000009141f29323b4246474a4b4b4c4d4e4f4948433d352b21160a000000020a11172129333d45525d6874808d9aa7ada197887c6f6255483c2f221509000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000006121f2b37434e58626c727f8791969fa2aaaaaaa29f9b9896918e8a8784807d7975706d66605d555045403930271e150b00000000000000000000000000000000000000000000000000000e1b2835414e5b687481868686868686868175695e5246382d22170b0000000000000000000000000000000000000006131f2c3845515c677480868686868686868174685b4e4135281b0e00000006101820262b2e2f3939393939393931302d29221b1209000000000000000000000000000000000000000000000000000000000000000000000000040d161e24292c2d363738393939383735312d2c29231d150d0600000000000000000007111b252d343a3e3f464646464646403f3b362e261c1208000000000000000000000000000000000007131f2a35404a5257596060606056544f473d424c545a5c6060605f5e5850473c3125190d0100000000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a0000000000000000000c1925323f4c5865727f8b939393938d8073665a4d4033271a0d0004101d2935404b5566737f8c99a3aea99e91847a6d68615955534d4f4e4d4c4c4c4b4b4c5865727f8b98a5afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000916232f3c4956626f7c8995acb6a89c8f82756a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a615f574d42362a1e120500000815212e3a47535f6a7784919eabaca095887c6f62584e4339312c282327262b2f35414c56616d7a86929facab9f9285796d6053463a2d20130700000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1825323e4b5865717e868686868686867c6f6256493c3939352d2c28231d2733404d5a66738086868686868686786d6053463a2d20130700000000000000000b1724313d4a56626d73808c9399938d837b726d615e56515a61696e79818a9298958f82786d60574d42372b1e120500000000000000020e1925303b444d5254565758595a5b5b56544f473d32271b0f0300000000060f18212935414c5663707d8996aab3a9988c7f7265594c3f3226190c000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000000000815212e3a47535f6a717e889299a1a9aca69f9c98928e8b8784817e7a7773706d6663605c54514b433e342e271e150c0300000000000000000000000000000000000000000000000000000916232f3c4956626f7c89959393939392867b6e61544a3f33281c0f030000000000000000000000000000000000000714202d3a4753606d7985929393939395897c6f6356493c302316090000040e18222a32373b3c464646464646463e3d39342d241b110600000000000000000000000000000000000000000000000000000000000000000000010c161f282f35393a4244454646464544413e3a38342f271f17110a02000000000000010d18232d373f464a4c5353535353534d4b4740382e24190e02000000000000000000000000000000000a17232f3b47525c63666c6c6c6c6360594f4349545e66696c6c6c6c6a62584d4135291d100400000000000000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d0100000000000000000c1925323f4c5865727f8b989f9f998d8073665a4d4033271a0d00000c18242f3b4854616e7b86929fa8ada19690827a706b65615f575c5a5a5959585858585865717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1623303d495663707c8996a3afa89b8e8177777777777777777777777777777777777777777777777777777777777777776e695f53463a2d211407000006121f2b37434e586673808d99a3afa89b8e81756a5f554b433c38342e3431373a4145525d68737f8c99a3afa79b8e8175675c5145382c1f130600000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000b1724313d4a56626c71797979797979796f6a605447464646413a38342e2726323f4b58636e737979797979797976665c5044382c1f120600000000000000000915212e3a45505a636e74818e939f9590867e756d68605c606c717b838e939f969083796d665c50453c31261a0e020000000000000005111e2a36424d565e61636465666767686360594f43382c1f13070000000000060f1924303a4753606d798698a2aea79a8e8174675b4e4134281b0e000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000006121f2b37434e58626f7c86929aa3aba8a09e948f8a85827e7b7774716e686763605c5453504a4540393128231f1c17110a02000000000000000000000000000000000000000000000000000915222e3b4854606a7783909daa9fa3998c7f73665b5044382b1f1409000000000000000000000000000000000006121f2b37434e5864717e8a97a29f9f9d9083776b6054483b2f22150900000a15202a343c434749535353535353534b49453e362d22170c0000000000000000000000000000000000000000000000000000000000000000000008131e28313a4145474f515252535352514e4b474540393127221b140b02000000000006121e29343f495156586060606060605a58524a40362a1f1307000000000000000000000000000000000c1926323f4b57636e73797979796f6b6054484e5a66707679797979746a5e5145382b1f120500000000000000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f0300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000714202d3a46525e6974808d96a1a9a89f9590847d77726e696a6867666665656565646465717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1724303d4a5763707d8a96a3b0ab9e928583838383838383838383838383838383838383838383838383838383838383837b6e6155483b2e2215080000030f1a26313c4854616e7b87929faaac9f92877c6f675d554e46454041414142474c515b606d7a85929eabaca095897d7063554b4034281c100400000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000915212e3a45505a62656c6c6c6c6c6c6c6260584e525353534e4645403930292f3b47525c63666c6c6c6c6c6c6c6c5c544a3f34281c1003000000000000000005111d29343f48525b606d78818f959f98928b827a706b676d747e8690959d9891847b6e675d544a3f332a1f140900000000000000000714202d3a46525e696e707172727374756f6b6054483b2f22150800000000000008131f2c3845515c677885929faba89b8f8275685c4f4235291c0f000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000815212e3a47535f6a76828f98a3aca7a0969189827d7975716e696764615e565653514a46443f38352f312f2d2b28221c140b0200000000000000000000000000000000000000000000000007131f2c38434e5865727e8b98a2aeab9e9184786c6053463b30251a0e00000000000000000000000000000000000814212e3a47535f6a7683909ca9aea2988b7f7265594f43382c1f130700030f1b26323c464e535560606060606060585650483e34291d11050000000000000000000000000000000000000000000000000000000000000000010d19242f3a434c52545c5d5f5f605f5f5d5b5753514b433f332d261d140a00000000000916222e3a46515b62656c6c6c6c6c6c66635c52473b2f23170a000000000000000000000000000000000d1a2633404d59667380868686867d6f635649505c69768286868686796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768286868276695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000005121e2a36424d57606d79849197a1a9a79f969189837f7b78767574737372727271717171717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1724313d4a5764707d8a97a3b0ada1979290909090909090909090909090909090909090909090909090909090909090887b6e6255483b2f2215080000000a15212d3a46535e6975818e98a3aea3999083796d675f5853514b4e4e4e4d53555d606d74818e97a1ada69d9083776b605443392e23180c0000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d2013070005111d29343f48505658606060606060605654575d5f6060605b53514b423a322a36404a52585a606060606060605f504a42382e23170c000000000000000000010c18222d364044505c666d79829095a09f938f857d746f79818a9298a09992867c6f695e554b42382e21180e0300000000000000000814212e3b4754616e7b7d7e7e7f8081827d6f6356493c3024190d02000000000004101c2934404b556b7784919eaaa99c908376695d5043362a1d10000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000915222f3c4855626f7b88949faaaca09590847d76706d6765615e575754524c494644403a444442413f3e3c3938332d261d140a000000000000000000000000000000000000000000000000030f1b27323d4754606d7a85929facaca1968a7d7063574d42362a1c110600000000000000000000000000000004101c2934404b55626e7b88949fabac9f92867a6d6054473d32271b0f030006131f2b37434e585f626c6c6c6c6c6c6c64625a5045392d211508000000000000000000000000000000000000000000000000000000000000000004111d2935414c565d60696a6b6c6c6c6b6a6864605c5550443f382f261b1106000000000b1825313e4a56626d72797979797979736e63584b3f3226190c000000000000000000000000000000000d1a2633404d596673808c9393897c6f635649505c6976838f939286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000020e1a25303b45515d676f7c8591979ea5a8a09e95908b8885838281807f7f7f7e7e7e7e7d7d808d9aa7afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1724313d4a5764707d8a97a3b0b3a9a19e9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d94887b6e6155483b2e22150800000005121e2a36424d57616e7b86929fa6aba0958f82796f6a63605c555b5a5b575f62676d747f8c939ea9a99f948a7d7064594f4430271d12070000000b1825323e4b5865717e8b98a4aca295897c6f6256493c2f23160900040d1a2733404d5a6673808d99a6aca09386796d6053463a2d20130700010c18222d363f454a4b53535353535353495761696b6c6c6c68605c544c443c342e3840474b4d5353535353535353443f3830261c11060000000000000000000006111b2428343f4a545d676d7a839196a19e979188807b838e929fa29f93877d706a5f574d433a30261c0f060000000000000000000b1724313e4a5764717e898a8b8c8d8e8c807366564c4135291e130b060400020509121f2b3844505c667885929eaba99c908376695d5043362a1d10000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000c1926333f4c5966727f8c99a6afa49a90837a706b64605c5554524d4b4746413d3a434a4f50514f4d4c4a4946443f382f261c11060000000000000000000000000000000000000000000000000a16202c3945515d6774818e9aa7b1a89b8f8275695e5246382e23170b00000000000000000000000000000006131f2c3845515c6774808d9aa6b0a79b8e8174685d5245392b21160a00000815212e3b47535f6a7679797979797979716c6256493d3024170a00000000000000000000000000000000000000000000000000000000000000000613202c3945525d686d757778797979787774716d67625a504941382d22170b030000000c1925323f4c5865727f8686868686868073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000009141f2935414b555f6a6f7c858f939c9fa4a79f9d989892908f8d8d8c8c8b8b8b8b8a8a8a8d929da9afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1723303d4a5663707d8996a3b0b8b0aba99f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa9aaaaaaaaaa94877a6e6154473b2e211408000000020e1a25313b46535f69737f8c949fa7a79f948f837c75706d676867676869696e737a818c919ca5aaa1978f82766c6155473d331e150b000000000b1825323e4b5865717e8b989f9f9f95897c6f6256493c2f2316090b10141a2733404d5a6673808d999f9f9f9386796d6053463a2d201307000006111b242d343a3d3e46464646464646505d697378797979746d665e564e463e3528363b3f40464646464646464638342e261e150a000000000000000000000000091217232e38424b555d686e7b849197a2a19a938d8890959da59d928b7f726b61584e453b31281e140a000000000000000000000815222f3b4855626e7c889798999a9a8f8275685d52463a30241d1512100c0e12141a202d3a4653606d7986939faca99c8f8276695c4f4336291c10000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000020f1c2835424f5b6875828e9ba8ac9f93877c6f68605953514b4846423e3b393634434d555b5d5d5c5a59575553504a42382d22170b00000000000000000000000000000000000000000000000004111d2935414b55626f7c88959fabac9f92877b6e61544a3f34281c100300000000000000000000000000000714202d3a4753606d7985929eabaca095897c6f63564c413529190f0400000916222f3c4955626f7c868686868686867e7164584b3e3125180b00000000000000000000000000000000000000000000000000000000000000000714212d3a4754606d7a8284858586868584817e79716c605b53493f33271f14090000000c1925323f4c5865727f8b939393938d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000020d18242f3a434e585f6a6f7a82898f93999c9fa2aaa29f9d9b9a999998989898979797979a9da4aeafa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000091623303c4956636f7c8996a2afb0a69f9c9393939393939393939393939393939393939393939393939c9ea6b0aea398877a6d6054473a2d2114070000000009141f2a36424d57606d78828f959fa7a69f959087817d79777574747476787b80858e939ca3aaa29892857b6e615a5044352b210c03000000000b1825323e4b5865717e8b9393939393897c6f6256493c2f231610171c20232733404d5a6673808d939393939386796d6053463a2d20130700000009121b22292e313239393939393945525f6b788586868681786d685f584f473f342e2f323339393939393939392c28231c150c030000000000000000000000000006111c263039434c565e696f7c859299a3a49f9a959da0a79e948d80746d62594f463c33291f160c02000000000000000000000613202d394653606c7785929ea5a69f92867a6d61564c41352e27201f1c181a1e21252a34404b55626f7c889aa4afa79b8e8174685b4e4135281b0e000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000003101d293643505c6976838f9ca9a99d9083766a5f564f4645403b3a36302e2d2f3c46555f666a6a6967656462605b544a3f33281c0f030000000000000000000000000000000000000000000000010d18242f3a47535f6a7683909da9afa3998c7f73665c5044382b1f14090a0a0a0a0a0a0a0a0a0a0a0a0a0a121f2b37434e5864717e8b97a2adaa9d9083776b6054443a2f2419070000000916222f3c4955626f7c8893939393938b7e7164584b3e3125180b00000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a87909292939292908e8a847e746c655b50443b30251a0e0200000c1925323f4c5865727f8b989f9f998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000007131d28313c464e585f686d757c82878b8f929897999a9b9c9d9d9d9e9e9e9e9f9f9f9fa3abacb5afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000815222f3b4855626e7b8895a9b3ab9f948f8686868686868686868686868686868686868686868686868f949eaaac9f928579675d5145392c20130600000000030e1a26313b44505c666d7a8390959da5a7a099938e898683828181818385888c92979da5a7a09892867d70695e52483e3323190f00000000000b1825323e4b5865717e868686868686867c6f6256493c2f23161a22282d303139404d5a66738086868686868686786d6053463a2d201307000000000911181d2124252d2d2d2d2d323f4c5965727f8c93938e827a6f6a6159514440393028272d2d2d2d2d2d2d2d1f1c17110a030000000000000000000000000000000a141e27313a444d575f6a707d879299a49f9f9f9fa9a0958f82786d605b51473e342a21170d04000000000000000000000005121f2b3744505b6575828f9baaaea3988b7f72685d52454039302d2c2823252a2d30363e45515c6773808c99acb4aa998c7f7366594c403326190d000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000004101d2a3743505d6a7683909da9a79b8e817468584e443d38342e2d2a2a2d2f38424e5866717777757472716f6c665b5044382b1f120600000000000000000000000000000000000000000000000007131d2b37434e5864717e8b97a2adab9e9184786d6053463b31251a16161616161616161616161616161616212e3a47535f6a7683909ca9aea2988b7f7265594f4332281e13080000000916222f3c4955626f7c88959f9f9f978b7e7164584b3e3125180b00000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a87949e9f9f9f9e9d9b96918b80776c60574d42362a1e120500000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000010c161f2a343c464e565e616b6f757b7f8285888a8c8d8f8f9090919191919292929292999ba3acafa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000714212d3a4754606d7a8797a2ada99c8f82797979797979797979797979797979797979797979797979828f9ca9ab9e9184786b554b4135291d1104000000000009141f28343f4a545e686d7a838e929d9fa7a49f9b9892908e8e8d8e8f9197999ea1a9a29e9590867d706b60574d42362c22110800000000000b1724313d4a56626c71797979797979796f6a6054473b2e2217242c33393c3d46464b58636e737979797979797976665c5044382c1f12060000000000060c111517182020202025313e4a56626d75818f969490847c706b625b514a423a322a211920202020202012100c060000000000000000000000000000000000020c151f28323b454e58606b717e8793939393939393969083796d665c50493f352c22190f05000000000000000000000000030f1b27333f495364717e8a98a2aeaa9e91857a6d605b514b423d3a38342e31363a3b42465059606d7984919eabaea398897d7063564a3d3023170a000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000003101d293643505c6976838f9ca9a79a8d817467564c413a39352f363036393c424a54606a77838482807f7d7c786c605346392d201306000000000000000000000000000000000000000000000000010f1b26323c4753606d7985929fabada1968a7d7063574d42362a23232323232323232323232323232323232934404b55626e7b88949fabac9f92867a6d6054473d3221160c010000000916222f3c4955626f7c8895a2aca4978b7e7164584b3e3125180b00000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a87949fa3aba6abaaa9a19e928b7f72695e52463a2d20140800000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000040d18222a343c444c52596063696e7276797b7d7f81828383848484848585858585868b909ba7afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000613202c3945515d677885929eabaa9d9184776c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c667784919eaaa99c8f8376695c50432f24180d010000000000030b17232e38424c565e686d79818990959b9fa2aaa39f9d9b9a9a9b9c9ea1a9a49f9c97928c837b706b60594f453b30241a100000000000000915212e3a45505a62656c6c6c6c6c6c6c6260584e43382b1c2328363e44494a525353525c63666c6c6c6c6c6c6c6c5c544a3f34281c10030000000000000105090b0b13131316222e3a46515b606d7a8491989691867d726d605c544c443c332b2317110a13131306030000000000000000000000000000000000000000030d162029333c464f59616c727f8686868686868686847b6e675d544a3f372d231a100700000000000000000000000000000b17222d3a4753606d7a85929faaada1978e81746d605c544f4946444043434246484d525a616b737f8c96a1acac9f92867a6d6053473a2d201407000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000020e1b2835414e5b6874818e9ba7a99c8f8276685e534c4745414343434146474d545b666f7c88908f8d8c8a85796c605346392d201306000000000000000000000000000000000000000000000000000a151f2c3845515d6774808d9aa6b0a89c8f8275695e5346382e3030303030303030303030303030303030303845515c6774808d9aa6b0a79b8e8174685d5245392c201304000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b00000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8799929995999fa2aaada49f92867b6e6154483b3025190e02000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000050e171e252a323a41464f54575e6165666d6f717374757676777777787878787879797e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000004111d2935414c55697683909ca9ab9f928578695f606060606060606060606060606060606060606d7986929faca79a8d8174675a4e4134271b070000000000000006111c26303a444c565e676d747c83898e9298999b9d9e9f9f9f9f9e9d9b999993908b857f786e6960594f473d33291f120800000000000005111d29343f485056586060606060606056544e463d3227262e343f485055575f6060605a585a606060606060605f504a42382e23170c000000000000000000000000060606121e29353f45525d686f7c86929f9892877f746d665d564d453d3528231c140c03000000000000000000000000000000000000000000000000040e17212a343d47505a626d727979797979797979786e695e554b42382e251b11080000000000000000000000000000000613202c3945515d6773808d98a2aea99d938c7f736d6660595653514a50504d5354575e616c707d87929fa8b0a69b8e8275675d5145392c201306000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000c1926323f4c5965727f8c98a7ac9f92867a6d655e5654514b504f504d5254575f666c7882909c9c9a988e8174655b5044372b1f12050000000000000000000000000000000000000000000000000004101d2935404b55626e7b88949fabac9f93877b6e61544a3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4753606d7985929eabaca095897c6f63564c4135291d1104000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b00000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a87878686888d9298a2abaea2988c807366564d41362a1e1105000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000020c1720293036393a3e3f44484d5354545c606264666768696a6a6a6b6b6b6b6c6c6c717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000010d19242f414d5a6774808d9aabaea298887b6e61555353535353535353535353535353535355626f7c8899a3afa9988b7e7265584b3f3225180c00000000000000000a141e28323a444c555c606b6f777d8185898c8e90919292929291908f8d8a86837e79726d665f574f473d352b20170d00000000000000010c18222d363f454a4b535353535353534947433d342b2830383f44515a61646c6c6c6c66635c5253535353535353443f3830261c11060000000000000000000000000000010d18232935414c565f6a727e8b939e99938c81786d685f574f473f342e261e150c03000000000000000000000000000000000000000000000000050f18222b353e48515b62656c6c6c6c6c6c6c6c6b615e574d433a30261c13090000000000000000000000000000000004111d2935404b55616e7b86929fa6afa59c918c8079706b6562605c545c5d575e6164696e747e869299a3afaa9f94897d7063554b4035291d1104000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000915222f3c4855626f7b88959faba3998e81776d6863605d555d5c5d565e6164696e78808e949fa8a0958a7d706453493f33271b0f0300000000000000000000000000000000000000000000000000000c18242f3947535f6a7683909ca9afa4998c8073665c504949494949494949494949494949494949494949494e5864717e8b97a2adaa9d9083776b6054443a2f24190d01000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b00000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d787c7a79797c80869299a4afaa9e918477685e5246392d201407000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000008131e29323a4146474b4c4d4e4f51524a50535557595a5c5c5d5d5e5e5e5e5f5f5f65717e8b98a4afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000081724313e4a5764717d8a99a3afaa988b7e7165574d42464646464646464646464646424d5765727f8c98abada297887b6f6255483c2f2215090000000000000000020c162029323a434b515960636b7075797c7f82838485868685858382807d7a76726d67605c544d453d352b23190e05000000000000000006111b242d343a3d3e464646464646463c3b38322b29323a424a505b636c7079797979736e63574b46464646464638342e261e150a00000000000000000000000000000000070d19242f3a434e58626d75818e95a09f928e827a6e69605951443f3830271e150b00000000000000000000000000000000000000000000000000061019232c363f4951565860606060606060605e54524d453b31281e140a0100000000000000000000000000000000010d18242f3a46525e68727f8c949fa8ada49c928d837d77726f6d666a69696a696e71757b818a9298a2abaea2988f82766b6054433a2f24180d01000000000000000205111e2a3744515d6a7784909d9f9f9c8f8376695c504336291d100d0b08030000000000000000000000000004111e2a3744515d6a7784909d9f9f9c8f8376695c504336291d1003000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000815212e3a47535f6a7683909da5ab9e938e817a74706d676a6969696a686e71757b828e929da6a59d9083786c605346392d22170b00000000000000000000000000000000000000000000000000000007121d2b37434e5864717e8a97a1adab9e9184796d6056565656565656565656565656565656565656565656565f6a7683909ca9aea2988b7f7265594f4332281e130800000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b020405060606050402000000000000000000000000000000000000000000000006121f2c3844515c666d6f6d686d6f737d87939facaca096877a6e6154473b2e211408000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000010d1925303a444c525457595a5b5c5d5e5b5953484a4c4e4f5050515151515252525965727f8c98a5afa396897c706356493d3023160a000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000714212e3a4754616d7a86929faca89b8e8275695e53463d313939393939393939303946525e6976828f9ca9ab9e9285786c605346392d201306000000000000000000050e172029313940454f54596063676d70727576787879797878777573706d6865605d55504a423c332b231911070000000000000000000009121b22292e3132393939393939392f2e2b272b333b444c545c606d727e868686868073665a4d4039393939392c28231c150c03000000000000000000000000000000000008131e28313c46515b606d79839198a29d948f847b706b625b504a423930271d12070000000000000000000000000000000000000000000000000007111a242d373f464a4c5353535353535353524846423b33291f160c0200000000000000000000000000000000000007131d2a36414d56606d78829096a1a8ada49d959089837f7c797777767677787b7d82868e939fa2aaaea39f92867b6e61594f4431281d130700000000000002080e11141e2a3744515d6a778490939393938f8376695c50433629201b1a18140f0801000000000000000000000004111e2a3744515d6a778490939393938f8376695c504336291d1001000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c1000000006121f2b37434e5863707d89939da6a59e938e86807d7a787776767677787a7e82878f949da5a69d938a7d70655b5044372b1b1106000000000000000000000000000000000000000000000000000000010f1a26313c4653606d7985929eacada1968a7d70646363636363636363636363636363636363636363636363636e7b88949fabac9f92867a6d6054473d3221160c0100000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180c0e101213131312100e0b0807050200000000000000000000000000000000000004101c2834404a545c6062615e60626b75818e9ba8b2a8968a7d7063574a3d3024170a000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000005111d2a36414c565e6164656768696a6b68655d534840414243434444444545454d596673808c99a6afa295897c6f6256493c2f231609000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000713202d3946525d6876828f9ca9ac9f92867b6e61584e433b322c292424292c3139424d57616e7b86929faca89b8e8174655b5044372b1f120500000000000000000000050e171f272f343d43484f54555c606366686a6b6c6c6c6c6b6a686664615e5653514b443f38302a211911080000000000000000000000000911181d2124252d2d2d2d2d2d2d2322242c343d454d565d666d747f87929892857b6e6154473b2e2d2d2d2d1f1c17110a03000000000000000000000000000000000000010c161f2a343f45515d676e7c86929fa59f9691857d726d605c544b42392e23180c000000000000000000000000000000000000000000000000000008121b252d343a3e3f4646464646464646453b3a36302921170d0400000000000000000000000000000000000000010e1925303b44505c666e7a849196a0a7afa7a09d95908c8985848383838485878a8e92999da5aeaaa39f918a7e71695f53473d321f160c010000000000050d14191e20212d3744515d6a77838686868686868276695c5043362d2d272724201a130b020000000000000000000004111e2a3744515d6a77838686868686868276695c504336291c140a000000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000000030f1a26313c4855606b74818e949da5a59e98928d898785838382838485878a8f93999fa6a49d948e81746c6153493f33271b0a000000000000000000000000000000000000000000000000000000000009151f2c3845515c6673808d9aa4afa99c8f82757070707070707070707070707070707070707070707070707074808d9aa6b0a79b8e8174685d5245392c2013040000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e312518191b1d1f1f201f1f1d1b181414110e080200000000000000000000000000000000000c18232e39424a5153555452535964717e8a97a4b1a5988b7f7265584c3f3225190c000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000713202d3946525e686d71727374767778756f65594d3d323536373737383835404b556774818e9aa7b2a995887b6e6255483b2f221508000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000005111d2935414c5664717e8b96a1ada3998d80746a60564d443e39352f2f35383c434b545e6973808d99a3aca096897d706353493f33271b0f030000000000000000000000050d151d232932383d44484b5161696b6c6c6c68605c5f5e5d5c5a5754524c47454039342e261e180f080000000000000000000000000000060c11151718202020202020151d2328363e464f575f686d78818c939993877d70695e52463a2d2020202012100c06000000000000000000000000000000000000000000040d18222935404b555f6a717e8a939da7a09792877f746d665c544b4034281c1004000000000000000000000000000000000000000000000000000009131b23292e31323939393939393939382e2d2a251f170f0500000000000000000000000000000000000000000008141f28343f4a545e686e7b8490959fa3abaca7a09d98989291908f90919297979b9fa3abaca7a098928b7f726c61574d42352b210d040000000000050e171e252a2d2e3939424f5b6771777979797979797670665a4e423939393433302b251d140b0100000000000000000003101d2936424f5b6771777979797979797670665a4e42352e261c12070000101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c10000000000a15202c38444f59606d79828e939da0a7a29f9a96979290908f90909297979b9fa4a7a09d928d82786d605a5041382d22170b000000000000000000000000000000000000000000000000000000000004101c2834404b54616e7b87939facac9f93877d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d85929fabaca095897c6f63564c4135291d11040000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e31252225282a2b2c2d2c2b2a282521201e19140f0a0400000000000000000000000000000007121c2730394044464847464855626f7b8895a2aea6998c7f7366594c403326190d000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000714212e3a4754616d7a7e7f8081828485817568584e43372e2c2823282c2f3945515d677783909daaada196877a6d6054473a2d211407000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000010d1924303a4653606d7984919ea7ab9f92877c6f685e564f47454141414045474e555c666e7b86929faba89e9184786c605346392d22170b00000000000000000000000000030b121821272c323839505d697378797979746d665e564e4f4d4a4746413a39352f28231c150c06000000000000000000000000000000000105090b0b131313130e161e272e344048505960696e7a828e939f948c7f736b60574d42362a1e1113130603000000000000000000000000000000000000000000000000071018242f39434e58616c74818e95a0a9a299928b80786d665c5145382c1f13060000000000000000000000000000000000000000000000000000010911181e2224252d2d2d2d2d2d2d2d2b21201e1a140d0500000000000000000000000000000000000000000000020b17232e38424d565f696e7b838d92999fa4acacaaaaa39f9e9d9c9c9d9ea1a9a8acaca8a19e9590867e726d625a50453c3123190f0000000000020d1720293036393b4646464a555f676a6c6c6c6c6c6c69665e54494646464641403c362f261d1308000000000000000000010e1a27333f4a555f676a6c6c6c6c6c6c69665e544b4740382e24190e0200101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d697683908f8276695c4f4336291c100000000003101c27333d45515c676d79818990959b9fa2aaa9a19e9d9c9c9c9d9fa2a9aaa29f9b95908a80786d665c51473e2f261b11060000000000000000000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9afa499938a89898989898989898989898989898989898989898989898989899297a2adaa9d9084776b6054443a2f24190d010000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e312d2e32353738393939383735312e2d2a251f1b150d070100000000000000000000000000000b151e272e34383a3c3a3a4754606d7a8793a0b5a69a8d8073675a4d4034271a0d000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000815212e3b4854616e7b878c8d8e8f909184786a6054473f3a38342e34383a404b55606d7a86929facab9e918578675d5145392c201306000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000008131f2c3845515c67727f8b95a0aba39991847a6e68615954514c4e4e4b5153575f676d78839098a2aca0968b7f72665b5044382b1b1106000000000000000000000000000001070c161b21273845525f6b788586868681786d685f584f473f3a3936302c29241d17110a03000000000000000000000000000000000000000000000600070f18202830394045525a616b6f7b838f949d968f82776c60594f453b30251a0e020600000000000000000000000000000000000000000000000000000007121d28313c46505a606d7983909893939393928d82796d6053463a2d20130700000000000000000000000000000000000000000000000000000000060d1216181920202020202020201f1514120e090200000000000000000000000000000000000000000000000006111c26303b444d575f696e7880878f939a9ea1a8a7a9aaaaaaa9a9aaaaa9a8aaa39f9c96918b837c716c625b51483e332a1f1107000000000008141e29323b4146535353535353555b5d6060606060605c5a545353535353534e4c4841382f251a0f030000000000000000000a16222e39434d555b5d6060606060606060605a57524a40352a1f130700101c2936434f5c6976828f908376695d5043362a1d10030000000000000000000000000000000000000000000000010507070b0b0b0b0b0b0b101d2a3643505d697683908f8276695c4f4336291c1000000000000b16212834404b555c676d747d838a8e9298989a9c9d9e9f9f9f9e9e9c9a9898928e8a837d746d665c544a40352c1d140a0000000000000000000000000000000000000000000000000000000000000007121d2a36424d5764707d8a96a1adaba49f9796969696969696969696969696969696969696969696969696969fa2a9aea2988b7f7265594f4332281e1308000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e373a3b3f4143454646464543413e3b3936302b272018130c0400000000000000000000000000030c151c23282c2d2f2e3a4653606d798699a3afa79a8d8074675a4d4134271a0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000714212d3a46535e697884919a9b9c9d96897c6f625a504a464440434044464b515c67717e8b98a3aeaa9b8f827568554b4135291d1104000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000004101c2834404b55606d78839099a3aba09690837a706b64605d555b5b555d60636a6e79818e959faaa49a9184796d60544a3f33281c0a0000000000000000000000000000000000040a0f1926323f4c5965727f8c93938e827a6f6a6159514440393028201d18120c0600000000000000000000000000000000000000000000000000071019212a323a434b515b636c717d8591959f9991847a6d655b50473d33291f14090000000000000000000000000000000000000000000000000000000000010c161f2a343e45515c676e7b8586868686868686867a6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000106090b0c131313131313131312080705020000000000000000000000000000000000000000000000000000000a141e29323c454d575e666d737c82878d9196989a9c9d9e9f9f9f9f9e9c9b9998928f8a847f786f6a625a51493f362c21180e0000000000020e1925303b444c525f6060606060605d5b5553535353534f54566060606060605a58534a41362b20140800000000000000000006111c27313b434a4f5153515a61646c6c6c6c66635c52473b2f23170a00101c2936434f5c6976828f908376695d5043362a1d100300000000000000000000000000000000000000000002080d11131417171717171717171d2a3643505d697683908f8276695c4f4336291c100000000000050c18232e39434b555c606b6f787d8185898b8e9091919292929191908e8c8985827d77706b605c544b42392e231a0b0200000000000000000000000000000000000000000000000000000000000000000e1a26313b4653606d7984919eabb5afaca3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3abadb3ac9f92867a6d6054473d3221160c01000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e4246484c4e505252535252504e4b4746413b373229241d160d0500000000000000000000000000030b12181c1f20222c3844505c667986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000005121e2a36424d576774818e9aa6a9a89b8e81756c605c5453514a504a5153555d606d7983919daaaea2988b7e7165584b3e2f24180d01000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000c18232e3944515c666f7c87929fa4a8a09590847d76716d6769676869676d70757b838e939ea7a59f93887d70665c5142382d22170b000000000000000000000000000000000000000b1825313e4a56626d75818f969490847c706b625b514a423a322a2119110600000000000000000000000000000000000000000000000000040f19222b333c444c555c606d737e869297a09f92877c6f685d53493f352b20170d02000000000000000000000000000000000000000000000000000000000000040d18222934404b555f696e78797979797979797976685e5246392d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c17202a333c454d545c606a6f757b8084888b8d8f91929293929291908e8c8986827d79726d665f5850483f372d241a0f06000000000005111e2a36414c565e6c6c6c6c6c6c6c6a675f554a46444f5960636c6c6c6c6c6c67645c53483c3024180b0000000000000000000008101f2931323a424a505b636c7079797979736e63574b3f3226190c00101c2936434f5c6976828f908376695d5043362a1d10030000000000000000000000000000000000000000050d13191e20212424242424242424242a3643505d697683908f8276695c4f4336291c1000000000000007121d273039434b515960666c7075797c7f81838485858685858483817f7d7975706b636159514b423930271c110800000000000000000000000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a3afbbb9b1acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa7a9afb8bab1a79b8e8174685d5245392c20130400000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b464d5355585b5d5e5f605f5e5d5b5854524d47433d352f281f170f050000000000000000000000000000070c1012131c28343f4a5f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000020e1a25313c4855626f7c88949faaaa9e938a7e726d6662605c545d545c6062676d75808d95a0aca99f92867a6d6154473a2e21140700000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000007121d2834404a54606a727f8c929ca4a7a096918a827d7a7775747475767a7d818790959ea5a59e938d80736b60544b402f261c1106000000000000000000000000000000000000000916222e3a46515b606d7a8491989691867d726d605c544c443c332b2317110a0200000000000000000000000000000000000000000000000a16212b343d454d565e676d757f8a9298a19e938b7f726a60564c41382d23190e050000000000000000000000000000000000000000000000000000000000000000060f18232f39434d575f616c6c6c6c6c6c6c6c6c6c5e564c41362a1e1105000000000000000000000000000000000000000000000000000000000000000000000000020608080c0e111212131312110e0c080705020000000000000000000000000000000000000000050e18212a333b424b51585f626a6e73787b7e80828485858686858483817f7c7975716d66605c544e463f362d251b12080000000000000714202d3946525e68767979797979797771675b4f434854606b70797979797979746e64584c4033271a0d00000000000000000007121a222b333b444c545c606d727e868686868073665a4d4033271a0d00101c2936434f5c6976828f908376695d5043362a1d100b0b0b0b0b0b0b07070501000000000000000000050e171e252a2d2e313131313131313131313643505d697683908f8276695c4f4336291c10000000000000000b151e27303940454f545b6063676d7072747677787879797877767472706d66636159554f45403930271e150b0000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87929facb9b1a7a0939393939393939393939393939393939393939393939b9ea5afb8aca095897c6f63564c4135291d110400000000000000000916222f3c4955626f7c8895a2afa4978b7e7164585053575f6165686a6b6c6c6c6b6a6864615e56544e45403a312921170f0500000000000000000000000000000004060c17232e46535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000915212e3b47535f6a76828f98a2aea59f92877f78726f6d666a696a666d6f7379818d929da7aca2978d8074685d5246392d20130700000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000c18232e39424e58626d73808c929ea1a8a19e948f8a8683828181828386898e93999fa7a39f938f81786d60594f42392e1d140a000000000000000000000000000000000000000006121e29353f45525d686f7c86929f9892877f746d665d564d453d3528231c140c03000000000000000000000000000000000000000000030f1b27323d464e575f686d79818c929fa3a0958e81756d62584e443a2f261b11080000000000000000000000000000000000000000000000000000000000000000000007121d27313c454d53555f60606060606060605f524c443b3025190e020000000000000000000000000000000000000000000000000000000000000000000003090e121415191b1d1e1f201f1f1e1b191514120e090300000000000000000000000000000000000000060f182129303940454e53575f6266696e71747677787979797877767572706d6764605c54504a423c342d241b1309000000000000000814212e3b4754616e7a86868686868683776a5d5144495663707d8686868686868074675a4e4134271b0e00000000000000030b1218242c343d454d565d666d747f87929892857b6e6154473b2e21140800101c2936434f5c6976828f908376695d5043362a1d17171717171717171413110d0802000000000000020d1720293036393a3e3e3e3e3e3e3e3e3e3e3e43505d697683908f8276695c4f4336291c1000000000000000030c151e272e343d424a5053555d60636567696a6b6c6c6c6b6b69676563605c54554f48443e342e271e150c0300000000000000000000000000000000000000000000000000000000000000000000000c17232e3846525e6975828f9ca8b2aca095898686868686868686868686868686868686868686868e939ea9b4aa9d9084776b6054443a2f24190d0100000000000000000916222f3c4955626f7c8895a2afa4978b7e7164545c6064696e72747678797979787674716e68626058514b433b332921170d030000000000000000000000000000000013202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000006121f2b37434e58626f7c86929fa4aca399928b837f7b797777767777797c80858e939da4aea49a92857a6d61564c4135291d110500000000000000000000000000000203101d2a3643505d69768390908376695d5043362a1d100302000000000000000000000007121c27303d46515b646e73808a92979fa3a69f9c9992908f8e8e8f9092989b9fa4a69f99928c81786d665c50473d30271d0b020000000000000000000000000000000000000000010d18232935414c565f6a727e8b939e99938c81786d685f574f473f342e261e150c03000000000000000000000000000000000000000007131f2c38434e5860696e7a828e939ca4a2989183796d605b51463d32281d140a0000000000000000000000000000000000000000000000000000000000000000000000010b151f2a333c4246485253535353535353535346413b32291e1408000000000000000000000000000000000000000000000000000000000000000000060c11151a1e212226282a2b2c2c2c2b2a282522211e1a14100b05000000000000000000000000000000000000060f171e272e343c43474e5355575f626567696a6b6c6c6c6c6b69686663605c5553504a443f38302a221b120901000000000000000814212e3b4754616e7a87939393939084776a5d5144495663707c89939393938d8174675a4e4134271b0e000000000000050c151d2328363e464f575f686d78818c939993877d70695e52463a2d20140700101c2936434f5c6976828f908376695d5043362a24242424242424242421201e19130d05000000000008131e29323a4146474a4a4a4a4a4a4a4a4a4a4a4a505d697683908f8276695c4f4336291c100000000000000000030c151d23282f383f44464b515356585b5d5e5e5f5f5f5e5e5d5b595653514b48443e383328231d150c0300000000000000000000000000000000000000000000000000000000000000000000000006111c2a36424d5763707d8a96a1acaa9d9083797979797979797979797979797979797979797979818e9ba7aea2988b7f7265594f4332281e13080000000000000000000916222f3c4955626f7c8895a2afa4978b7e716460666d71777b7f8183858586858583817e7b756f6a605d554d453b33291f150b0100000000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000030f1b26323c47535f6a717e8b939aa2aaa39f95918c8886848483838485898c92979ea5aaa39f93887d70685e52443a3024190d01000000000000000000000000050a0f12101d2a3643505d69768390908376695d5043362a1d10120f0a05000000000000000000000b151e2b343f49525c646e737e858e92999ea1a8a39f9d9c9a9b9c9d9fa3a9a29f9b948f877f776d665c544a3f352c1e150b00000000000000000000000000000000000000000000070d19242f3a434e58626d75818e95a09f928e827a6e69605951443f3830271e150b00000000000000000000000000000000000000000915222e3b4854606a6f7b8490949ea5a49f92867c6e675d51493f342b20160b02000000000000000000000000000000000000000000000000000000000000000000000000030d18212a31373a3b4546464646464646463b3936302920170d020000000000000000000000000000000000000000000000000000000000000002090e171d1f262b2e2f32353738393939383735322e2d2b261f1c160c07010000000000000000000000000000000000050c151d232831373c4247484d5355585a5c5e5f5f605f5f5e5d5b595653514b46443f38342e261e1810090000000000000000000814212e3b4754616e7a87949f9f9d9084776a5d5144495663707c89969f9f9a8d8174675a4e4134271b0e0000000000060e161e272e344048505960696e7a828e939f948c7f736b60574d42362a1e110500101c2936434f5c6976828f908376695d504336313131313131313131312e2d2a251e170e05000000010d1925303a444c5254575757575757575757575757575d697683908f8276695c4f4336291c10000000000000000000030b12181d262d333839404547494c4e5051525253525251504e4c4a4645403938332c282118120b0300000000000000000000000000000000000000000000000000000000000000000000000000000e1a25303b4653606c7884919eabaca095897c6f6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7a86929facac9f92867a6d6054473d3221160c010000000000000000000916222f3c4955626f7c8895a2afa4978b7e71646a6f787e83888b8e909192939291908e8b86827c746d675e574d453b31271d120700000000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000a15202b37434e58616c727f8892989fa3a7a09d99999291909090919298999ea2a9a69f98928b7f726c61564c4132281e13080000000000000000000000010910161b1e20202a3643505d69768390908376695d5043362a20201e1b161009010000000000000000030c19222d37404a525c636c717a81868d9196989b9c9e9f9f9f9f9e9d9b9997928e89827c736c655c544b42382e231a0c03000000000000000000000000000000000000000000000008131e28313c46515b606d79839198a29d948f847b706b625b504a423930271d1207000000000000000000000000000000000000000916232f3c4956626f7c85919693939393928a7e716a5f554b40372d22190e040000000000000000000000000000000000000000000000000000000000000000000000000000060f181f262b2d2e3939393939393939392e2d2a251e170e0500000000000000000000000000000000000000000000000000000000000000050d141a22282d31373a3b3f4144454546464544413f3b3a37312c272118120b030000000000000000000000000000000000030b121820262b31373a3c4247484b4d4f51525253535251504e4c494745403a38342e28231c140c06000000000000000000000814212e3b4754616e7a8794a1aa9d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e00000000070f18202830394045525a616b6f7b838f949d968f82776c60594f453b30251a0e0200101c2936434f5c6976828f908376695d50433e3e3e3e3e3e3e3e3e3e3e3a3936302920170d02000005111e2a36414c565e616464646464646464646464646464697683908f8276695c4f4336291c100000000000000000000000070b141c22282b2f35383a3d3f41434445454646454443413f3d3a38342e2c28211c160c070000000000000000000000000000000000000000000000000000000000000000000000000000000009141f2b3844505b66727f8c99a3aea79a8d8174675c606060606060606060606060605765717e8b98a2aea79b8e8174685d5245392c201304000000000000000000000916222f3c4955626f7c8895a2afa4978b7e716c717c838b9095989b9d9e9f9f9f9e9d9b99928f8781796e695e574d43392f23180c03000000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000040f1a26313c46505a636d727e868e92999da0a8aba39f9e9d9c9d9e9fa2aaaaa29f9b948f867e726d62594f443a3020160c0200000000000000000000010a131b21272b2d2d2d3643505d69768390908376695d5043362d2d2d2b27211b130a01000000000000000007101b252e38404a525a61686d747b8084888b8e90919292929291908e8c8985817c766f6a605b534b423930261c1108000000000000000000000000000000000000000000000000010c161f2a343f45515d676e7c86929fa59f9691857d726d605c544b42392e23180c000000000000000000000000000000000000000d1a2633404d59667380868686868686868680746c61574e43392f251b100700000000000000000000000000000000000000000000000000000000000000000000000000000000060e141a1e21222c2d2d2d2d2d2d2d2d21201e19140d0500000000000000000000000000000000000000000000000000000000000000060f171f252a34393c4247484c4e505152535252514e4c4846423c383329241d150d03000000000000000000000000000000000000070c151b20262b2e31373a3b3e41434445464646454443423f3d3a38342f2c28231c17110a0200000000000000000000000814212e3b4754616e7a8794a1a99d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e000000071019212a323a434b515b636c717d8591959f9991847a6d655b50473d33291f14090000101c2936434f5c6976828f908376695d504a4a4a4a4a4a4a4a4a4a4a4a4746413a32291e130800000713202d3946525e686d7171717171717171717171717171717683908f8276695c4f4336291c10000000000000000000000000020a11171c1f24292c2d3032343637383939393838363432302d2c28231d1c16100b050000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1c28333f4a54616e7a86929facab9f9285796d60535353535353535353535353535f697683909caaaca095897c6f63564c4135291d1104000000000000000000000916222f3c4955626f7c8895a2afa4978b7e71717e8790959da09e9c9b9a9b9c9ea1a9aba39f9a938e847b6e695e554b403429201509000000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000000a15202a343e48515b636c717b81878c919597999c9d9e9e9f9f9f9e9d9b9998928e89827b716c625b51473e32281e0e04000000000000000000000009131c252c33373939393943505d69768390908376695d50433939393937332c251c130900000000000000000009131c262e38404850565e61696e73787c7e818384858686858583817f7c79746f6a625f585049413930271e150a0000000000000000000000000000000000000000000000000000040d18222935404b555f6a717e8a939da7a09792877f746d665c544b4034281c10040000000000000000000000000000000000000c1925323f4b57636d737979797979797979746e645a50453c31281d120900000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214151f20202020202020201414110e080200000000000000000000000000000000000000000000000000000000000000060f18212930363e45494d5355595b5d5e5f5f5f5e5d5b5855534d48443d352f271f150d03000000000000000000000000000000000000030a0f151a1e21262b2e2f32343637383939393938363533302d2c29231f1c17110b06000000000000000000000000000814212e3b4754616e7a87949c9c9c9084776a5d5144495663707c89969c9c9a8d8174675a4e4134271b0e0000040f19222b333c444c555c606d737e869297a09f92877c6f685d53493f352b20170d020000101c2936434f5c6976828f908376695d5757575757575757575757575754524c443a3025190d01000714212e3a4754616d7a7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7e83918f8276695c4f4336291c100000000000000000000000000000060b0f12181d1f202325282a2b2b2c2c2c2b2b2a282623201f1c1812100b0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222d3846525e6875828e9ba8ada2978a7e7164574d42464646464646463f4a54626e7b88949fabaa9d9084776b6054443a2f24190d01000000000000000000000916222f3c4955626f7c8895a2afa4978a7e717e8892999e9896918f8e8d8e8f92979b9fa4aca49f9691847b6e675c51453c31261a0e020000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000030e18222d363f49515a61696e747b8084888b8d8f90919292929291908e8c8985817c766e69615a51493f352c20160c000000000000000000000005101b252e373e434646464646505d69768390908376695d504646464646433e372e251b10050000000000000000010a141c262e363e444c52575e61666a6f7274767878797978787675726f6d66626058534e443f382f271e150c03000000000000000000000000000000000000000000000000000000071018242f39434e58616c74818e95a0a9a299928b80786d665c5145382c1f13060000000000000000000000000000000000000a16232f3b47525b63666c6c6c6c6c6c6c6c67645c52483e332a1f160c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002050708121313131313131313080705020000000000000000000000000000000000000000000000000000000000000000030d18212a333b42465055575f6265686a6b6c6c6c6b6a6865615f57544f45403931271f150b010000000000000000000000000000000000000003090e12151a1e21222527292b2c2c2d2c2c2b2a282623201f1c1812100c060000000000000000000000000000000814212e3b4754616e7a878f8f8f8f8f84776a5d5144495663707c898f8f8f8f8d8174675a4e4134271b0e00000a16212b343d454d565e676d757f8a9298a19e938b7f726a60564c41382d23190e05000000101c2936434f5c6976828f908376696464646464646464646464646464615e564c41362a1e1105000a1723303d4a5663707d898a8a8a8a8a8a8a8a8a8a8a8a8a8a8a91958f8276695c4f4336291c100000000000000000000000000000000003070c10131416191b1d1e1f1f201f1f1e1d1b19171313100c07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c2a36414c5663707d8996a0aca99c8f8276695e5246382d393939393844505c6673808d99a6aea2988b7f7265594f4332281e130800000000000000000000000916222f3c4955626f7c8895a2afa4978a7e7c86929a96918c8784828181818285898e939aa1a9a8a0969083796d60574e42372b1f14090000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b989f9f998d8073665a4d4033271a0d0000000000000006101b242e373f4850575e61696e73777b7e80828484858686858583827f7d79756f6b625f5750483f372d231a0e0400000000000000000000000a16212c3740494f5353535353535d69768390908376695d5353535353534f4940372c21160a000000000000000000020a131c242c323a41464d5254585f626568696b6c6c6c6c6b6a686663605c54544e47433c332d261d150c03000000000000000000000000000000000000000000000000000000000007121d28313c46505a606d7983909893939393928d82796d6053463a2d20130700000000000000000000000000000000000007131e2a35404952575960606060606060605a58524a40362c21180d04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b151f2a333c454d525a6164696e72747778787979787774726e69636059514b433931271d12070000000000000000000000000000000000000000000206090e121415181a1c1e1f1f20201f1e1d1b19161413100c070300000000000000000000000000000000000714212d3a4754606d7a8283838383838174675b4e414855626f7c8283838383827f7265584c3f3225190c00030f1b27323d464e575f686d79818c929fa3a0958e81756d62584e443a2f261b110800000000101c2936434f5c6976828f9083767171717171717171717171717171716d685e5246392d201307000a1723303d4a5663707d8993939393939393939393939393939393938f8276695c4f4336291c10000000000000000000000000000000000000000406070a0c0e1011121213131211100e0c0a07060400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1925303b4854606b7784919daaac9f93877b6e6153493f33272d2d2d3a4653606d7984919eabac9f92867a6d6054473d3221160c0100000000000000000000000916222f3c4955626f7c8895a2afa3978a7e839098938d847f7b777574747476797c81889297a1a9a89f958d80736a5f53473b30251a0e0200000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8b939393938d8073665a4d4033271a0d000000000000000009121c252e363e454d52575f62666a6e71737577787879797978777573706d67636059534d453e362d251b11080000000000000000000000000f1b27333e49525a5f60606060606069768390908376696060606060605f5a52493e33271b0f00000000000000000000010a121a202830363b4246484e5355585b5d5e5f5f5a61646c6c6c6c66635c52473d373127221b140b03000000000000000000000000000000000000000000000000000000000000010c161f2a343e45515c676e7b8586868686868686867a6e6154473b2e211408000000000000000000000000000000000000020d19242e3740474b4d53535353535353534d4c4740382f241a0f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000030613131313131313130d0c0a07020000000000000000000000000003060809131313131313130b0b090501000000000000000007121d27313c464e575e616c71777b7f8183848586858584817f7b76706b605d554b43392f23180c040000000000000000000000000000000000000000000000020608080b0e1011121313131211100f0c0a07060400000000000000000000000000000000000000000713202c3945525d686d767676767676746f64584c4047535f6a6f767676767676726d62564a3e3125180b0007131f2c38434e5860696e7a828e939ca4a2989183796d605b51463d32281d140a0000000000101c2936434f5c6976828f91837e7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7a6d6154473a2e211407000a1723303d4a5663707d868686868686868686868686868686868686868276695c4f4336291c1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008141e2c38444f5965727f8c98a3aea4998c7f73655b5044372b1f2a36414c5663707d8a97a1ada79b8e8174685d5245392c2013040000000000000000000000000916222f3c4955626f7c8895a2afa89b8e818e9593878079726e6969686768656c6f757d859297a2ada79f92877b6e62574d42362a1e110500000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000c1925323f4c5865727f8686868686868073665a4d4033271a0d0000000000000000000a131c242c333b42464d5355575f626466696a6b6b6c6c6c6b6a686663605d55544f47423c332d241b130900000000000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c7683909083766c6c6c6c6c6c6c6c645a4f43372b1e12000000000000000000000000080e161e252a30363a3c4347484b4e504a505b636c7079797979736e63574b3f32262017110a020000000000000000000000000000000000000000000000000000000000000000040d18222934404b555f696e78797979797979797976685e5246392d2014070000000000000000000000000000000000000007121c252e353b3f404646464646464646413f3c362f261d12080000000000000000000000000000000000000000000000000000000000000000000000000000000000060c101220202020202020201a1917130e0800000000000000000000040a0f13151620202020202020181715110c06000000000000000c18242f39434e585f696e767e83888c8e909192929291908e8b87827d746d675d554b40342920150a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004111d2935414c565d6069696969696967645c53483c434e585f6269696969696965625b51463a2e221609000915222e3b4854606a6f7b8490949ea5a49f92867c6e675d51493f342b20160b020000000000101c2936434f5c6976828f95918a8a8a8a8a8a8a8a8a8a8a8a8a8a8a897d7063564a3d3023170a000916222f3c4854606b70797979797979797979797979797979797979797670665a4e4135281c0f00000000000000000000000000000000000003080b0d0e13131313131313131313131313131313131313131313131313131313131313131311100e0a06000000000000000000000000000000000000000000000000000000000002101c27333d4754616d7a86929facab9e9184786c6053463a2f242d3946525e6875828f9ba9aca095897c6f63564c4135291d11040000000000000000000000000916222f3c4955626f7c8895a2afaa9e938e9393877e736d67615e575b5a535b60626b707c85929fa6afa3998e8175695e52463a2d20140800000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825313e4a56626d72797979797979736e63584b3f3226190c000000000000000000010a121a212930363c4247485761696b6c6c6c68605c5f5f5e5d5b595653514b48433d37312a211b1209010000000000000000000000000013202d3946535f6c767979797979797979839090837979797979797979766c5f5346392d201300000000000000000000000000050c13191f252a2d32373b3c3f444c545c606d727e868686868073665a4d4033271a0b060000000000000000000000000000000000000000000000000000000000000000000000060f18232f39434d575f616c6c6c6c6c6c6c6c6c6c5e564c41362a1e110500000000000000000000000000000000000000000a131c242a2f323339393939393939393433302b241d140b00000000000000000000000000000000000000000000000000000000000000000000000000000000030a11171c1f2d2d2d2d2d2d2d2d2726231f19120a0200000000000000070f161b1f22232d2d2d2d2d2d2d2524211d181109000000000004101d2935404b555f6a6e7b838a9095989b9c9a989898999c9b9a938f8981796d675c51453d32271b0f00000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1924303a444c52545c5c5c5c5c5c5b58534a41363c464e53555c5c5c5c5c5c585651493f34291e1206000916232f3c4956626f7c85919693939393928a7e716a5f554b40372d22190e04000000000000101c2936434f5c6976828f9393939393939393939393939393939393897d7063564a3d3023170a000713202c38444f5960636c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c69665e54493d3225190d0000000000000000000000000000000001080f14181a1b2020202020202020202020202020202020202020202020202020202020202020201e1d1a16110b04000000000000000000000000000000000000000000000000000000000b16202d3946525d6875818e9ba7aca096897c7063554b4135292e3a4754616d7a86929facaa9d9084776b6054443a2f24190d010000000000000000000000000916222f3c4955626f7c8895a2afafa59e9b958c7f736c605c55524d4e4e49505359606a717e8a949fabab9f92877b6e6154473b3025190e02000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000916222e3a46515b62656c6c6c6c6c6c66635c52473b2f23170a0000000000000000000000080f171f252a313744505d697378797979746d665e564e504f4c4a4745403938322b2620180f0900000000000000000000000000000013202d394653606c798686868686868686909494908686868686868686796c605346392d2013000000000000000000000000000002080d141a1e20262b343d454d565d666d747f87929892857b6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000000000000000007121d27313c454d53555f60606060606060605f524c443b3025190e020000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d2726241f19130b02000000000000000000000000000000000000000000000000000000000000000000000000000000030c151c23282c393939393939393933322f2a241c140a00000000000007101920272b2e2f3939393939393932312e29221b12090000000006131f2c3945515d676e7c8490959d9d9993908d8b8b8b8d8f92999f9c938e82796d60584e43372b1c110600000000000000000000000106090b0c0e06060300000000000000020405060605040200000000000002070a0c0d0b0b0905010000000000000000000000000008131e28323a4145475050505050504e4c4841382f343c4347485050505050504c4a463f372d23180d01000d1a2633404d59667380868686868686868680746c61574e43392f251b100700000000000000101c2936434f5c697682868686868686868686868686868686868686867d7063564a3d3023170a0004101c27333d474f5456606060606060606060606060606060606060605c5a544c42382c211509000000000000000000000000000000020b131a202427272d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2a2927221c150d0500000000000000000000000000000000000000000000000000000005111d2935414c56636f7c8995a0aca89b8e8174675d5145392c37434e5865727f8b99a3aea2988b7f7265594f4332281e1308000000000000000000000000000916222f3c4955626f7c8895a2afb7afa89d9083786d605a514b464241413f44464f58616c76828f9ca9afa3998c7f7266564c41362a1e1105000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000006121e29343f495156586060606060605a58524a40362a1f1307000000000000000000000000050d141a1f263845525f6b788586868681786d685f584f47403d3a38352f2c27211a150e060000000000000000000000000000000013202d394653606c798693939393939393969696969393939393939386796c605346392d201300000000000000000000000000000000050c151d2328363e464f575f686d78818c939993877d70695e52463a2d20140700000000000000000000000000000000000000000000000000000000000000000000000000010b151f2a333c4246485253535353535353535346413b32291e14080000000000000000000000000000000000000000000000070d1316191a20202020202020201a1a17130e0801000000000000000000000000000000000000000000000000000000000000000000000000000000000a151e262e34384646464646464646403f3b362e261c120800000000040f19222b32383b3c464646464646463e3d3a342d241b1106000004111d2935414c55606d798391969f9b938e8783807f7e7f8082878f949e9d948e81746a605447382e23170b00000000000000000000070d121618191b13120f0b06000608080c0e1112131312110f0c09080603080e1317191a181715110c06000000000000000000000000020c1620283035393a43434343434341403c362f262a32373b3c4343434343433f3e3a342d251b110700000c1925323f4b57636d737979797979797979746e645a50453c31281d120900000000000000000f1c2835414e5a66707679797979797979797979797979797979797979706b6054483c2f22160900000b16212b353d44484a535353535353535353535353535353535353534f4e49423a30261b10050000000000000000000000000000010b141d252b3033343939393939393939393939393939393939393939393939393939393939393939393736332e271f170d040000000000000000000000000000000000000000000000000000010d1924303a4854606b7783909daaac9f92857a6d6054473c313b4754606a7783909dabac9f92867a6d6054473d3221160c01000000000000000000000000000916222f3c4955626f7c8895a2afb9ada1968a7d70665c5045403936302d33373d46505a63707d8a97a1adab9d908377685e5246392d201407000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000d1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000010d18232d373f464a4c5353535353534d4b4740382e24190e020000000000000000000000000002090e1926323f4c5965727f8c93938e827a6f6a6159514440393029241d1b160e0903000000000000000000000000000000000013202d394653606c798693928d89898989898989898989898989898986796c605346392d2013000000000000000000000000000000060e161e272e344048505960696e7a828e939f948c7f736b60574d42362a1e11050000000000000000000000000000000000000000000000000000000000000000000000000000030d18212a31373a3b4546464646464646463b3936302920170d0200000000000000000000000000000000000000000000000002070a0c0d13131313131313130e0d0b0703000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c2630383f4453535353535353534d4b4740382e24190e020000000a16202b343d434749535353535353534b4a453f362d22180c01000613202c3945515d6773808d95a09b918c817b767372717273767b828f939e9f93877c6f62544a3f34281c100300000000000000010911181e22252628201f1c17110e121415181b1e1e1f201f1e1c191615130f12191f2326272524211d181109000000000000000000000000040e161e24292c2d3636363636363433302b251d20262b2e2f36363636363632312e29231b13090000000a16232f3b47525b63666c6c6c6c6c6c6c6c67645c52483e332a1f160c0000000000000000000d1925323d49545e66696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6360594f44382c2013070000050f19232b33383c3d4646464646464646464646464646464646464643413d3830281e140a00000000000000000000000000000008131d262f363c404146464646464646464646464646464646464646464646464646464646464646464644423f3931291f150b00000000000000000000000000000000000000000000000000000008131e2c38434f5965727f8b98a2aea2988b7e7165574d4237404b55626f7c8895a0aca79b8e8174685d5245392c20130400000000000000000000000000000916222f3c4955626f7c8895a2afb7ab9e9184786c60544a3f342e2a2522272b343e4653606c7885919eabac9f93877a6e6154473b2e211408000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000002090e1a2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000007111b252d343a3e3f464646464646403f3b362e261c1208000000000000000000000000000000000b1825313e4a56626d75818f969490847c706b625b514a423a322a211911060000000000000000000000000000000000000013202d394653606c7986938d807d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7063564a3d3023170a0000000000000000000000000000070f18202830394045525a616b6f7b838f949d968f82776c60594f453b30251a0e02000000000000000000000000000000000000000000000000000000000000000000000000000000060f181f262b2d2e3939393939393939392e2d2a251e170e050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c17232e38424a505f606060606060605a58524a40362a1f13070000030f1b27323d464e545660606060606060585650483f34291d1105000714212d3a4754606d7a85929f9e948c7f746e696765656566696e78818f98a39a8e8175665c5044382b1f12060000000000000009131b23292e3132352d2b28221c1a1e212225282a2b2c2c2b2a282622221f1b1c242a2f323332312e29221b1209000000000000000000000000040c13191d2021292929292929282724201a13151b1f21222929292929292525221e1811090100000007131e2a35404952575960606060606060605a58524a40362c21180d040000000000000000000915212c38424c545a5c6060606060606060606060606060606060606056544f473d33271c100400000008111921272c2f30393939393939393939393939393939393939393635322c261e160c020000000000000000000000000000030f1a252f3841484c4e535353535353535353535353535353535353535353535353535353535353535353514f4a433b31271c11060000000000000000000000000000000000000000000000000000020f1b27323d4754606d7a86929facaa9c908376695f53473845515c6774808d9aa7aca095897c6f63564c4135291d110400000000000000000000000000000916222f3c4955626f7c8895a2afb6ac9a8d8073665b5042382e231d1a171b222b3744505b6574818e9ba7afa49a8a7e7164574b3e31241807000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000040a0f141a1e2633404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000009131b23292e313239393939393933322f2a241c140a00000000000000000000000000000000000916222e3a46515b606d7a8491989691867d726d605c544c443c332b2317110a02000000000000000000000000000000000013202d394653606c7986938b7e727070707070707070707070707070706b6054483c2f22160900000000000000000000000000071019212a323a434b515b636c717d8591959f9991847a6d655b50473d33291f14090000000000000000000000000000000000000000000000000000000000000000000000000000000000060e141a1e21222c2d2d2d2d2d2d2d2d21201e19140d05000000000000000000000000000000000000000000000000000000000000000000000000000000000001070b0f1112131313131313130a090704000001070b0f1112131313131313130a0907040000000000000003101c28343f4a545c6c6c6c6c6c6c6c6c66635c52473b2f23170a000006131f2b38434e5860626c6c6c6c6c6c6c65625a50453a2e211509000b1825323e4b5865717e8b989e9c8f82756d615e57585858575e666e7b86929f9e9285786d6053463a2d20130700000000000009121b252d353a3e3f413938332d26262b2e2f323537383939383735322f2e2b27262e353b3f403e3d3a342d241b120900000000000000000000000002080d1113141d1d1d1d1d1d1b1a18140f080a0f1215151d1d1d1d1d1d191816120d070000000000020d19242e3740474b4d53535353535353534d4c4740382f241a0f060000000000000000000005101b26303a42494e4f535353535353535353535353535353535353534a48443d352b21160b0000000000080f161c2022232d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d292825211b140c040000000000000000000000000000000814202b36414a53585a6060606060606060606060606060606060606060606060606060606060606060605d5b554d43392e22160a0000000000000000000000000000000000000000000000000000000a16202c3945515d6774818e9aa7ab9f94887b6e62544a3f4653606d7985929fabaa9d9084776b6054443a3024190d0100000000000000000000000000000916222f3c4955626f7c8895a2afafa49a897d7063544a3f30261c120e0b0f1b27333f495364717e8b97abb5ac9a8d8073675a4d402e23180c000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000000000000002080d161b1f252a2d33404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000010911181e2225252d2d2d2d2d2d2726231f19120a02000000000000000000000000000000000006121e29353f45525d686f7c86929f9892877f746d665d564d453d3528231c140c030000000000000000000000000000000013202d394653606c7986938b7e7265636363636363636363636363636360594f44382c201307000000000000000000000000040f19222b333c444c555c606d737e869297a09f92877c6f685d53493f352b20170d0200000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e1214151f20202020202020201414110e08020000000000000000000000000000000000000000000000000000000000000000000000000000000000050c12171b1e1f20202020202020171613100b050c12171b1e1f20202020202020171613100b05000000000006121f2c3844505c667679797979797979736e63584b3f3226190c00000815222e3b4754606a6f79797979797979716c62564a3d3124170b000e1b2835414e5b6874818e909192897c6f635b524d4c4b4c4d545e6976828f9ca297887b6e6155483b2e221508000000000009121b252d373f464a4c4e46443f382f31373a3b3f41444546464544423f3c3b37322c3840474b4d4b4a453f362d241a120800000000000000000000000000010407071010101010100e0d0b08030000030608091010101010100c0b0906010000000000000007121c252e353b3f404646464646464646413f3c362f261d12080000000000000000000000000a141e2830383d4143464646464646464646464646464646464646463d3c38332b23190f05000000000000050b10131617202020202020202020202020202020202020201c1c1915100a02000000000000000000000000000000000b1824303c48535c64676c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a675f554a3f33271a0e00000000000000000000000000000000000000000000000000000004111d2935414c55626f7c88959faba6998d8073665c50444d5764717e8a97a2ada2988b7f7265594f4332281e13080000000000000000000000000000000916222f3c4955626f7c8895a2afac9f93867a6d6053473a2d20140a00000b17222d3c4855626f7b8899a4afa99c8f837669554b4034281c10040000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000050c131921272c30363a3b404d596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000070d121618192020202020201a1917130e0800000000000000000000000000000000000000010d18232935414c565f6a727e8b939e99938c81786d685f574f473f342e261e150c0300000000000000000000000000000013202d394653606c7986938b7e72655856565656565656565656565656544f473d33271c10040000000000000000000000000a16212b343d454d565e676d757f8a9298a19e938b7f726a60564c41382d23190e050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205070812131313131313131308070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f171e23282a2b2d2d2d2d2d2d2d2322201c160f171e23282a2b2d2d2d2d2d2d2d2322201c160f08000000000713202d3a4653606d78868686868686868073665a4d4033271a0d00000916232f3c4956626f7c868686868686867e7165584b3e3225180b000c1926323f4c5965727f8283848586786d605346423f3e3f424d576773808d9aa995897c6f6256493c2f2316090000000008121b242d373f495157595b53504a42383c4247484b4e5151525352514f4c4947433c39404a52585a585650483f362c241a1108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a131c242a2f323339393939393939393433302b241d140b00000000000000000000000000020c161e262c32353639393939393939393939393939393939393939302f2c27211911080000000000000000000407090a13131313131313131313131313131313131313100f0d09050000000000000000000000000000000000000d1a2733404c58646e747979797979797979797979797979797979797979797979797979797979797979797771675b4f4236291d10000000000000000000000000000000000000000000000000000000010d19242f3a47545f6a7783909da9ab9e9184796d605346525e6976828f9ca9ac9f92867a6d6054473d3221160c020000000000000000000000000000000916222f3c4955626f7c8895a2afaa9e918477675d5145392c20130200000613202d3a4653606d7986939facab9e918478675c5145382c1f13060000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000000000070e171e252a32383b4246474b4e596673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000070d121618192020202020201a1917130e080000000000000000000000000000000000000000070d19242f3a434e58626d75818e95a09f928e827a6e69605951443f3830271e150b00000000000000000000000000000013202d394653606c7986938b7e7265584b4a4a4a4a4a4a4a4a4a4a4a4a48443d352b21160b000000000000000000000000030f1b27323d464e575f686d79818c929fa3a0958e81756d62584e443a2f261b11080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f1821282f34373839393939393939302f2c27211921282f34373839393939393939302f2c27211911080000000713202d3a4653606d798693939393938d8073665a4d4033271a0d00000916232f3c4956626f7c8993939393938b7e7165584b3e3225180b000c1825313e4a57636d7275767778796d665c5044383030363f4c5966727f8c99ab96897d7063564a3d3023170a000000040d1a242d363f49515b626568605b544a45464d5355585b5d5e5f5f5e5d5b5955544e47454a525c636665625a50483e362c231a0d0400000000000000000003060809131313131313131313131313131313131313131313131313130b0a0804000000000000000000010a12191e2325262d2d2d2d2d2d2d2d2726241f19130b020000000000000000000000000000040c141b212528292d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2322201c160f0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1b2734414e5a67748186868686868686868686868686868686868686868686868686868686868686868683776a5d5144372a1e110000000000000000000000000000000000000000000000000000000008131e2b37434e5865717e8b97a2ada1968a7d7063564c54616e7b87939faca79b8e8174685d5245392c201304000000000000000000000000000000000916222f3c4955626f7c8895a2afa89c8f827569554b4035291d1104000006131f2c3845515c677884919eabac9f9386796d6053463a2d2013070000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000000071019202930363d44484d5254575b5d6673808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000010911181e2225252d2d2d2d2d2d2726231f19120a020000000000000000000000000000000000000008131e28313c46515b606d79839198a29d948f847b706b625b504a423930271d1207000000000000000000000000000013202d394653606c7986938b7e7265584b3f3d3d3d3d3d3d3d3d3d3d3d3c38332b23190f0500000000000000000000000007131f2c38434e5860696e7a828e939ca4a2989183796d605b51463d32281d140a0000000000000000000000000000000000000000000002070c0f11121313131313131313131313131313131313131313131313131313131313131313131313131308070502000000000000000000000001070b0f1112131313131313130a09070400000000000000010c17212a333a404345464646464646463d3c38332b232a333a404345464646464646463d3c38332b23190f0500000713202d3a4653606d7986939f9f9f998d8073665a4d4033271a0d00000916232f3c4956626f7c89959f9f9f988b7e7165584b3e3225180b000916222e3a46515b636568696b676d675c544a3f41414142464e586673808d99a399887c6f6255493c2f2216090000010c161f2c363f48515b626d72746c665b545153575f6265686a6b6c6c6b6a68656260585452525c636e73716c625a50483e352c1f160c01000000000000040a0f12151520202020202020202020202020202020202020202020202020171714110c05000000000000000000070d1316191a20202020202020201a1a17130e080100000000000000000000000000000000020a1015191c1c20202020202020202020202020202020202020171613100b05000000000000000000000000000000000000000003090d1012131313131313130e0d0b080300000000000000000000000000000000000000000e1b2734414e5a6774818d939393939393939393939393939393939393939393939393939393939393939083776a5d5144372a1e1100000000000000000000000000000000000000000000000000000000010f1b26323c4753606d7985929faba99b8e8275685d525966737f8c99a4aca095897c6f63564c4135291d1104000000000000000000000000000000000916222f3c4955626f7c8895a2afa79a8d8174675a4e412f24180d01000004101c2834404b556a7683909da9afa49a887b6e6155483b2e2215080000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000061019222b323a41464f54575e6164676a6b73808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000009131b23292e313239393939393933322f2a241c140a00000000000000000000000000000000000000010c161f2a343f45515d676e7c86929fa59f9691857d726d605c544b42392e23180c000000000000000000000000000013202d394653606c7986938b7e7265584b3f3d3d3d3d3d3d3d3d3d3d3d3c39332c231a10050000000000000000000000000915222e3b4854606a6f7b8490949ea5a49f92867c6e675d51493f342b20160b02000000000000000000000000000000000000000000060d13181c1e1f202020202020202020202020202020202020202020202020202020202020202020202020201514120e09030000000000000000050c12171b1e1f20202020202020171613100b05000000000007121e28333c454b5052535353535353534a48443d352b333c454b5052535353535353534a48443d352b21160b00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2aca4988b7e7165584b3e3225180b0006121e2a353f495157595b5d555c605c554b474e4e4e4e4d52575f6a76838f9c9f92867a6d6054473a2d211407000007131d28313e48505a626d727f81786c665b5c6064696e727477787979787775726f6a65605d5c636e73807e716c615a50473e31281e13080000000000060e151b1f21222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c17100800000000000000000002070a0c0d13131313131313130e0d0b0703000000000000000000000000000000000000000005090d0f10131313131313131313131313131313131313130a090704000000000000000000000000000000000000000000070e14191d1f202020202020201b1a17140e08010000000000000000000000000000000000000e1b2734414e5a6774818d9a9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9d9084776a5d5144372a1e1100000000000000000000000000000000000000000000000000000000000a151f2c3945515d6774808d9aa6ac9f92867a6d6154606b7784919eabaa9d9084776b6054443a3024190d01000000000000000000000000000000000916222f3c4955626f7c8895a2afa6998c807366594d4033261a07000000000c18232e424f5c6975828f9ca8b6ac95887c6f6255493c2f2216090000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000050e18222b343d444c52596063696e7174767778808c9996897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000007111b252d343a3e3f464646464646403f3b362e261c120800000000000000000000000000000000000000040d18222935404b555f6a717e8a939da7a09792877f746d665c544b4034281c10040000000000000000000000000013202d394653606c7986938b7e7265584b4a4a4a4a4a4a4a4a4a4a4a4a49443e362c22170b0000000000000000000000000916232f3c4956626f7c85919693939393928a7e716a5f554b40372d22190e04000000000000000000000000000000000000000000070f171e24282b2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d22211e1a140e06000000000000060f171e23282a2b2d2d2d2d2d2d2d2322201c160f08000000000b17232f3a454e565c5e6060606060606056544f473d333a454e565c5e6060606060606056544f473d33271c1004000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00010d18232d373f464a4c4f504b5153514c52545a5a5a5b575e61696f7c87929f9c8f8376675d5145392c20130600010d18242f3a43505a626c727f8b8e81786c66666d71767b7e81848485868584827f7c77726d68606e73808d877e716c61594f433a2f24190d0100000006101820262b2e2f3939393939393939393939393939393939393939393939393931302d28221a1208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000811191f25292b2c2d2d2d2d2d2d2726241f1a130b0200000000000000000000000000000000000e1b2734414e5a6774818d9aa7acacb2a9a19e9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9084776a5d5144372a1e11000000000000000000000000000000000000000000000000000000000004101d2935404b55626f7b88949faba3998b7e726557636f7c8996a0aca2988b7f7265594f4332281e130800000000000000000000000000000000000916222f3c4955626f7c8895a2afa5988b7f7265584c3f3225190c00000000071b2835424e5b6875818e9ba8b0a396897d7063564a3d3023170a0000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000020c16202a343d464e565e616b6f757b7e8183848587939f96897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000010d18232d373f464a4c5353535353534d4b4740382e24190e0200000000000000000000000000000000000000071018242f39434e58616c74818e95a0a9a299928b80786d665c5145382c1f13060000000000000000000000000013202d394653606c7986938b7e726558575757575757575757575757575550483e33281c100400000000000000000000000d1a2633404d59667380868686868686868680746c61574e43392f251b1007000000000000000000000000000000000000000000060f1921292f343738393939393939393939393939393939393939393939393939393939393939393939393939392e2d2b261f180f0600000000050f1821282f34373839393939393939302f2c27211911080000000f1b2834404b5660686b6c6c6c6c6c6c6c6360594f4438404b5660686b6c6c6c6c6c6c6c6360594f44382c201307000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000007111c252d353a3e3f42434045474c565d616767676869696e727b8491999e938a7d7063554b4135291d11040004111d2935404b55616c717e8893938e81786c70797e83888b8e9091929291908e8c88847f7a726d73808d9292877e716b61554c4135291d11040000040e18222a32373b3c464646464646464646464646464646464646464646464646463e3c39332c241a1005000000000000000000000000020608080c0b09060100000000000000000000000000000000000000000004080a0b0807050200000000000000000000000000000000000205070813131313131313130707050100000000000000000007111a232a313538393939393939393433302b241d140b01000000000000000000000000000000000e1b2734414e5a6774818d9aa9b3b9ada1979191919191919191919191919191919191919191919191919083776a5d5144372a1e110000000000000000000000000000000000000000000000000000000000000c18242f3947535f6a7683909ca9ab9d908376695f6774818e9aa8ac9f92867a6d6054473d3221160c0200000000000000000000000000000000000916222f3c4955626f7c8895a2afa5988b7e7265584b3f3225180c000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a0000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000008131e28323c464e5860686d767c82878a8e9091929399a496897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000006121e29343f495156586060606060605a58524a40362a1f1307000000000000000000000000000000000000000007121d28313c46505a606d7983909893939393928d82796d6053463a2d2013070000000000000000000000000013202d394653606c7986938b7e72656464646464646464646464646464615a5044392d20140800000000000000000000000c1925323f4b57636d737979797979797979746e645a50453c31281d1209000000000000000000000000000000000000000000020d17212b333b404445464646464646464646464646464646464646464646464646464646464646464646464646463b3a37312a21180e030000010c17212a333a404345464646464646463d3c38332b23190f050000111e2a3743505c68727879797979797979706b6054483c43505c68727879797979797979706b6054483c2f221609000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000a131c232a2e3132352f343946525d686d7474747475777b7f8591969e938e81746b6155433a2f24180d01000613202c3945515d67717e87939a9d938e81797d848b9095989b9d9e9f9f9e9d9b9895918c857f79808d929c9992877d70675d5145392c20130600000a15202a343c434748535353535353535353535353535353535353535353535353534a49453e362c22170c0000000000000000000003090e121415191815120d06000000000000000000000000000000000000050c111417171514120e09030000000000000000000000000002090e12141520202020202020201413110d0802000000000000030e19232c353c414546464646464646413f3c362f261d1308000000000000000000000000000000000e1a2734414d5a6774808d97a2adb8ab9e91858484848484848484848484848484848484848484848484848275685c4f4235291c0f00000000000000000000000000000000000000000000000000000000000007121d2b37434e5864717e8a97a1ab9f95887b6e616d7985929faba79b8e8174685d5245392c2013040000000000000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b0000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000010d1925303a444e58606a6f7a82898f94979a9d9e9f9fa4ab96897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d100000000000000000000916222e3a46515b62656c6c6c6c6c6c66635c52473b2f23170a0000000000000000000000000000000000000000010c161f2a343e45515c676e7b8586868686868686867a6e6154473b2e2114080000000000000000000000000013202d394653606c7986938b7e727070707070707070707070707070706c6155493c3023160a00000000000000000000000a16232f3b47525b63666c6c6c6c6c6c6c6c67645c52483e332a1f160c0000000000000000000000000000000000000000000007131e29333d454c5052535353535353535353535353535353535353535353535353535353535353535353535353534846423c332a1f1409000007121e28333c454b5052535353535353534a48443d352b21160b0000121f2b3845525e6b7884868686868686867d7063564a3d45525e6b7884868686868686867d7063564a3d3023170a000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000010a11181e22252628232e3a4754616d7a808181818284878c929796918b81796d60594f4431281d130700000714202d3a4753606d7a859297a2a59d938e848991969d9fa7a7aaa8a7a7a8aaa8a7a09d97928b858d929ca4a39892857a6d6054473a2d21140700030f1b26323c464e535560606060606060606060606060606060606060606060606060575550483e33281c11040000000000000000060e151a1e21222524221e181109010000000000000000000000000000000810171c21232422211e1a140d060000000000000000000000050d141a1e20212d2d2d2d2d2d2d2d21201d19130c05000000000009141f2a353e474d51535353535353534e4c4741382f241a0e030000000000000000000000000000000815212e3b4854616e7b85929ea4aea99d9083787777777777777777777777777777777777777777777777756f65594d4134281b0e000000000000000000000000000000000000000000000000000000000000010f1a26313c4653606d7985929eaca7998c7f7366717d8a98a2aca095897c6f63564c4135291d11040000000000000000000000000000000000000916222f3c4955626f7c8895a2afa4988b7e7165584b3e3225180b000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000005111d2a36414c565f6a6f7d848f949c9ea6a7a9aaabacafa296897c6f635649505c6976838f9c9286796c5f5346392c201306000000000000000000000000030a0f1d2a3643505d69768390908376695d5043362a1d0f0a03000000000000000b1825313e4a56626d72797979797979736e63584b3f3226190c000000000000000000000000000000000000000000040d18222934404b555f696e78797979797979797976685e5246392d2014070000000000000000000000000013202d394653606c7986938d807d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7e7064574a3d3124170a000000000000000000000007131e2a35404952575960606060606060605a58524a40362c21180d04000000000000000000000000000000000000000000000c18242f3b454f575d5f6060606060606060606060606060606060606060606060606060606060606060606060606055534d453c31261a0e02000b17232f3a454e565c5e6060606060606056544f473d33271c100400121f2b3845525e6b7885919393939393897d7063564a3d45525e6b7885919393939393897d7063564a3d3023170a000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000070d121618191c212e3b4854616e7b878d8d8e8f9193938f8d89847e756d675c51473e331f160c0100000613202c3945515d676f7c859298a2a59d9591959da0a8aba8a09d9b9a9a9b9d9fa4aca9a19e9691969ca4a39992867d70675d5145392c2013060006121f2b37434e585f626c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d21140800000000000000060f181f262b2e2f32312e29231b130a010000000000000000000000000008121a22282d30312e2d2a261f180f06000000000000000000050f171f252a2d2e39393939393939392e2d2a251e160e05000000010d1925313c4750585e5f6060606060605a58524a41362b1f14080000000000000000000000000000000714202d3a46525e69707d8a929da7ab9f958d80736b6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a68655d54493d3125190c000000000000000000000000000000000000000000000000000000000000000a151f2c3845515c6773808d9aa4aa9d9184776a75828e9baaaa9d9084776b6054443a3024190d010000000000000000000000000000000000000916222f3c4955626f7c8895a2afa5988b7e7265584b3f3225180c000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b0000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000713202d3946525e686f7c8691969ea6aab0b4b6b7b8b9afa296897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000000060e151a1f2a3643505d69768390908376695d5043362a1f1a150e060000000000000c1925323f4c5865727f8686868686868073665a4d4033271a0d00000000000000000000000000000000000000000000060f18232f39434d575f616c6c6c6c6c6c6c6c6c6c5e564c41362a1e11050000000000000000000000000013202d394653606c798693928d8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a86796c605346392d20130000000000000000000000020d19242e3740474b4d53535353535353534d4c4740382f241a0f0600000000000000000000000000000000000000000000000f1c2834404c5761686b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5f574d42372b1e1205000f1b2834404b5660686b6c6c6c6c6c6c6c6360594f44382c20130700121f2b3845525e6b7885919e9f9f9f96897d7063564a3d45525e6b7885919e9f9f9f96897d7063564a3d3023170a000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000000000106090c0c15212e3b4854616e7b87949a9b9c9e938682807d78716c605c554b40352c210d0400000004111d2935404b55606a6f7c869298a2a7a09da0a7a9a29f9996918f8e8d8e90939a9ea1a8a8a19ea1a8a39992877d706b60554c4135291d1104000815212e3b47535f6a7679797979797979797979797979797979797979797979797979716c6155493c3023170a000000000000060f18212a31373a3b3f3e3a342d251c130a01000000000000000000000008121a242c33393c3e3b3a36312921180f0500000000000000020d17212930363a3b4646464646464646463936302820160c02000004101d2935414d58626a6c6c6c6c6c6c6c67645c52473c3024170b00000000000000000000000000000005121e2a36424d57616c74808d95a0aaa79f93887d70685e545e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5c59544b42372c2115090000000000000000000000000000000000000000000000000000000000000004101c2834404b55616e7b87939faca095887b6f7985929faca3988b7f7265594f4332281e1308000000000000000000000000000000000000000916222f3c4955626f7c8895a2afa5988b7f7265584c3f3225190c000000010e1b2834414e5b6774818e9aa7b0a4978a7d7164574a3e3124170b0000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000005121e2a36424d57616d7a849198a1a8b0b7bbc1c3c4c5bcafa296897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000000006101820262b2e3643505d69768390908376695d5043362e2b262018100600000000000c1925323f4c5865727f8b939393938d8073665a4d4033271a0d000000000000000000000000000000000000000000000007121d27313c454d53555f60606060606060605f524c443b3025190e020000000000000000000000000013202d394653606c798693939393939393939393939393939393939386796c605346392d201300000000000000000000000007121c252e353b3f404646464646464646413f3c362f261d1208000000000000000000000000000000000000000000000000111e2b3744505d6873787979797979797979797979797979797979797979797979797979797979797979797979797976695f53463a2d21140700111e2a3743505c68727879797979797979706b6054483c2f22160900121f2b3845525e6b7885919eabaca396897d7063564a3d45525e6b7885919eabaca396897d7063564a3d3023170a000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000000000060b0f12131c212e3b4854616e7b8793939495989a9285817d756e685e574d43392e23180c00000000010d18242f3a434e58606a6f7d86929aa4acaaaca59d97928c88848281818283878b91969fa3ababadac9f92877d706b61594f433a2f24190d01000915222f3c4855626f7c868686868686868686868686868686868686868686868686867e7164574a3e3124170b0000000000050f18212a333c4247484c4a463f372e251c130a0100000000000000000008121a242c363e45494a4846423b332921170e0500000000000009141f29333b42464853535353535353535346413a32281e1308000005121f2b3845515e6a7479797979797979746e64584c3f33261a0d000000000000000000000000000000020e1a25303b454f59606d79839098a2aea49a92857a6e665b5051515151515151515151515151515151514f4d49423930261b100400000000000000000000000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9a7998c7f737d8a98a2ac9f92867a6d6054473d3221160c02000000000000000000000000000000000000000916222f3c4955626f7c8895a2afa6998c7f7366594c4033261907000000020f1b2835424e5b6875818e9ba8b0a3978a7d7064574a3d3124170a0000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000714212d3a46535f6974818e96a1aab2bac2c7ccd0d1c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c201306000000000000000000061018222a31373a3c43505d69768390908376695d50433c3a37312a22181006000000000c1925323f4c5865727f8b989f9f998d8073665a4d4033271a0d0000000000000000000000000000000000000000000000010b151f2a333c4246485253535353535353535346413b32291e1408000000000000000000000000000013202d394653606c798686868686868686868686868686868686868686796c605346392d2013000000000000000000000000000a131c242a2f323339393939393939393433302b241d140b00000000000000000000000000000000000000000000000000121f2c3845525f6b7885868686868686868686868686868686868686868686868686868686868686868686868686867b6e6155483b2e22150800121f2b3845525e6b7884868686868686867d7063564a3d3023170a00121f2b3845525e6b7885919eabaca396897d7063564a3d45525e6b7885919eabaca396897d7063564a3d3023170a000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000000020a11171c1f2028232e3b4854616e7b86868687898c9195928e89827a6e695e544a4034281c10040000000007131d28313d464e58606b6f7c87939facaba39f938e857f7b7775747475777a7e848c9299a2a9b3a4978a7e716b61594f473d31281e130800000916232f3c4956626f7c8993939393939393939393939393939393939393939393938a7d7164574a3e3124170b00000000050e172129333c454d5355585651493f372e251c130a010000000000000008121a242c363e4850555755534d453b332920170e0500000000020e1a25303b454d525f60606060606060605f524c443a3025190d01000613202c3946535f6c79868686868686868074675a4e4134271b0e0100000000000000000000000000000009141f29333e45515c676e7b86929fa5aca1978f82786c60594f4444444444444444444444444444444442413d3730271e140900000000000000000000000000000000000000000000000000000000000000000007121d2b37424d5764717d8a97a1aa9d908377818e9baaa79b8e8174685d5245392c20130400000000000000000000000000000000000000000916222f3c4955626f7c8895a2afa79a8d8174675a4e412e23180c000000030f1c2936424f5c6975828f9ca8afa296897c6f6356493c302316090000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000815222e3b4855616e7b87929fa8b2bcc4ccd3d7dcd5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000000060f18222a343c43474847505d69768390908376695d50474847433c342a22180f060000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000000000000000000030d18212a31373a3b4546464646464646463b3936302920170d02000000000000000000000000000013202d3946535f6c767979797979797979797979797979797979797979766c5f5346392d201300000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d2726241f19130b0200000000000000000000000000000000000000000000000000121f2c3845525f6b7885929393939393939393939393939393939393939393939393939393939393939393939393887b6e6155483b2e22150800121f2b3845525e6b7885919393939393897d7063564a3d3023170a00121f2b3845525e6b7885919e9f9f9f96897d7063564a3d45525e6b7885919e9f9f9f96897d7063564a3d3023170a000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000020b141c22282b2d352e343a46535e69767979797a7c7f848c9399948f847b6e665c5144382c1f150900000000010c161f2b343d45515d67717e8b9aa4afa399928b817a736e6968676768686e72797f879297a2aaa6998c7f73695f53463e352b1f160c010000091623303c4956636f7c89969f9fa8a19e9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c978a7d7164574a3e3124170b000000020b172029333b454d575f6265625b51493f372e251c130a01000000000008121a242c363e48505a6164615f574d453b322920170c0200000005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c5e564c41362a1d1105000613202c3946535f6c798692939393938d8174675a4e4134271b0e01000000000000000000000000000000030d17212834404b555f69717e8a939da8a99f948c7f736b60564c4135373737373737373737373737373534312c261e150c02000000000000000000000000000000000000000000000000000000000000000000000e1a26313c4653606d7984919eaba095887b85929faba095897c6f63564c4135291d110400000000000000000000000000000000000000000916222f3c4955626f7c8895a2afa89b8f827568544a4034281c1004000004101c2934404b556a7683909da9b4aa95887b6f6255483c2f2215090000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0006121e2b37424d576774818d99a3afbac4ced6dfe3e2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c20130600000000000000030e18212a343c464e535554525d69768390908376695d525455534e463c342a21180e0300000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000000000000000000000000000000000000000000060f181f262b2d2e3939393939393939392e2d2a251e170e05000000000000000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e12000000000000000000000000000000070d1316191a20202020202020201a1a17130e08010000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929e9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f94887b6e6155483b2e22150800121f2b3845525e6b7885919e9f9f9f96897d7063564a3d3023170a00121f2b3845525e6b7885919393939393897d7063564a3d45525e6b7885919393939393897d7063564a3d3023170a000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000a141d262d33383942434045464d575e6c6c666d6d6f72787f87939f969083786d6053463c31261a0e0200000000040f1b27333f4953606d7984919eaca49f92877f746d68615f575b5a565e61676d727d859298a2ac9f92867b6e61564c41362a1e11050000000a1623303d495663707c899aa4aca196918f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8a7d7164574a3e3124170b0000000a141d29323b454d575f696e726d635b51493f372d251c130a0100000008121a242c363e48505a616c716e695f574d443b32291e140a0000000714202d3a46525e6976797979797979797976685e5246392d201307000613202c3946535f6c7986929f9f9f9a8d8174675a4e4134271b0e0100000000000000000000000000000000050f18232e39434d57616c74818e95a0aaa69f92877d6f685d52463f342a2b2b2b2b2b2b2b2b2b2b2b292825211b140c03000000000000000000000000000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a4a79c8f828f97a2aa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000916222f3c4955626f7c8895a2afaa9d908477665c5144382c1f1206000006131f2c3845515c677884919eabaea298877a6d6154473a2e2114070000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000814212d3a47535f697884919eabb5c0ccd6e0e8f1e2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000009151f2a333c464e585f62615e566976839090837669565e61625f584e463c332a1f150900000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000000000000000000000000000000000000000000000060e141a1e21222c2d2d2d2d2d2d2d2d21201e19140d05000000000000000000000000000000000f1b27333e49525a5f60606060606060606060606060606060606060605f5a52493e33271b0f0000000000000000000000000000000002070a0c0d13131313131313130e0d0b070300000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eabacacaea9a7a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a194887b6e6155483b2e22150800121f2b3845525e6b7885919eabaca396897d7063564a3d3023170a00121f2b3845525e6b7884868686868686867d7063564a3d45525e6b7884868686868686867d7063564a3d3023170a000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000006111c262f383f44464f504b51535452535f605c606162666c727f8b95a0958c7f7265574e42372b1e12060000000005121f2b3744505b65727f8c97a1a89c928a7e726d615d56534d4e4e4c52555c606b707c86929fa6a3988e8175685e5246392d2014070000000815222f3b4855626e7b87939fa99e91848383838383838383838383838383838383827d706356493d3023160a000006111b262f3b444d575f696e7b7f726d635b51493f372d251c130a010008121a242c363e48505a616c717d7b6e695e564d443a30261c110600000815212e3b4854616e7b86868686868686867a6d6154473a2e211407000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000007121d27303c45505a606d79839198a3aea39991847a6d615b51463c31281d1e1e1e1e1e1e1e1e1e1c1b191510090200000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87939fac9e948f949ea9a3988b7f7265594f4332281e13080000000000000000000000000000000000000000000916222f3c4955626f7c8895a2afac9f9286796d6053463a2d20130900000714202d3a4753606d7a86939facac9f928579685e5246392d2013070000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000815222e3b4855616e7b8896a1adbdc7d1dee8f2efe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c201306000000000000020e1a26313c454e585f6a6f6d685e69768390908376695e686d6f6a5f584e453c31261a0e02000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000000000000000000000000000000000000000000000003090e1214151f20202020202020201414110e080200000000000000000000000000000000000a16212c3740494f535353535353535353535353535353535353535353534f4940372c21160a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eabb8aea49d9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a94887b6e6155483b2e22150800121f2b3845525e6b7885919eabaca396897d7063564a3d3023170a00111e2a3743505c68727879797979797979706b6054483c43505c68727879797979797979706b6054483c2f221609000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000b17222d38424a50535b5d555c60605d564c4a505354545b606c7883909d9e9184786a5f53473a2e211408000000000613202d394653606c7884919ea9a0968d80736c625b524c4642414141464b5159606a717e8a939eaa9f92867a6e6154473b2f24180c0000000814212e3a47535f6975818e97a29d9084787676767676767676767676767676767676706b6054483b2f22160900000b17222d38414d565e696e7b848b7f726d635b51493f372d251b130a08121a242c363e48505a616c717e86847b6e695e564c42382e23170b00000815212e3b4854616e7b87939393939393877a6d6154473a2e211407000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e010000000000000000000000000000000000000b151e2a333e45515d676f7c86929fa5aba1968f82756d62584e433a2f24180f111111111111110f0e0c09040000000000000000000000000000000000000000000000000000000000000000000000000000000c17232e3846535e6975828f9ca8a69e9c9ea6ac9f92867a6d6054473d3221160c020000000000000000000000000000000000000000000916222f3c4955626f7c8895a2afaea399887c6f6255493c31261a0d06030615222f3c4855626f7b8899a4afaa9d9084776a564c41362a1e11050000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000b1825313e4b5864717e8b97a8b2bdcfd9e3f0faefe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c20130600000000000006121e2b37424d575f6a6f7b7a6d686976839090837669686d7a7b6f6a5f574d42372b1e1206000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000000000000000000000000000002050708121313131313131313080705020000000000000000000000000000000000000005101b252e373e4346464646464646464646464646464646464646464646433e372e251b10050000000000000000000000000000000000000003080b0e0e131313131313130a090704000000000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eabb8a99d928d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d887b6e6155483b2e22150800121f2b3845525e6b7885919e9f9f9f96897d7063564a3d3023170a000f1b2834404b5660686b6c6c6c6c6c6c6c6360594f4438404b5660686b6c6c6c6c6c6c6c6360594f44382c201307000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00030f1c28333f4a545b6068696b676d6d685d52454446474a505b6573808c99a196887b6e6255483b2f221508000000000a1623303d495663707d8996a0a99e9184786d605a5146413a373130363940454f58616c75828f99a3a3998c7f7266554b4035291d1004000006121e2b37424d57616e7b85929fa0958c80736c6969696969696969696969696969696360594f44382c20130700030f1b27333f49535e696e7b8491918c7f726d635b51493f372d251b13121a242c363e48505a616c717e879291847b6e685e544a3f34281c1003000815212e3b4854616e7b87949f9f9f9f94877a6d6154473a2e211407000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000000030c18212935404b555f6a727f8b939ea8a89e948b7f726a5f554b41352921180d030404040404020200000000000000000000000000000000000000000000000000000000000000000000000000000001070c06111c2a36424d5763707d8a96a1acaaa8aab0a79b8e8174685d5245392c201304000000000000000000000000000000000000000000000916222f3c4955626f7c8895a2afb5ab998c7f7266574d42372b1f15120f121c2834404a5465717e8b98abb5a89b8e8175685b4e423025190d010000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000d192633404c5966737f8c99a6b2bfcfd9eaf5ffefe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000814212d3a47535f696f7c85837a6d68768390908376686d7a83857c6f695f53473a2d211408000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131c252c33373939393939393939393939393939393939393939393937332c251c130900000000000000000000000000000000000001080f14181a1b20202020202020171614100b0500000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eabb4a79a8d8080808080808080808080808080808080808080808080808080808080807a6d6154473a2e21140700121f2b3845525e6b7885919393939393897d7063564a3d3023170a000b17232f3a454e565c5e6060606060606056544f473d333a454e565c5e6060606060606056544f473d33271c1004000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0006121f2b3844505b666c75767778797a6d60544b403a3a3f495364717e8b97a8978a7d7164574a3e3124170b00000003101c28343f4a546773808d9aa8a2978a7e71665c51483f35302b26252a2e343d46505a626e7b87929fab9d908376675d5145382c1f13060000020e1a26313c46525e68717e8a929c9f93887e716c605b535c5c5c5c5c5c5c5c5c5c5c56544f473d32271b10030005121f2b3744505b656e7b8491969c918c7f726d635b51493f372d251b1a242c363e48505a616c717e8792999691837a6d665c5044382b1f1206000815212e3b4854616e7b8794a1acaca094877a6d6154473a2e211407000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000060f18242f39434e58626d75818e96a1aba69f92867c6f675d51453f332a1f150b010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050c13181b1e1a25313b4653606c7884919e9f9f9f9f9fa095897c6f63564c4135291d1104000000000000000000000000000000000000000000000916222f3c4955626f7c8895a2afb6a99c908376695f53473c3127201f1c1f232c3844515c6675818e9ba8b3a9988c7f7265594c3f32261908000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000d1a2734404d5a6773808d9aa6b3c0cdd9e6f3fcefe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000815222e3b4855616e7b859290837a6d7683909083766d7a839092857b6e6155483b2e221508000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000000000000000000000000000000000000000000010406070a0d101112131312100e0b080705020000000000000000000000000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b27211b130a010000000000000000000000000000000000020b131a202427282d2d2d2d2d2d2d2323201c160f08000000000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a73737373737373737373737373737373737373737373737373737373736d685e5246392d20130700121f2b3845525e6b7884868686868686867d7063564a3d3023170a0007121e28333c454b5052535353535353534a48443d352b333c454b5052535353535353534a48443d352b21160b00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000613202d394653606c7881838485868275665c5145403f414a5464717e8b97a4988b7e7165584b3e3225180b00000006121f2b3844505c667683909da99f9285796d60544a403629241e1a191d2328343e47535f6a7683909ca99f92867a6d6053473a2d2014070000000915202a36414d56616c73808d939d9a92877e736c655d554e5050505050505050504948443d352b21160b00000613202d394653606c79839096a0a39c918c7f726d635b51493f372d25242c363e48505a616c717e879299a3a0959083796d6053463a2d201307000815212e3b4854616e7b8794a1acaca094877a6d6154473a2e211407000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000000000007121d28313c46515b606d7a849199a3aea3999184796d605a50463c31271d120700000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f171e23282a2b2d2b3844505b66737f8c999393939393939084776b6054443a302419120b030000000000000000000000000000000000000000000916222f3c4955626f7c8895a2afb7ab9f94887b6e62574e4339312d2b282b2e343f4953606d7985929fabada297897c6f6356493c30231609000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000e1b2835414e5b6874818e9ba7b4c1cedae7f4fcefe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c2013060000000000000713202d3a4653606d78818e9390837a7683909083767a8390938e81786d6053463a2d201307000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000000020608080d0606030000000000000000000000000000000104080d111314171a1d1e1f201f1f1d1b181414110e080200000000000000000000000000010910161b1e202020202020202020202020202020202020202020201e1b161009010000000000000000000000000000000000010b141d252b30333439393939393939302f2c27211a11080000000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e67676767676767676767676767676767676767676767676767676767615e564c4135291d110500111e2a3743505c68727879797979797979706b6054483c2f22160900010c17212a333b434a4f5053535353534c4a463f372d232a333b434a4f5053535353534c4a463f372d23190f0500000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0006121f2b3844505b6677849091929285796d6058514a4c4b515b6673808d99a9978a7d7164574a3e3124170b0000000713202d3a4653606d7986929fa89b8e8175665c5042392e2419130e0d1218222b37434e5866727f8c99a5a399897c6f6356493c30231609000000030e1925303b44505a606c77818e939c99928b80776d675f585045414343434343433d3b38322b23190f04000005121f2b3744505b65707d869298a2a39c918c7f726d625b51493f372d2c363e48505a616c717e879299a3a39992877e71665c5044382b1f1206000815212e3b4854616e7b87949f9f9f9f94877a6d6154473a2e211407000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e010000000000000000000000000000000000000000010c161f2a343f45525d686f7c87929fa6aba0968e81756c62584e43392f24180f060000000000000000000000000000000000000000000000000000000000000000000000000000000000050f1821292f3437383939333f4a54616e7a8786868686868686867f7265594f43322c29231d150d0700000000000000000000000000000000000000000916222f3c4955626f7c8895a2afbdb0a69a8d81746a5f554b433c39383338393f44505b65717e8a97a2adab9f9285796d6053463a2d201307000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000e1b2835414e5b6874818e9ba7b4c1cedae7f4fcefe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c20130600000000000006121f2c3844505c666d78818e9390837a839090837a8390938e81786d665c5044382c1f1206000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000003090e1214151913120f0b06000000000000000000000003070d1013191d202124272a2b2c2d2c2b2a282521201e19140f0a0400000000000000000000000000050a0f1213131313131313131313131313131313131313131313120f0a050000000000000000000000000000000000000008131d262f363c4041464646464646463d3c38332c231a0f0500000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e615a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a54524c443a3025190d01000f1b2834404b5660686b6c6c6c6c6c6c6c6360594f44382c20130700000a16222e39434d555b5d6060606060585651493f34292e39434d555b5d6060606060585651493f34291e120600000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00030f1c28333f4a546774818e9a9f978b7e716a605c5459555d606c7884919da297897c6f6356493c302316090000000714212e3a4754616d7a8798a3a5988b7f7265544a3f30271c1208020007101a26313d495663707c8996a3ab978a7d7164574a3e3124170b0000000008141f29323e44505b656c78818d929f9f928c81796f6a625a514c433c34363636302f2c2721191107000000030f1b27333f4953606b707d869298a2a39c918c7f726d625b51493f37363e48505a616c717e879299a3a39992877e716c61544a3f34281c1003000815212e3b4854616e7b87939393939393877a6d6154473a2e211407000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000000000000040d18222935414c56606a727f8c949fa9a89e938b7e716a5f554b40352921170c03000000000000000000000000000000000000000000000000000000000000000000000000000000010c17212a333a4044454646463a46525e686e797979797979797979726d6256473f3a38342f271f191007000000000000000000000000000000000000000916222f3c4955626f7c8895a2afb4aba39f92877b6e675d554e4846443f44464a5059606c7883909da9b1a89b8e8175665c5044382b1f1206000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000e1b2734414e5a6774818d9aa7b4c0cddae7f6ffefe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c20130600000000000003101c28343f4a545c666d78818e939084839191838490938e81786d665c544a3f34281c1003000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000060e151a1e212226201f1c17110a0200000000000003060c1012181d2024292c2d30343638393939383735322e2d2a251e1b150d08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1a252f3841484c4e535353535353534a48443d352c21160b00000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e61544d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4746413a32281e130800000b17232f3a454e565c5e6060606060606056544f473d33271c100400010e1a27333f4a555f676a6c6c6c6c6c65625b51463a2e333f4a555f676a6c6c6c6c6c65625b51463a2e22160900000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000b17222d3c4956626f7c89949f9f92857c716d66666666676d737f8c96a09f9285796d6053463a2d2013070000000815222f3b4855626e7b8895aaa4978a7d7164574a3e2e24150b000000000915222f3b4855626e7b8895a1a5988b7e7265584b3f3225180c00000000020d172027333f49535b666c74808b92989c938f847c716c605d554e463e362e292322201b160f0700000000000b17222d38414f59606b707d869298a2a39b918c7f726d625b51493f3e48505a616c717e879299a3a39992877e716c615a5042382e23170b00000815212e3b4854616e7b86868686868686867a6d6154473a2e211407000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000061019242f3a444e58606c77828f97a1aba59f92867c6e675d51453e33291e150b00000000000000000000000000000000000000000000000000000000000000000000000000000007131e29333c454c505253535246444d565e616c6c6c6c6c6c6c6c6c65625b51504c47454039312a221910060000000000000000000000000000000000000916222f3c4955626f7c8895a2afaea39992999083796d6760585553504a5053545c606b727f8b95a0acaca095897d7063544a3f34281c1003000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000d192633404c5966737f8c99a6b2bfced9e5f1feefe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c201300000000000000000c17232e38424a545c666c78818e92909195959191928d81786c665c544a42382e23170c00000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000060f181f262b2d2e332d2b28221c140b08060406060b0f12171c1f24292c2f35393a3d4043444546464543413e3b3936302b272019130c04000000000000000000000000000000000000000000050a0d0f101313100f0d0a05000000000000000000000000000000000000000000000000000814202b36414b53595b6060606060606056554f473d33271c1004000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e615447404040404040404040404040404040404040404040404040403a3935302820160c02000007121e28333c454b5052535353535353534a48443d352b21160b000003101d2936424f5b6771777979797979726d62564a3e3136424f5b6771777979797979726d62564a3e3124180b00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000615222e3b4754606a76828f98a29792857e7975737273757a8088939fa1978d8074665c5144382c1f12060000000916222f3c4955626f7c8895a2a396897d7063564a3d30231706000000000714212e3a4754616d7a8794a0a5998c7f7266594c3f3326190c0000000000050e17222d38414a545b606e737e8691969e9691867e756d675f58504840372e261c13100b0400000000000006111b262f3d474f59606b707d869298a2a39b918c7f726d625b514948505a616c717e879299a3a39992877e716c615a50483e30261c110600000714202d3a46525e6976797979797979797976685e5246392d201307000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000000000000000008131e28323d44505b656d7a859199a4aea2989083796d605a50453b30271c120700000000000000000000000000000000000000000000000000000000000000000000000000000c18232f3a454f575c5e60605f53504a4d52545f60606060606060605c5e5f5f5c5853514b433c342a22180c0200000000000000000000000000000000000916222f3c4955626f7c8895a2afac9f928692958f81796f6a6462605b545b6062666d727d87929fa7b0a69d9184786c605346392e23170b00000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000b1824313e4b5764717e8a97a8b2bdc8d4e2edf8efe2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c20110c0600000000000006111c263038424a545b666c77808d929da0a09d928d80776c665b544a423830261c110600000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000030e18212a31373a3b403938332d261d191312101314171c1f23282c2f35393a4145474a4d505152535252504e4b4746413b373229241e160e05000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a0300000000000000000000000000000000000000000000000b1824303c48535d64676c6c6c6c6c6c6c6360594f44382c201407000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b3434343434343434343434343434343434343434343434342e2d29251e160e04000000010c17212a333b434a4f5053535353534c4a463f372d23190f05000004111d2a3744505d6a778386868686867f7265584c3f323744505d6a778386868686867f7265584c3f3225190c00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000006131f2b37434e58616e7b869298a097928b8582807f8082858d939aa19892857a6d61544a4034281c10040000000815222e3b4855616e7b8894aaa4978a7d7164574a3e2d22170b000000000815222f3b4855626e7b8895a1a5988b7e7265584b3f3225180c00000000000006111b262f38424a505c636c717c848e939f98928b817a6f6a625a524940382e251c110800000000000000000a141d2b353d474f59606b707d869298a2a39b918c7f726d625b51505a616c717e879299a3a39992877e716c615a50483e362c1e140a00000005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c5e564c41362a1d1105000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e010000000000000000000000000000000000000000000000010c162027333f49535e68707d87939fa6aaa0958d81746c61574d42392e23180e05000000000000000000000000000000000000000000000000000000000000000000000000030f1b2834404c5761686b6c6c6c605c544a46475353534c52565d6065696b6c6b6965605c554e463c342a1e140a00000000000000000000000000000000000916222f3c4955626f7c8895a2afa5988b7f8b93938f837c76716e6c666b666c6e72787f879299a3aea99f948a7e71665b5044382b1c110600000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000815222e3b4855616e7b8896a0acb8c6d0dbe7f0f9e2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f5346392c211d1711090000000000000a151e263038424a545b656c77808d939d9d938d80776c655b544a423830261e150a0000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000009151f2a333c4247484c46443f382f2925201f1d1f2022282b2e34383a4045474c5254575a5d5e5f605f5e5d5b5854524c47433c35302820170e0500000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d04000000000000000000000000000000000000000000010e1a2733404c59646f7479797979797979706b6055483c2f231609000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e272727272727272727272727272727272727272727272721201d19130c0400000000000a16222e39434d555b5d6060606060585651493f34291e1206000004111e2b3744515e6a7784919393938c7f7265594c3f323744515e6a7784919393938c7f7265594c3f3226190c00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000030f1b27323d46535f69707d8691969e9f97928e8c8c8d8f92989f9f9691867d6f685e5242392e23180c000000000714212e3a4754616d7a8798a2a5988b7f7265544a3f33281c1107010006101823303c4956636f7c8996a2aa978a7d7164574a3e3124170b000000000000000a141d262f383f44525a616a6f7a818b92989f938e847c716c635b524a40372e231a0d0400000000000000020b19232b353d474f59606b707d869298a2a39b918c7f726d625b5a616c707e879299a3a39992877e716c615a50483e362c241a0c02000000020e1a25303b454d525f60606060606060605f524c443a3025190d01000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000000000000000000040d17222d38414c56606b73808d949fa9a79d928a7e71695f544a40342820170b02000000000000000000000000000000000000000000000000000000000000000000000005111e2a3744505c6873787979796d665c504441454c52565e61686d727678797876726d675f584e463c30261c1106000000000000000000000000000000000916222f3c4955626f7c8895a2afa396897d818e96959087827e7b79787778797b7f848c9299a3abaaa2978f82776c60544a3f33281c0a0000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000714212d3a46535f697784919eaab4bfcad6dee8eee2d5c9bcafa296897c6f635649505c6976838f9c9286796c5f534639302d29221b12090000000000030c151e262f38424a535b656c74818e9b9b8e81746c655b534a42382f261e150c030000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00020e1a26313c454d53555953504a423b35302d2b292c2d2d3338393f44464b5153565d606367696b6c6c6c6b6a6865615e56544e46413a322920170d020000000000000000000000000000030d161f272d32353639393635322d271f160d030000000000000000000000000000000000000000010e1b2834414e5b677481868686868686867d7063564a3d3023170a000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1413110d08020000000000010e1a27333f4a555f676a6c6c6c6c6c65625b51463a2e221609000005111e2b3844515e6b7784919e9f998c7f7266594c3f333844515e6b7784919e9f998c7f7266594c3f3326190c00000713202d3a4653606d798693a0aca6998d8073665a4d4033271a0d00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000a15202a36424d57606b707c848c9196999c9b9999999b9d9a97928d847d6f6b60564c4130271c1207000000000613202d394653606c7985929fa79b8e8174665b5044382d2218120d0c1117222b37424d5765727f8c98a5a398897c6f6256493c2f23160900000000000000020b141d262d33404850585f686d757e8690959d9691867e736d645c524940352c1f160c0100000000000000071119232b353d474f59606b707d869298a2a39b918c7f726d62616c707e879299a3a39992877e716c615a50483e362c241a1208000000000009141f29333b42464853535353535353535346413a32281e130800000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e010000000000000000000000000000000000000000000000000006111b262f3a444f59606d78829097a2ada49f92857b6e665c51443e32291d140a000000000000000000000000000000000000000000000000000000000000000000000005121f2b3845525e6b7885868686786d60534a4c51565e61686d737a7f82858685837f796f6a5f584e42382e23170b000000000000000000000000000000000916222f3c4955626f7c8895a2afa3968a7d7a84919899938f8b888685848486888c91969fa3aba9a29892857b6e655b5042382d22170b0000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0005121e2a36424d576673808c98a2aebac3ccd7dce3e7d5c9bcafa296897c6f635649505c6976838f9c9286796c5f53463e3d39342d241b110600000000060f19232b353d464e58606a6f7c8592989891857c6f6a60584e463d352b23190f060000000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0006121e2b37424d575f6166605b544d46413b393835393a3c3f44464a5053555d6064686d70737677787979787674716e68626058524c443a32291e130800000000000000000000000000000a151f2831383e4243464643423e3831281f150a0000000000000000000000000000000000000000010e1b2734414e5a6774818d93939393938a7d7064574a3d3124170a000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e21140d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d070705010000000000000003101d2936424f5b6771777979797979726d62564a3e3124180b000005121e2b3845515e6b7884919ea6998c807366594d40333845515e6b7884919ea6998c807366594d4033261a0d00000713202d3a4653606d798693a0aca69a8d8073675a4d4034271a0700000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b000000040e1a26313b454f59606a6f797f848a8d8f9192929291908d8a8580796f6b60594f443a301e150b000000000006121f2b3844505b667683909ca99e9285786c60544a3f3329241d19181b2227343c46535f6976838f9ca99f9286796d6053463a2d2013070000000000000000020b141c2228363e464e565d606c717b838d929f98928b80736e645b51473d31281e13080000000000000000071119232b353d474f59606b707d869298a2a39b918c7f726d6c707e879299a3a39992877e716c615a50483e362c241a1208000000000000020d17212930363a3b4646464646464646463936302820160c0200000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000000000000a141d29323d44505c666e7b85929ea4ada2979083786d60594f443b2f261c11060000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d6976839098897c6f635a56555d60686d737a80858b8f9192928f8b847c6f6a5f544a3f34281c10030000000000000000000000000000000916222f3c4955626f7c8895a2afa4978a7d717d8692989f9c9799929291919298989ea0a8aba69f9792867d70695f53493f2f261c11060000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00020e1a26313b4754616e7a86929fa7b1bac2cbd1d6dcd5c9bcafa296897c6f635653535c6976838f9c9286796c5f53534b49453e362d22170c000000030e18212b353d474f58606a6f7c8592918c8c9191857c6f6a60584f473d352b21180e0300000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000814212d3a47535f696e736c665f57524c484644404547494a5053545c6063676d71757a7d8083848586858583817e7a756f6a615d564c443a3025190d0100000000000000000000000005111c27313a434a4e505353504e4a433a31271c110500000000000000000000000000000000000000010e1a2734414d5a6774808d9a9f9f9f978a7d7164574a3e3124170b000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e2114080101010101010101010101010101010101010101000000000000000000000004111d2a3744505d6a778386868686867f7265584c3f3225190c000005121f2b3845525e6b7885919ea6998d8073665a4d40333845525e6b7885919ea6998d8073665a4d4033271a0d00000713202d3a4653606d798693a0aca79a8e8174675b4e412e23180c00000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b0000000009141f29333d474f5860676d72787d8082848586858483807e79736d6760594f473d32281e0c030000000000030f1c28333f4a546673808d99a7a1978a7d70665b50443e352f292423282d333d464f59616e7b86929faa9c908376665c5145382c1f13060000000000000001070d111317242d343c444c525a62696e78808b92999f928c80736d63594f433a2f24190d010000000000000000071119232b353d474f59606b707d869298a2a39b918c7f72707e879299a3a39992877e716c615a50483e362c241a12080000000000000000050f171f252a2d2e39393939393939392e2d2a251e160e050000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e010000000000000000000000000000000000000000000000000000020b172028343f4a545e69707d8a929da7a99f958d80736b61564d42382d22170e05000000000000000000000000000000000000000000000000000000000000000000010e1b2834414e5b6774818e9a8e81756c656364676d737a80868d92989c9e9f9e9c9691857c6f665c5044382b1f13080000000000000000000000000000000916222f3c4955626f7c8895a2afa4978a7e71707d8690959da0a39f9e9e9e9fa3aaa9a8a69f9c948f857d706b60574d41382d1d140a000000000000000000000000000613202c3946535f6c7986929f9f9f9a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000914202d3946525e6873808c95a0a8b1bbc0c7cbd0d0c9bcafa296897c6f63606060606976838f9c9286796c606060585650483e34291d110500000915202a333d474f59606a6f7c8592918c7f7f8c9192857c6f6a60594f473d332a20150900000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000815222e3b4855616e7b7f786e69615e565453504b515356545b6063666d70757a7e82868a8d909192939291908e8b86827c746d685e564c41362a1e11050000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a00000000000000000000000000000000000000000d1a2633404d596673808c99a6aca4978b7e7164584b3e3125180b000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000004111e2b3744515e6a7784919393938c7f7265594c3f3226190c000005121f2c3845525f6b7885929ea69a8d8073675a4d40343845525f6b7885929ea69a8d8073675a4d4034271a0d01000713202d3a4653606d798693a0aca89b8f827568544b4034281c1004000916232f3c4956626f7c8995a2afa4988b7e7165584b3e3225180b00000000030d17212b353d464e555c60666d70737677787978787674716d67605d554f473d352b20160c000000000000000b17222d3c4956636f7c8995a0a99d9083786c605a50454039352f2e34383f444e58616b75818e99a3a3988c7f7265544b4034281c1004000000000000040c13181d202021222a323a414550575f666d747e8792989c928c7f726b61564c4135291d1307000000000000000000071119232b353d474f59606b707d869298a2a39b918b7f7d879299a3a39992877e716c615a50483e362c241a120800000000000000000000050d141a1e20212d2d2d2d2d2d2d2d21201d19130c05000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000000000000000000000000050e17232e38424d57616c74808d95a0aaa79f93887d70695e544a3f332820160b020000000000000000000000000000000000000000000000000000000000000000000c1825323f4b5865727e8b98938b7f75717071747a80858d92989fa2aaa4a3a5a8a1979083786d6053463a2f24190d0100000000000000000000000000000916222f3c4955626f7c8895a2afa4978a7e716b707c838b9195989b9d9e9f9f9f9e9d9b9894908a827b706b60594f453b2f261b0b02000000000000000000000000000613202c3946535f6c798692939393938d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000005111e2a36414c56606d798390969fa7afb5babfc2c3c4bcafa296897c6f6c6c6c6c6c6c76838f9c9286796c6c6c6c64625a5045392d21150800020f1a26313c464f59606b6f7c8592918b7f72727f8b9192857c6f6b60594f463c31261a0f02000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000815222f3b4855626e7b88827b736d686461605b555d606265666c7074797d81858a8f92999a9c9e9f9f9f9e9d9b99928f87817a6d685e5246392d2013070000000000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d01000000000000000000000000000000000000000c1925323f4c5865727f8b98a5b2a5988b7f7265584c3f3225190c000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000005111e2b3844515e6b7784919e9f998c7f7266594c3f3326190c000006131f2c3946525f6c7985929fa79a8d8074675a4d41343946525f6c7985929fa79a8d8074675a4d4134271a0e01000713202d3a4653606d798693a0aca99d908376665c5145382c1f130700091623303c4956636f7c8996a2afa4988b7e7165584b3e3225180b0000000000060f19232b343d434b51545c606366696b6c6c6c6b6a6764605d55514b433d342b23190e04000000000000000615222f3b4854606b7784919da8a0958c7f726c615a514b4541403f4045495058606a707d8a939eaa9f92867a6d6154473a2e23180c000000000000040d161d24292c2d2e2f30302f353e454d545c606c717d8692999f93887d70685d52453a2f24180d01000000000000000000071119232b353d474f59606b707d869298a2a39b918b869299a3a39992877e716c615a50483e362c241a120800000000000000000000000002090e12141520202020202020201413110d080200000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e010000000000000000000000000000000000000000000000000000000006111c26303b45505a606d79839098a2aea49a92857b6e665b50443d32281d140a0000000000000000000000000000000000000000000000000000000000000000000815222f3b4855626e7b88959b918b827e7d7e81858c92989fa2a29f9a9796989c9f9f958a7d7164554c4135291d110400000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e71646a6e787e84888c8e909192929291908e8b88837d766e6960594f473d33291d140a00000000000000000000000000000613202c3946535f6c79878686868686868074675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000020e1925303b45515c666e7b8490959fa3abaeb4b6b7b8b9afa296897d7979797979797979828f9c92867979797979716c6256493d3024170a0006121f2b37434e58606b707d8692918b7f726d6d727f8b9192867d706b60584e43372b1f1206000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000815222f3b4855626e7b888f86807a75716e6c666b676d6f7175797c81858a8e92989c9fa3aba39f9e9d9d9d9fa3a39f9a938e847a6d6154473a2e2114070000000000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f03000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0a6998c807366594d4033261a0d000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000005121e2b3845515e6b7884919ea6998c807366594d4033261a0d00000613202c3946535f6c7986929fa79a8d8174675a4e41343946535f6c7986929fa79a8d8174675a4e4134271b0e01000713202d3a4653606d798693a0acac9f9286796d6053463a2e23180d060a1723303d4a5663707d8996a3b0a4978b7e7164584b3e3125180b000000000000081119222b303940454a5053575a5c5e5f5f5f5e5d5a5753514b45413a312b22191107000000000000000007131f2c38434f5965727f8b96a1a79f93887e716c605d55524c4c4c4b51535b606a6f7c86929fa5a3988e8174685e5246392d1d12070000000000010c161f282f35393a3b3c3c3d3d3c383b424a515a626b707e87939f9a92857a6d60554b4135291d110400000000000000000000071119232b353d474f59606b707d869298a2a39b999299a3a39992877e716c615a50483e362c241a120800000000000000000000000000000002050708131313131313131307070501000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000000000000000040404000a141e29333e45515c676e7b86929fa5aca1978f82786c60594f443a2f261b110600000000000000000000000000000000000000000000000000000000000000000814212e3a47535f6a7784919d9b948f8b898a8d92989fa2a29f98928d8a898b90949c9c8f8276675d5145392c20130600000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e71645f666d71777b7f8183858586858583817e7b76706b615e574f473d352b21180b02000000000000000000000000000006121f2c3845525e6a7579797979797979746e64584c3f33261a0d000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000008141e2834404b545e696e7b838d92999fa3aaa9aaabacaea5998f8986868686868686868f949f988986868686867e7164584b3e3125180b000814212e3a47535f6a707d8692918b7f726d62626d727f8b9192867d706a5f53473a2e211408000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000815222f3b4855626e7b8898928d86827e7b797877787a7c7e8285898d92979b9fa2a7a09d9999929190909192999a9ea19f96887b6e6255483b2f221508000000000000000000000003101d2a3643505d69768286868276695d5043362a1d1003000000000000000000000000000000000000000916232f3c4956626f7c8995aab4a79a8e8174675b4e4134281b09000000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000005121f2b3845525e6b7885919ea6998d8073665a4d4033271a0d000006121f2c3844515c667986939fa79b8e8174685b4e41353844515c667986939fa79b8e8174685b4e4135281b0e02000713202d3a4653606d798693a0acaea398897c6f62544b4034281f1612101824313e4b5764717e8a97a4b1a4978a7e7164574b3e3124180b000000000000000810191e272e34383f44464a4d505152535251504d4a47454039352f281f191007000000000000000000030c1b27323d4753606d7984919eaca49a92867e736d67605d565959545c60656c717c859198a2ac9f92867b6e61564c4135291d0c03000000000007131d28313a4045474848494a4a48443d3940445059616c73808c96a0978d8073675d5145392c2013060000000000000000000000071119232b353d474f59606b707d869298a2aba39fa3a39992877e716c615a50483e362c241a12080000000000000000000000000000000000000000060606060606060600000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e010000000000000000000000000000000000000000000306080911111111110c17212834404b555f69717e8a939da8a99f948c7f736b60564c41382d22170d040000000000000000000000000000000000000000000000000000000000000006121e2b37424e5765727e8b95a09e9c9896979a9fa2a39f98928c85817e7d7e838c929f92867a6d6054473a2d21140700000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164545c60646a6e72757778787979787675726e69636159534d453d352b23190f0600000000000000000000000000000004111d2a36424e59636a6c6c6c6c6c6c6c67645c52473c3024170b000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000020c18232e39424d575e696e7880878d9298999c9d9e9fa39fa1999693939393939393939c9fa6a393939393938b7e7164584b3e3125180b000815222f3b4855626e7b8592938b7f726d625b5b626d727f8b9192857b6e6255483b2f221508000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000815222f3b4855626e7b88959f98928e8b878685848586898b8e92979a9ea1a8a09e9995908c89868483838486898d92979e95887b6e6255483b2f221508000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000814212e3b4754616e7a8798a2aea89b8f8275685c4f4230251a0e020000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000005121f2c3845525f6b7885929ea69a8d8073675a4d4034271a0d01000713202d3a4653606d79869aa4a89b8e8175685b4e42353a4653606d79869aa4a89b8e8175685b4e4235281b0f02000713202d3a4653606d798693a0acb4aa998d8073665c51453b3128201f1c1e26323f4c5965727f8c98a5b0a3968a7d7063574a3d3024170a0000000000000000070c151d23282e34383a3d4043444546454543413e3a38352f29241d160d07000000000000000000000b151e2b353d45515c67717d8a9aa4aca298928a8079716d6867666567666d70787e869197a1aaa6998c8073695e53493f372d1e150b00000000010d18242f3a434b51535455565756554f473d343f47505a606d7884919e9f92857a6d6054473a2d211407000000000000000000000000071119232b353d474f59606b707d86929facafacac9f92877e716c615a50483e362c241a1208000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e0100000000000000000000000000000000000000030a0f1215151e1e1e1e1e1e1e18232e39434d57616c74818e96a0aaa69f93877d70685e53493f33271f160c01000000000000000000000000000000000000000000000000000000000000020e1a26313c4653606c78839097a1a8a4a3a4aaa29f98928d86807a74717072767f8c94998a7d7063574a3d3024170a00000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164585053585f6265686a6b6c6c6c6b6a6865615f57554f46423b332b2319110700000000000000000000000000000000010e1a26313d4751595e5f6060606060605a58524a41362b1f1408000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000007121d27303b454d575e666d747b8186898d8f909192999393939393939393939393939393939393939393938b7e7164584b3e3125180b000814212e3a47535f6a74808d887f726d625b51515b626d727f8b8d80746a5f53473a2e211408000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000815222f3b4855626e7b88949fa29f9b979992919192939a989b9ea1a9a29e9a96918c8883807d7a78767677797c80858b9297887b6e6255483b2f221508000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000613202d394653606c7985929facaa9d9083776a574d42362a1e11050000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000006131f2c3946525f6c7985929fa79a8d8074675a4d4134271a0e01000714202d3a4753606d7a8693a0a89b8e8275685b4f42353a4753606d7a8693a0a89b8e8275685b4f4235281c0f02000713202d3a4653606d798693a0acb8ab9e9285796d60574d433a322d2c282a2d36424d576774818e9aa7b3a995897c6f6256493c2f231609000000000000000000030b12181c23282b2d30333638393939383734312d2c29241d18130c040000000000000000000007121c27303d474f59606b707d87939facaaa29f928d847e7a767473727375797d838b9298a1a9b3a5998c7f726d625b51493f30271d120700000004111d2935404b555d60616263636360594f4438353e44505c66727f8b98a2988a7e7164574b3e3124180b00000000000000000000000000071119232b353d474f59606b727f8c98a5b2b3a79a8d80746c615a50483e362d241b120900000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000000060e151a1f21222b2b2b2b2b2b2b2b2b27303c45505a606d79849198a3aea49991847a6d655b50443d31281e13080000000000000000000000000000000000000000000000000000000000000009151f2b3844505b666f7c8591969c9f9f9e9c98928d86807a736d686463656d76828f998d8073665a4d4033271a0d00000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b464e5355595b5d5e5f5f5f5e5d5b5855534d48443e363129211911070000000000000000000000000000000000000915202b353f474e52535353535353534e4c4741382f241a0e03000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000b151e29333b454d545c60696e747a7d808384858686868686868686868686868686868686868686868686867e7164584b3e3125180b0006121f2b37434e58646e74817e726d625b514949515b626d727f80746e64584e43372b1f1206000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000714212d3a4754606d79828b92989ea1a8a39f9e9e9f9fa4aca9a19e9a97928e89847f7b7773706d676a6a666d6f73797f858f887b6e6255483b2f221508000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000005121f2b3744505b657783909daaac9f928579695e52463a2d2014070000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929fa79a8d8174675a4e4134271b0e01000714212d3a4754606d7a8793a0a89b8f8275685c4f42353a4754606d7a8793a0a89b8f8275685c4f4235291c0f02000713202d3a4653606d798693a0acb9ada1978b7e71695e554c443e3a3834363a3d46535e697784909daaada297877a6e6154473b2e2114080000000000000000000000070c11171c1f202427292b2c2c2c2b2a2724201f1d18120d070100000000000000000000000c18232e39424f59606b707d86929aa4aba9aca49c96918b8682807f7f8082858a90959fa3aaaaaca79c918b7f726d625b5142392e23180c0000000613202c3945515d676d6e6f6f70706b6055483d32343f4a54616e7b8899a49a8d8174675a4e4134271b0e010000000000000000000000071119232b353d474f59606b707d86929facacacac9f92877e716c615a50483e362d241b1209000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e01000000000000000000000000000000000006101820262b2e2f3737373737373737373737333e45515d676f7c86929fa5aba1968f82776c60584e433a2f24190d06000000000000000000000000000000000000000000000000000000000000030f1c28333f4a545f6a6f7c848c909292918f8b86807b746e68605d56565b64707d8a998f8275685c4f4235291c0f02000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e4347484c4e505252535252504e4b4846423b38332a251f170f0700000000000000000000000000000000000000040f19242d353d424546464646464646413f3c362f261d130800000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000030c172129333b424a51575e61676d7073767778797979797979797979797979797979797979797979797979716c6256493d3024170a00020f1a26313c46525c646e74726d625b51493f3f49515b626d72746e645c52463c31261a0f02000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000613202c3945515d676d767e858c9196989b9d9e9f9f9e9d9a9897928e8a85817c77736e696663605d55545c6063676d727a81887b6e6255483b2f221508000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000030f1b27333f49536874818e9ba7aea298877b6e6154473b2e2114080000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e2114080000000000000000000000000000000000000000000000000000000000000006121f2c3844515c667986939fa79b8e8174685b4e4135281b0e02000814212e3b4754616e7a8794a1a89c8f8275695c4f42363b4754616e7a8794a1a89c8f8275695c4f4236291c0f03000713202d3a4653606d798693a0acb1a7a09d92857b6e675d56504846443f4246474f58616e7b8795a0acab9f928578685e5246392d20140700000000000000000000000000060b101213171a1d1e1f201f1e1d1a171413100c070100000000000000000000000004101c2834404a54606b707d869298a3a69f9c9fa4a8a19e99928f8d8c8c8d8f92989da0a7a7a09da0a7a39b918b7f726d62544b4034281c100400000714202d3a4753606d797b7b7c7d7d7063584e4338313a4653606d7986939f9c8f8276695c4f4336291c100300000000000000000000071119232b353d474f59606b707d869298a2a39f9fa3a39992877e716c615a50483e362d241b12090000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929faca79b8e8174685b4e4135281b0e0200000000000000000000000000000000030e18222a31373a3c44444444444444444444444444404b555f6a727f8b939ea8a89e948c7f726a60554c41352922180c010000000000000000000000000000000000000000000000000000000000000b17222d38424e585f6a6f797f83858684827f7a736e69615e56524c4a54606d7987868683776a5e5144372b1e1104000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e373a3b3f4244454546464543423f3b3a36312c28211a140d050000000000000000000000000000000000000000000a16202b343d4347494949494949494846423b33291f140900000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000050f172029303940444d53555d606366696a6b6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64625a5045392d21150800000915202a33414a525c646765625b51493f37373f49515b626567645c524a41332a20150900000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0004111d2935414b555d606d717a7f84898c8f9091929291908e8b8885817d79746f6b66615f575653514b4b5153555c60686d757f7b6e6155483b2e221508000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000b17222d3f4c5865727f8b98aab4aa96897c706356493d302316080000000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d79869aa4a89b8e8175685b4e4235281b0f02000815212e3b4854616e7b8794a1a99c8f8376695c5043363b4854616e7b8794a1a99c8f8376695c504336291d1003000713202d3a4653606d798693a0acaca09590959082796d68615a5553504a4d525459606a74808d9aa7b1a99c8f827669564d41362a1e11050000000000000000000000000000000306070a0d101112131212100e0b07060400000000000000000000000000000006121f2c3844515c66707d869298a3a39c948f939aa0a7aba39f9c9a99989a9b9fa2aaa8a19e9590959ba3a39b918b7f72665c5145382c1f13060003101c2936434f5c6976828788898a85786a605448423f404653606d798699a49c8f8376695c504336291d1003000000000000000000071119232b353d474f59606b707d869298a2a399929299a3a39992877e716c615a50483e362d241b120900000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929faca89b8e8275685b4f4235281c0900000000000000000000000000000000000a15202a343c4347485151515151515151515151515151514e58626d75818f96a1aba69f92877c6f675d51453f34291d110500000000000000000000000000000000000000000000000000000000000006111c262f3c464e585f676d727678797876726d68615e56524c454145515d67757979797771675b4f43362a1d1004000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e312e2f32353738393939383735322e2d2a261f1c170e0903000000000000000000000000000000000000000000030f1b27323d464e545656565656565654534d453b31251a0e02000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000000050e171e272e343b42464b5153565a5c5d5e5f6060606060606060606060606060606060606060606060585650483e34291d11050000030e18212f38414a52585a585651493f372d2d373f495156585a58524a41382f21180e0300000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00010d18242f3a434b515a62686d72797c7f82848586858583817f7c7974706d6663605955534d494745404045464b51565e616d726e695f53473a2d211408000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000616232f3c4956626f7c8998a3aea5988c7f7265594c3f3025190d0100000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0a89b8e8275685b4f4235281c0f02000815222e3b4855616e7b8894a1a99c908376695d5043363b4855616e7b8894a1a99c908376695d5043362a1d1003000713202d3a4653606d798693a0acaa9d9084909490827a716c6562605c54565e61646b707c87929facb0a6998c7f7266594c3f3025190e0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d79849197a1a49c918c838790959c9fa4aca9a7a6a5a6a8a8a7a09d96918a848c919ba3a0959084796d6053463a2d20130700000d1a2733404d5a6673808d959697897c6f625b534d4c4d4f58626f7c8895ab9b8e8275685b4f4235281c0f020000000000000000071119232b353d474f59606b707d869298a2a3999286869299a3a39992877e716c615a50483f362d241b1209000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929faca89c8f8275695c4f4230251a0e02000000000000000000000000000000030f1a26313c464e53555e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5b606d7a849199a3aea39991847a6d605a50453a2e211509000000000000000000000000000000000000000000000000000000000000000a141d2a343c464e555d6065696c6c6b6965615e56524d46413b35414b555d6b6c6c6c6a675f564b3f33271b0e02000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e31252226282a2b2c2c2c2b2a282522211e1a14100b05000000000000000000000000000000000000000000000006131f2b37434e586062626262626262615e574d42362a1e1205000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000000000050c151c232831363a4045474a4d5051525353535353535353535353535353535353535353535353534b49453e362d22170c00000000060f1d262f3841474c4e4b4a453f372d25252d373f464a4b4e4c4741382f261d0f060000000c1925323f4c5865727f8b989f9f998d8073665a4d4033271a0d000007131d28313a414550565d60666d6f727577787979787674726f6c6663605c54544f4846423d3a393534383a40454c525b6265615f574d42372b1e1206000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000713202d3a4653606d7986929faca89b8e817568564c41362a1e110500000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000714212d3a4754606d7a8793a0a89b8f8275685c4f4235291c0f02000815222f3b4855626e7b8895a1a99d9083766a5d5043373b4855626e7b8895a1a99d9083766a5d5043372a1d1004000713202d3a4653606d798693a0aca396897d85929490847d76726e6d666b6b696e71757d859299a3afab9f94887b6e6155483b2e2215080000000000000002060a0c0d1313131313131313131313131313131313131313131312110f0c0701000000000000000006121f2c3844515c666e7c8591979c928c7f767c838a8f939a9a9d9e9f9f9e9d9b9895908b847e777f8c919b9691837a6e665c5145382c1f130600000916232f3c4956626f7c89959f9c8f82756d615e57595959616a73808d99a8998d8073665a4d4033271a0d0000000000000000071119232b353d474f59606b707d869298a2a39992877d7d879299a3a39992877e716c625a50483f362d241b12090000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaa9d9083776a574d42362a1e120500000000000000000000000000000006121f2b37434e585f626a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a686f7c87929facaba0968e81756c62564a3d3124170b00000000000000000000000000000000000000000000000000000000000000020b18222a343c434b5154595d5f5f5e5c5854524c46423b36302f3a434b515e6060605e5b564d44392e22170b00000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e312518191b1d1f1f201f1f1d1b181514120e0903000000000000000000000000000000000000000000000000000815222e3b4754606a6f6f6f6f6f6f6f6e695e53463a2d211407000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000030b12181f252a2f35393a3d404344454646464646464646464646464646464646464646464646463e3d39342d241b110600000000000b141d262f363c40413f3d3a342d251b1b252d343a3d3f413f3c362f261d140b000000000c1925323f4c5865727f8b939393938d8073665a4d4033271a0d0000010c161f282f353f444c52545c606265686a6b6c6c6b6a676562605b5453514a48433d3a36312d2c29282c2f343a414651575955534d453c31261a0e02000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000006121f2c3844515c667683909ca9aa9e918477685e5246392d20130700000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a8794a1a89c8f8275695c4f4236291c0f03000915222f3c4855626f7b8895a2aa9d9083776a5d5044373c4855626f7b8895a2aa9d9083776a5d5044372a1d1104000714202d3a4753606d7a8693a0ada194887b7e8b9296918a837f7b79787778797a7d82889297a1abafa4998f8276695f53473a2d211408000000000000070d12161919202020202020202020202020202020202020202020201f1e1b18130c050000000000000004101c2834404a545f6a6e7c8591928c7f736d6f787d82878b8e9091929291908e8b88837e79716d727f8c9191847a6e685e544b4034281c100400000815222e3b4754606a7783909a9e948c7f756e69676666676b707c86929fa096897c6f6356493c3023160900000000000000071119232b353d474f59606b707d869298a2a39992877e70717e879299a3a39993877e716c625a50483f362d241b120900000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facac9f928579695e52463a2d2014060000000000000000000000000000000815212e3a47535f6a6f777777777777777777777777777777777777777777777f8c99a5b2a89e938b7e7165584b3e3225180b0000000000000000000000000000000000000000000000000000000000000000061018222a313a4145474c50525352504c4746413a36302a2528313a414547535353514f4b443b32281d110600000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180c0f111212131312100f0c080705020000000000000000000000000000000000000000000000000000000916232f3c4956626f7c7c7c7c7c7c7c7b6e6154483b2e211508000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d0000000000000000000000070c141a1d24292c2d303336373839393939393939393939393939393939393939393939393931302d29221b1209000000000000020b141d242b30333432312e29231b12131b23292e31323433302b241d140b02000000000c1925323f4c5865727f8686868686868073665a4d4033271a0d000000040d161d2429323a41454a505356595c5d5e5f5f5e5d5b585553504a4644403938322d2a2620201d1c1f232930363f464a4c4847423c332a1f150900000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000004101c2834404a5466737f8c99a9aca096877a6d6154473a2e21140a00000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8794a1a99c8f8376695c504336291d1003000916232f3c4956626f7c8995a2aa9d9084776a5d5144373c4956626f7c8995a2aa9d9084776a5d5144372a1e1104000714212d3a4754606d7a8793a0ada194877b74818e949e95908c888685848585878a8f939aa1a9afa59f93877c6f62574d42372b1e120600000000010a12191e2325262d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b2b28241e170f06000000000000000c18232e39424e575f6a6e7c858c80736d63666d70767b7e81838485858584817f7c77726d67626d727f8b847b6e685e564c42392e23180c00000006131f2b38434e5863707d88939f9c918c817b7673727374777d859298a29e9184786d6053463a2d201307000000000000071119232b353d474f59606b707d869298a2a39992877e706c6c717e879299a3a49993877e716c625a50483f362d241b1209000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929facaea298877b6e6154483b2d22170b0607080808060200000000000000000915222f3c4855626f7c8484848484848484848484848484848484848484848484919daab7afa59f9285786c5f5245392c1f120600000000000000000000000000000000000000000000000000000000000000000610181f282f35393a3f43454645433f3a3936302a251f191f282f35393a46464644433f39322920160b0000000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b020405060606050402000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c79878989898989898074675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000000000000000003090e13181d20202327292a2b2c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2524211d1711090000000000000000020b131a1f2426272524221d1811090911181d2224252726241f1a130b0200000000000b1825313e4a56626d72797979797979736e63584b3f3226190c00000000040c131820282f35383f4446494c4f5152535252504e4c4946443f3a38342e2c27211e1a1413101013181e252a353a3e3f3b3a37312a21180e0300000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000c18232e3c4956626f7c8997a2ada8978a7e7164574a3e31261b0f03000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000815222e3b4855616e7b8894a1a99c908376695d5043362a1d100300091623303c4956636f7c8996a2aa9e9184776b5e5144383c4956636f7c8996a2aa9e9184776b5e5144382b1e1105000714212e3a4754616d7a8794a0b4ab94877a6d78828f939f9d989a939291919298979b9fa4acaba39f938d80736a6054453c31261a0e02000000000a131c232a2f3233393939393939393939393939393939393939393939393837342f2921180f0500000000000007121c27303c454e575f6a6e7c7f736e635b5c6064696e717477787979787775726f6a65605d5b626d727e7b6e695e564d443b30271d1207000000030f1b27323d4854606b73808d939f9c938e8783807f8081848a9297a19f928a7d70665c5044382b1f12060000000000071119232b353d474f59606b707d869298a2a39992877e716c61616c717e879299a3a49993877e716c625a50483f362d241b12090000000000000000000000000000060606060606060600000000000000000000000613202c3946535f6c7986929facb4aa978a7d7064544a3f33281c131313151514120f0a030000000000000916222f3c4955626f7c889191919191919191919191919191919191919191919196a0acb8b8ac9f9285796c5f5246392c1f1306000000000000000000000000000000000000000000000000000000000000000000060d161d24292c2d323639393836322e2d2a251e19140d161d24292c2d3939393736332e2820170e040000000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c798692959595958d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d000000000000000000000000000001070d111314171a1d1e1f202020202020202020202020202020202020202020202020181715110c060000000000000000000001080e14171a1b181815120c060000060c121518181b1a17140e08010000000000000916222e3a46515b62656c6c6c6c6c6c66635c52473b2f23170a000000000001070d161e24292e34383a3c3f42444546464543413f3c3938332d2c28231c1b16120e09060404070c131923292e31322e2d2b261f180f060000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000713202d3a4653606d7985929eaba79b8e817468584e43372b1f1206000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000815222f3b4855626e7b8895a1a99d9083766a5d5043372a1d1004000a1623303d495663707c8996a3ab9e9184786b5e5145383d495663707c8996a3ab9e9184786b5e5145382b1e1205000814212e3b4754616e7a87949f9fa39986796d6d79818c92989fa29f9e9e9e9fa2aaa8a9aaa29f99928b81786d60584e43332a1f15090000000007121c252e353b3e40464646464646464646464646464646464646464646464544403a332b21170c010000000000000b151e2a333c454e575f6a6e726d635c525053575e6164676a6b6c6c6b6a6865625f585351515b626c716e695e574d443b32291e150b00000000000a16202c38444f59606c77808c92989f9992908d8c8c8e91969e9f99928c80736b61544a3f34281c100300000000040f19232b353d474f59606b707d869298a2a49992877e716c615a5a616c717e879299a3a49993877e716c625a50483f362d241b110600000000000000000002050708131313131313131307070501000000000000000613202c3946535f6c7986929facb4a79a8e8174665b5044382d22201f202222211f1a150e0600000000000916222f3c4955626f7c88959d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9da0a8b2acacac9f9285796c5f5246392c1f130600000000000000000000000000000000000000000000000000000000000000000000040c13181d2021262a2c2c2b292521201d19130e09040c13181d20212d2d2d2b2a27221d160e05000000000000000000000000000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929fa2a29a8d8174675a4e4134271b0e000c1925323f4c5865727f8b98a5a6998d8073665a4d4033271a0d00000000000000000000000000000000010406070a0d1011121313131313131313131313131313131313131313131313130b0a0805000000000000000000000000000003080b0d0e0c0b090501000000000106090b0c0e0d0b0803000000000000000006121e29343f495156586060606060605a58524a40362a1f130700000000000000040c13191c23282b2d2f323537383939383734322f2d2b28221f1c18120f0a0502000000000002080d181e22252622211e1a150e06000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000006121f2b3844505c6674818e9baaab9e9184786a5f53473a2e21150a000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b8895a2aa9d9083776a5d5044372a1d1104000a1723303d4a5663707d8996a3ab9e9185786b5e5245383d4a5663707d8996a3ab9e9185786b5e5245382b1f1205000815222e3b4855616e7b889393939392867966676d787f868d92989a9c9e9e9f9f9e9d9c9998928d877f746d665c50463d3221180e03000000020d19232e3740464b4c5353535353535353535353535353535353535353535352504c453d33291e1307000000000000030c18212a333c454e575f6266635b524944464d5354585b5d5e5f5f5e5d5b5855534e474549515a6265615e574d453b322920170c03000000000004101c27323d44505b656c777f868e92999b9c9a99999a9d9b99938f867f736e63594f42382e23170b00000000000b16212b353d474f59606b707d869298a2a49993877e716c615a50505a616c717e879299a3a49993887e716c625a51483f372d23180c0100000000000002090e12141520202020202020201413110d080200000000000613202c3946535f6c7986929facb8ab9e9185786c60544a3f332d2c2c2d2f2f2e2b2620180f06000000000916222f3c4955626f7c88959f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9285796c5f5246392c1f1306000000000000000000000000000000000000000000000000000000000000000000000001070d111314191d1f201f1d191413110d0802000001070d1113142020201e1d1b17110b0400000000000000000000000000000000000916222f3c4955626f7c8895a2aca4978b7e7164584b3e3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929faca79a8d8174675a4e4134271b0e000c1925323f4c5865727f8b989f9f998d8073665a4d4033271a0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d18232d373f464a4c5353535353534d4b4740382e24190e02000000000000000001080d11171c1f202326292a2b2c2c2b2a282522201f1c1712100c070000000000000000000000070d121618191514120e090300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000003101c28343f4a5464707d8a98a2ada196887b6f6255483c31261a0f000000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000916232f3c4956626f7c8995a2aa9d9084776a5d5144372a1e1104000a1724303d4a5763707d8a96a3ab9e9285786b5f5245383d4a5763707d8a96a3ab9e9285786b5f5245382c1f0600000916232f3c4956626f7c86868686868685786b5c666c727b80858a8d8f9192929291908f8c8a86807b726d605c544a3f342b200f060000000006121e2a354049515759606060606060606060606060606060606060606060605e5c574f453a2f24180c00000000000000060f18212a333c454e53555957514940383b4246484b4e5051525252514f4c4847433c393f4850565854534d453b332920170e05000000000000000b162127333f49535b656c727b81868b8e9091929291908e8b87827c726d635c52473e30261c11060000000003101b27323d474f59606b707d869298a2a49a93877e716c615a504848505a616c717e879299a4a49a93887e716c625b51493f34291d11050000000000050d141a1e20212d2d2d2d2d2d2d2d21201d19130c05000000000613202c3946535f6c7986929facb4aba1978a7e71665b50443f3a39383a3b3b3a37312a22180e030000000916222f3c4955626f7c8893939393939393939393939393939393939393939393939393939393939285796c5f5246392c1f130600000000000000000000000000000000000000000000000000000000000000000000000000010406070c10121312100c070705010000000000000104060713131311100e0b06000000000000000000000000000000000000000916222f3c4955626f7c88959f9f9f978b7e7164584b3e3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c7986929f9f9f9a8d8174675a4e4134271b0e000c1925323f4c5865727f8b939393938d8073665a4d4033271a0d00000000000000000000000000000000000000000000000000000000000000000000040613131313131313131312110e09040000000000000000000000000000000000040613131313131313131312110e0904000000000000000000000000000000000007111b252d343a3e3f464646464646403f3b362e261c1208000000000000000000000000060b10121316191c1e1f201f1f1d1b191613120f0b060400000000000000000000000000000106090b0c08080602000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000b17232e3a4753606d7985929faca8998c7f7366584e43372b1c11060000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000000091623303c4956636f7c8996a2aa9e9184776b5e5144382b1e1105000a1724313d4a5764707d8a97a3ab9f9285786c5f52452e3d4a5764707d8a97a3ab9f9285786c5f52452e23170b00000815222e3b4754606a6f797979797979787368545b60696e74797d808284858685858482807d7a746e69625b504a42382e22190f00000000000a16232f3b46515b63666c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b6861574c4034281b0f0000000000000000060f18212a333c4247484c4b463f372b31363a3b3e41444546464544423f3c3a37312c363f454a4b4846423b332920170e050000000000000000050b17222d384149535b606a6e757a7e81838585868584817f7b756f6a635b524940352c1e140a00000000000713202c38444f59606b707d869298a2a49a93887e716c615a50483e3e48505a616c717e879399a4a49a93887f726d625b51453a2e22150900000000050f171f252a2d2e39393939393939392e2d2a251e160e050000000613202c3946535f6c7986929facaea399929183786c6059504947454546484847433c342a20150a0000000916222f3c4955626f7c8686868686868686868686868686868686868686868686868686868686868686796c5f5246392c1f130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000916222f3c4955626f7c8893939393938b7e7164584b3e3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c798692939393938d8174675a4e4134271b0e000c1925323f4c5865727f8686868686868073665a4d4033271a0d0000000000000000000000000000000000000000000000000000000000000001070c10132020202020202020201f1d1a150f080000000000000000000000000001070c10132020202020202020201f1d1a150f08000000000000000000000000000000000009131b23292e313239393939393933322f2a241c140a000000000000000000000000000000030607090c0f1112131312100e0c090606030000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000006131f2c3845515d6774818e9ba8aa9d9184776a5f5347382e23170b0000000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000a1623303d495663707c8996a3ab9e9184786b5e5145382b1e1205000b1824313e4b5764717e8a97a4ac9f9285796c5f4a3f343e4b5764717e8a97a4ac9f9285796c5f4a3f34281c10030006131f2b37434e5860626c6c6c6c6c6c6b68615750575e61676d7073767778797978777673706d67615e5751443f3830261c100700000000000c1925323e4b57636d73797979797979797979797979797979797979797979797873685c5044372b1e11000000000000000000060f18212a31373a3b3f3e3a352e25252a2d2e313437383939383735322f2e2b26242d343a3d3e3b3a36312921170e050000000000000000000006111b262f38414950575f62686e717477787979787775726e69625f58514940372e231a0c0200000000000916222f3b4854606b707d869298a2a49a93887e716c625a50483e36363e48505a616c717e879399a4a49a93887f726d62564a3d3124180b000000020d17212930363a3b4646464646464646463936302820160c0200000613202c3946535f6c7986929facac9f9286928c7f736b605b53535151535555534e463c31261a0f0200000815222e3b4754606a76797979797979797979797979797979797979797979797979797979797979797974695d5144382b1f120500000000000000000000000000000000000003080c0e0e131313131313130f0e0c09040000000000000000000000000000000000000000000000000000000000000003070b0d0e131313131313130e0e0c08030000000000000916222f3c4955626f7c868686868686867e7164584b3e3125180b000000000000000000000000000000000000000000000000000000000000000000000000000000000613202c3946535f6c79878686868686868074675a4e4134271b0e000b1825313e4a56626d72797979797979736e63584b3f3226190c000000000000000000000000000000000000000000000000000000000000030b12181c1f2d2d2d2d2d2d2d2d2c2c2a26201912090000000000000000000000030b12181c1f2d2d2d2d2d2d2d2d2c2c2a262019120900000000000000000000000000000000010911181e2225252d2d2d2d2d2d2726231f19120a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000004101d2935404b5563707d8996a1aca095887b6f62544a3f34281c100300000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d8996a3ab9e9185786b5e5245382b1f1205000b1825313e4b5864717e8b97a4ac9f938679665c5044383e4b5864717e8b97a4ac9f938679665c5044382b1f120600030f1b27323d464e54566060606060605f5c574f444d53555c606367696b6b6c6c6b6a696663605d55534d453f342e261e140a0000000000000d192633404c5966737f8686868686868686868686868686868686868686868685786b5e5245382b1f1200000000000000000000060f1820262b2e2f33322f2a231c1a1e212125282a2b2c2c2b2a282522211f1b1b22292e31322e2d2a251f170f050000000000000000000000000a141d262f383f444e53565e6165686a6b6c6c6b6a6865615e57534e463f372e251c11080000000000000a1623303d495663707d869298a2a39f93887f716c625a50483e362c2c363e48505a616c717e879399a4a49a93887e7265584b3f3225180c00000009141f29333b42464853535353535353535346413a32281e1308000005121f2b3744505b657986939faca79a8d818d93877d726c6562605d5c6062625f584e43372b1f1206000006131f2b37434e5860626c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6962584d4135291c10030000000000000000000000000000000001090f14181a1b202020202020201c1b191510090200000000000000000000000000000000000000000000000000000001080e1317191a202020202020201b1a18140f0901000000000815212e3b47535f6a7679797979797979716c6256493d3024170a0000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2c3845525e6a7579797979797979746e64584c3f33261a0d000916222e3a46515b62656c6c6c6c6c6c66635c52473b2f23170a0000000000000000000000000000000000000000000000000000000000030d151d23292c3939393939393939393836312b241b1208000000000000000000030d151d23292c3939393939393939393836312b241b12080000000000000000000000000000000000070d121618192020202020201a1917130e08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a0500000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000c18242f394653606c7884919eaba7998c8073665c5044382b1f140900000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000a1724303d4a5763707d8a96a3ab9e9285786b5f5245382c1f0600000b1825323e4b5865717e8b98a4afa49986796d6053463a3e4b5865717e8b98a4afa49986796d6053463a2d20130700000a16202b343d43474953535353535352504c453b42464b5153575a5c5e5f5f5f5e5d5c595754514c46423b3328231c140c020000000000000d192633404c5966737f8c93939393939393939393939393939393939393939185786b5e5245382b1f120000000000000000000000060e151a1e21222625221e18120e121415181b1d1e1f1f1f1e1c191515120f11181d21242521211e1a140d0500000000000000000000000000020b141d262d333c42474c5254585b5d5e5f5f5e5d5b5854524d47433c342d251c130a000000000000020f1c2935424f5c6875828f949fa39b918b7f726d625a50483e362d24242c363e48505a616c717e879399a49e938e8175685b4e4235281b0f0200020e1a25303b454d525f60606060606060605f524c443a3025190d01000613202d394653606c78869aa4afa396897d869292877f78726e6d67676d6e6e6a5f53473a2e2114080000030f1b27323c464e5455606060606060606060606060606060606060606060606060606060606060605f5d5850463b3025190d00000000000000000000000000000000030b131a202427282d2d2d2d2d2d2d292825211b140c0300000000000000000000000000000000000000000000000000020b12191f2326272d2d2d2d2d2d2d282724201a130b0300000006131f2b37434e585f626c6c6c6c6c6c6c64625a5045392d2115080000000000000000000000000000000000000000000000000000000000000000000000000000000004111d2a36424e59636a6c6c6c6c6c6c6c67645c52473c3024170b0006121e29343f495156586060606060605a58524a40362a1f130700000000000000000000000000000000000000000000000000000000010b151f272f343846464646464646464645423d352d24190f0400000000000000010b151f272f343846464646464646464645423d352d24190f0400000000000000000000000000000000000106090b0c1313131313130d0c0a07020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a030000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000007121f2b3844505b6673808c99a3ab9e9184796d6053463b30251a0e01000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000a1724313d4a5764707d8a97a3ab9f9285786c5f52452e23170b00000c1825323f4b5865727e8b98a5b5a093867a6d6053473a3f4b5865727e8b98a5b5a093867a6d6053473a2d2014070000040f19222b32373b3c4646464646464544403a3136394045474a4d4f5152535252514f4d4a4745413a3631292117110a02000000000000000d192633404c5966737f8c999999999999999da0a7a9a29f999999999999999185786b5e5245382b1f1200000000000000000000000003090e121415191816120d07020507080b0e1112131312110f0c09080603060c111517181514120e0903000000000000000000000000000000020b141b222731373b4146474b4e5152525352514e4c4846423b37312a221c130a01000000000000000714202d3a4753606d79828f949b918b7f726d625a50483f362d241b1a242c363e48505a626c717e87939a938e81786d6053463a2d201307000005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c5e564c41362a1d1105000713202d3a4653606d798693a0b6a295887c818e99928c837f7b7a7979797b7c6e6255483b2f2215080000000a15202b343c4347495353535353535353535353535353535353535353535353535353535353535352514d463e342a1f1408000000000000000000000000000000010b151d252b303435393939393939393534312c261e150c000000000000000000000000000000000000000000000000000b141d242b303334393939393939393534302b251d150b010000030f1b26323c464e535560606060606060585650483e34291d110500000000000000000000000000000000000000000000000000000000000000000000000000000000010e1a26313d4751595e5f6060606060605a58524a41362b1f140800010d18232d373f464a4c5353535353534d4b4740382e24190e020000000000000000000000000000000000000000000000000000000007121d2731394045535353535353535353524e473f352b2015090000000000000007121d2731394045535353535353535353524e473f352b20150900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d0400000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000030f1c28333f4a54616e7b87929faca1968a7d7063574d42362a1d1307000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000b1824313e4b5764717e8a97a4ac9f9285796c5f4a3f34281c1003000c1925323f4c5865727f8b98a5ada093877a6d6054473a3f4c5865727f8b98a5ada093877a6d6054473a2d21140700000007101920272b2e2f3939393939393837342f252a2f34383a3d404344454646454443403d3a39352f2a251f170f060000000000000000000d192633404c5966737f8c8c8c8c8c8c8c8c9095a0a297928c8c8c8c8c8c8c8c85786b5e5245382b1f120000000000000000000000000000020608080c0c0a060200000000000001040506060504020000000000000105090b0b08070502000000000000000000000000000000000000020a111720262b3036393b3e41444546464544423f3b3a36302b262018100a01000000000000000006131f2c3845515c676d79828f918b7f726d625b51483f362d241b12121a242c363e48505a626c717e88938e81786d665c5044382b1f120600000714202d3a46525e6976797979797979797976685e5246392d201307000714202d3a4753606d7a8693a0ada194887b7c88949f95918c8886858586888073675a4d4034271a0d000000040f19222b32373b3c464646464646464646464646464646464646464646464646464646464646464644413b342c22180d0200000000000000000000000000000009131d272f373c40414646464646464642413d3730271e0e050000000000000000000000000000000000000000000000030d1d262e363c3f414646464646464641403c372f271d13090000000a15202a343c434749535353535353534b49453e362d22170c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000915202b353f474e52535353535353534e4c4741382f241a0e03000007111b252d343a3e3f464646464646403f3b362e261c120800000000000000000000000000000000000000000000000000000000000c18232f39434b515f606060606060605f5e5951473d31261a0e010000000000000c18232f39434b515f606060606060605f5e5951473d31261a0e0100000000000000000000000000000000000000000000000000000000000106090b0c131313130c0b09060100000000000000000000000000000000000000000000000000000000000000030d161f272d32353639393635322d271f160d03000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000b17222d3846525e6975828f9ba7a89b8f8275695e52463a2f24180d000000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b97a4ac9f938679665c5044382b1f1206000c1926333f4c5966727f8c99a5ada094877a6d6154473a3f4c5966727f8c99a5ada094877a6d6154473a2e21140700000000070f161b1f22232d2d2d2d2d2d2c2b28241a1d23292c2d3034363838393938373633302d2c29241e1a140d0500000000000000000000091623303c4956636f7d808080808080808083909d9f928580808080808080807f7265594c3f3226190c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060b151a1e252a2d2e323537383939383735322e2d2a251f1a150e060000000000000000000004101c2934404b555c676d79828a7f726d625b51493f362d241b120909121b242d363e48505a626c717e8681786d665c544a3f34281c100300000815212e3b4854616e7b86868686868686867a6d6154473a2e211407000714212d3a4754606d7a8793a0ada194877a76828f99a09d9895989292988d8073675a4d4034271a0d0000000007101920272b2e2f39393939393939393939393939393939393939393939393939393939393939393835302a221a1006000000000000000000000000000000030f1a252f3941484d4e535353535353534f4d4942393020170d02000000000000000000000000000000000000000000010b151f2e3840474c4d535353535353534e4d4841392f251a0f030000040e18222a32373b3c464646464646463e3d39342d241b1106000000000000000000000000000000000000000000000000000000000000000000000000000000000000040f19242d353d424546464646464646413f3c362f261d13080000000009131b23292e313239393939393933322f2a241c140a000000000000000000000000000000000000000000000000000000000004101c2934404b555c6c6c6c6c6c6c6c6c6c6a63594e42362a1d1104000000000004101c2934404b555c6c6c6c6c6c6c6c6c6c6a63594e42362a1d110400000000000000000000000000000000000000000000000000000000070d1216181920202020181815120c060000000000000000000000000000000000000000000000000000000000000a151f2831383e4243464643423e3831281f150a000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000006111c2a36424d5763707d89959fac9f92867b6e61554b4135291d12070000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b98a4afa49986796d6053463a2d201307000d192633404c5966737f8c99a6ada194877a6e6154473b404c5966737f8c99a6ada194877a6e6154473b2e2114080000000000040a0f1315162020202020201f1e1c180e12181c1f202427292b2c2c2c2b2a29262421201d19130e090300000000000000000000000915222f3b4854606b6f7373737373737374818e9b9e91847873737373737373726d62574a3e3125180b0000000000000105090b0b1313131307060405090b0b131313130706040005090b0b13131313070604000000000000000000000000000000000000000000000000000000000000000003090e14191e202125282a2b2c2c2b2a282521201e1a140f0a030000000000000000000000000c18232f39434b555c676d797d726d625b51493f372d241b1209000009121b242d363f48505a626c717d786d665c544a42382e23170b0000000815212e3b4854616e7b87939393939393877a6d6154473a2e211407000814212e3b4754616e7a8794a1aca093877a6f7c87929fa5a5aaa29f9f9a8d8073675a4d4034271a0d0000000000070f151b1f22222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2b29251f181008000000000000000000000000000000000814202b37414b53595b606060606060605c59544b4232291f140900000000000000000000000000000000000000000007121d2731404a52585a606060606060605b59534b41372b20140800000006101820262b2e2f3939393939393931302d29221b1209000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b242b313638393939393939393433302b241d140b0100000000010911181e2225252d2d2d2d2d2d2726231f19120a02000000000000000000000000000000000000000000000000000000000006131f2c3845515c67767979797979797979756a5e5245382c1f1206000000000006131f2c3845515c67767979797979797979756a5e5245382c1f12060000000000000000000000000000000000000000000000000000010911181e2225252d2d2d2d2524221d1811090000000000000000000000000000000000000000000000000000000005111c27313a434a4e505353504e4a433a31271c11050000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000000000e1a25303b4854606b7683909da8a3998d8073675d5145392e23180c0000000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000c1825323f4b5865727e8b98a5b5a093867a6d6053473a2d201407000d1a2633404d596673808c99a6aea194887b6e6155483b404d596673808c99a6aea194887b6e6155483b2e221508000000000000000306080913131313131312110f0c01070c101314171a1c1e1f201f1f1e1c1a171413110d0801000000000000000000000000000713202c38444f5960636666666666666874818e9b9e9184786b66666666666665625b51463a2e2216090000000000060c111517182020201f141310111517182020201f1413100c111517182020201f1413100c07010000000000000000000000000000000000000000000000000000000000000002080d111414181b1e1f1f201f1e1b191514120e0903000000000000000000000000000007121d273139434b555c676d716c625b51493f372d251b12090000000009121b242d363f48505a626b706d665c544a423830261c11060000000815212e3b4854616e7b87949f9f9f9f94877a6d6154473a2e211407000815222e3b4855616e7b88949f9fa39986796d73808c939fa2aaaaaba69a8d8073675a4d4034271a0d000000000000040a0f131516202020202020202020202020202020202020202020202020202020202020201f1f1c19140d0600000000000000000000000000000000000c1824303c48535d64686c6c6c6c6c6c6c68655d54443b3025190e0000000000000000000000000000000000000000000c18232f3943525c64676c6c6c6c6c6c6c68645d53483c3024180c00000000060e151b1f21222d2d2d2d2d2d2d2524211d1711090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121920262a2c2c2d2d2d2d2d2d2726241f1a130b0200000000000000070d121618192020202020201a1917130e08000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d798686868686868687796c5f5346392c20130600000000000714202d3a4753606d798686868686868687796c5f5346392c201306000000000000000000000000000000000000000000000000000009131b23292e31323939393932312e29231b13090000000000000000000000000000000000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a0000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000009141f2c38444f5964717e8a96a0ab9f92857a6d60544b4034281d120700000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000c1925323f4c5865727f8b98a5ada093877a6d6054473a2d211407000d1a2733404d5a6673808d99a6aea195887b6e6255483b404d5a6673808d99a6aea195887b6e6255483b2f2215080000000000000000000000060606060606050503000000000406070a0d10111213131211100d0a07060401000000000000000000000000000000030f1b27323d474f545659595959595b6874818e9b9e9184786b5e5959595959595751493f35291e1206000000000911181d2124252d2d2d2c201f1c1d2124252d2d2d2c201f1c181d2124252d2d2d2c201f1c18120b030000000000000000000000000000000000000000000000000000000000000000010507080b0e1112131312110f0c0807050200000000000000000000000000000000010b151f273139434b555c6064615a51493f372d251b130900000000000009121b242d363f4850596063605c544a423830261e140a000000000815212e3b4854616e7b8794a1acaca094877a6d6154473a2e211407000915222f3c4855626f7b8893939393928679666c77818c92989b9e9f9f9a8d8073675a4d4034271a0d000000000000000003060809131313131313131313131313131313131313131313131313131313131313131312100d08020000000000000000000000000000000000000e1a2734404d59646f7479797979797979756f65564d42362a1c11060000000000000000000000000000000000000004101c2934404b55646e7479797979797979746f64594d4034271a0e0000000000040a0f13151620202020202020181715110c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1d1f202020202020201b1a17140e08010000000000000000000106090b0c1313131313130d0c0a070200000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693939393939286796c5f5346392c20130600000000000714202d3a4753606d7a8693939393939286796c5f5346392c2013060000000000000000000000000000000000000000000000000007111b252d343a3e3f464646463f3d3a342d251b110600000000000000000000000000000000000000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d0100000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000002101b27323d4653606c7884919da8a2978b7f72665c5145392e23180c01000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000c1926333f4c5966727f8c99a5ada094877a6d6154473a2e211407000d1a2734404d5a6773808d9aa6aea295887b6f6255483c404d5a6773808d9aa6aea295887b6f6255483c2f22150900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212b353d4448494d4d4d4d4e5b6874818e9b9e9184786b5e514d4d4d4d4c4a463f372d23180d0100000009121b22292e3132393939392d2c29292e3132393939392d2c2923292e3132393939392d2c29231d150d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d151f273139434b5153575550483f372d251b1309000000000000000009121b242d363f474f545653504a423830261e140c02000000000815212e3b4854616e7b8794a1acaca094877a6d6154473a2e211407000916222f3c4955626f7c86868686868685786c656c777f868b8e919292928d8073675a4d4034271a0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1b2835414e5b687481868686868686868175695e5246382d22170b0000000000000000000000000000000000000006131f2c3845515c677480868686868686868174685b4e4135281b0e0000000000000003060809131313131313130b0a080500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090e1112131313131313130e0d0b080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a86939f9f9f9f9286796c5f5346392c20130600000000000714202d3a4753606d7a86939f9f9f9f9286796c5f5346392c201306000000000000000000000000000000000000000000000000010d18232d373f464a4c535353534b4a463f372d23180c01000000000000000000000000000000000000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f0300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000000000b161f2b3844505b66717e8b96a0a99e9184796d60554b4034281e1308000000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000d192633404c5966737f8c99a6ada194877a6e6154473b2e211408000e1b2734414e5a6774818d9aa7afa295887c6f6255493c414e5a6774818d9aa7afa295887c6f6255493c2f2216090000000000000105080b0b1313131313130c0b090501000000000000000000000000000002070a0c0d1313131313130b0a08050000000000000000040f19232b32383b3c404040414e5b6874818e9b9e9184786b5e51454040403f3e3a352d251b110700000006111b242d343a3d3e464646463a3834343a3d3e464646463a38342f343a3d3e464646463a38342f271f150b0100000000000000000000000000000000000000030608090d1012131312110f0b0707050100000306060b0f121312110e080705020000000000000000000000000000030d151f2731394045474a49453e362d251b13090100000000000000000009121b242d353d44484a46443f3830261e140c0200000000000815212e3b4854616e7b87949f9f9f9f94877a6d6154473a2e211407000815222e3b4754606a767979797979797873695b656c727a7f8284858685837e7164574b3e3124180b00000000000004090c0e0f131313131313131313131313131313131313131313131313131313131313131313100f0d09050000000000000000000000000000000000000916232f3c4956626f7c89959393939392867b6e61544a3f33281c0f030000000000000000000000000000000000000714202d3a4753606d7985929393939395897c6f6356493c3023160900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a05000000000000000000000000000714202d3a4753606d7a8693a0acac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0acac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000006121e29343f4951565860606060585651493f34291d120600000000000000000000000000000000000000000000000003101d2a3643505d69768286868276695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000000030f1c28333f4a54606d7884919da7a1968b7e72675c51453a2f24190d030000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000d1a2633404d596673808c99a6aea194887b6e6155483b2e221508000e1b2834414e5b6774818e9aa7afa295897c6f6256493c414e5b6774818e9aa7afa295897c6f6256493c2f2316090000000000060c11151718202020202020181815110c06000000000000000000000000070e1316191a202020202020181715110c060000000000000007111921272c2f30333335414e5b6874818e9b9e9184786b5e514538333332312e29231b130a000000010c18222d363f454a4b535353524745403f454a4b53535352474540393f454a4b535353524745403931271d12070000000000000000000000000000000000040a0f1315161a1d1f1f201f1e1b181413110d080b0f1213181c1f201f1e1b1514120e090300000000000000000000000000030d151f272f34383a3e3c39332c241b130901000000000000000000000009121b232b33383c3d3a38342e261e140c020000000000000815212e3b4854616e7b87939393939393877a6d6154473a2e2114070006131f2b37434e5860626c6c6c6c6c6c6c6961535b60686d72757778797876716c6155493d3023170a0000000002091015191b1c2020202020202020202020202020202020202020202020202020202020202020201d1c1915100a03000000000000000000000000000000000915222e3b4854606a7783909daa9fa3998c7f73665b5044382b1f1409000000000000000000000000000000000006121f2b37434e5864717e8a97a29f9f9d9083776b6054483b2f22150900000000000000000000000000000000000000000406070a0c0f11111213131312110f0d0b070705010000000000000000000000000000000000000000000000000003060809131313131313130b0a08050000000000000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a0300000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000916222e3a46515b62656c6c6c6c65625b51463a2e22150900000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000000000b17222d3844505c66717e8a95a0a89e9184796d60564c4135291f14090000000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000d1a2733404d5a6673808d99a6aea195887b6e6255483b2f221508000e1b2835414e5b6874818e9ba7afa396897c706356493d414e5b6874818e9ba7afa396897c706356493d3023160a000000000911171d2124252d2d2d2d2d2d2524221d181109000000000000000000010a12191e2325262d2d2d2d2d2d2524211d17110900000000000000070f161b202223262835414e5b6874818e9b9e9184786b5e5145382b262625221e18110a0100000005111d29343f485056586060605f53514b485056586060605f53514b43485056586060605f53514b43392f23180c00000000000000000000000000000003090e151b1f2222272a2b2c2c2c2a282521201d1913171c1f2024292b2c2c2a2821211e1a140d0500000000000000000000000000030d151d23292c2d31302d28221a1209010000000000000000000000000009111921272c2f302d2b28231c140c02000000000000000815212e3b4854616e7b86868686868686867a6d6154473a2e21140700030f1b27323c464e54556060606060605f5d574950565d6065686b6c6c6b6a64615a5045392d211408000000030c141b212528292d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d292826211b140c0400000000000000000000000000000007131f2c38434e5865727e8b98a2aeab9e9184786c6053463b30251a0e00000000000000000000000000000000000814212e3a47535f6a7683909ca9aea2988b7f7265594f43382c1f1307000000000000000000000000000000000001070c10131417191b1d1e1f20201f1f1e1c1a171413110d0804010000000000000000000000000000000000000000040a0f13151620202020202020181715110c060000000000000000000000000000000000000000000000000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d04000000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000b1825313e4a56626d7279797979726d62564a3d3124180b00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000000000006111c28343f4a54606c7883909da6a1968c7f72685d52453b31261a0c0300000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000d1a2734404d5a6773808d9aa6aea295887b6f6255483c2f221509000f1b2835424e5b6875818e9ba8b0a396897d7063564a3d424e5b6875818e9ba8b0a396897d7063564a3d3023170a00000009121b22292d303139393939393932312e29231b120900000000000000000a131c242a2f323339393939393931302d29221b120900000000000000040b0f1315161b2835414e5b6874818e9b9e9184786b5e5145382b1e191816120d0700000000000915212e3a45505a62656c6c6c6c605c55505a62656c6c6c6c605c554b505a62656c6c6c6c605c554b4034291c100400000000000000000000000000060e141a20262b2e2f3336383939383735322e2d2a251e22282b2d313638393937342e2d2a251f170f0500000000000000000000000000030b12181c1f202423211c17100800000000000000000000000000000000080f161c202223201f1c17110a0200000000000000000714202d3a46525e6976797979797979797976685e5246392d20130700000a15202b343c43474953535353535352514c3f444c5254585b5e5f5f5f5d575550483e33281d11050000020c151e262c3134353939393939393939393939393939393939393939393939393939393939393939393635322d261e160c030000000000000000000000000000030f1b27323d4754606d7a85929facaca1968a7d7063574d42362a1c110600000000000000000000000000000004101c2934404b55626e7b88949fabac9f92867a6d6054473d32271b0f03000000000000000000000000000000050b1012181c1f202326282a2b2c2c2c2c2c2a29272421201d1913100d07010000000000000000000000000000000000060e151b1f21222d2d2d2d2d2d2d2524211d171109000000000000000000000000000000000000000000000000000000000000000000000000030d161f272d32353639393635322d271f160d030000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000c1925323f4c5865727f868686867f7265584b3f3225180c00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000000000000000b17232e3844505b66707d89949fa89e92857a6d60574d42362a1e150a00000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000e1b2734414e5a6774818d9aa7afa295887c6f6255493c2f221609000f1c2835424f5b6875828e9ba8b0a3968a7d7063574a3d424f5b6875828e9ba8b0a3968a7d7063574a3d3024170a000006111b242d34393d3e4646464646463f3d3a342d241b0b02000000000000030d1c252e353b3f404646464646463e3d39342d241b110600000000000000000307090e1b2835414e5b6874818e9b9e9184786b5e5145382b1e120b0906010000000000000b1724313d4a56626c71797979796d675c56626c71797979796d675c5156626c71797979796d675c5145382c1f1306000000000000000000000000080f181f262a32373b3c40434546464544423e3a3936302a2d3338393e4245464544413b3a36312921170d030000000000000000000000000001070c101314171714110c05000000000000000000000000000000000000050b101316171312100b060000000000000000000005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c5e564c41362a1d11050000040f19222b32373b3c464646464646454441333a4145474b4f51525352504b49453e362c22170c00000009141e2730373d414246464646464646464646464646464646464646464646464646464646464646464643413e3830281e140a0000000000000000000000000000000a16202c3945515d6774818e9aa7b1a89b8f8275695e5246382e23170b00000000000000000000000000000006131f2c3845515c6774808d9aa6b0a79b8e8174685d5245392b21160a0000000000000000000000000000040b10161c1d23292c2d30333537383839393938373633312e2d2a25201d18120b0600000000000000000000000000000006101820262b2e2f3939393939393931302d29221b120900000000000000000000000000000000000000000000000000000000000000000000000a151f2831383e4243464643423e3831281f150a0000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000c1926323f4c5965727f8c93938b7f7265584c3f3225190c00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000000000006111c28333f4a54616b76828f99a4a1978d8073695f53463d30261c1106000000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000e1b2834414e5b6774818e9aa7afa295897c6f6256493c2f231609000f1c2936424f5c6975828f9ca8b0a3978a7d7064574a3d424f5c6975828f9ca8b0a3978a7d7064574a3d3124170a00010c17222d363f45494b5353535353534b4a453f372d1d140a0000000000010b151f2e3740474b4d5353535353534b49453e362d22170c00000000000000000000020e1b2835414e5b6874818e9b9e9184786b5e5145382b1e12050000000000000000000b1825323e4b5865717e86868686796d605865717e86868686796d60535865717e86868686796d6053473a2d20140a0000000000000000000000081119212a31363c4347494d5052525352514e4b4746413a36383f44464b4f525352514e4846423b33291f1409000000000000000000000000000000000406070b0a0805000000000000000000000000000000000000000000000407090a070603000000000000000000000000020e1a25303b454d525f60606060606060605f524c443a3025190d0100000007101920272b2e2f393939393939393835272f35393a3f4244454645433e3d39332c241a1006000004101b26303942494d4f535353535353535353535353535353535353535353535353535353535353535353504e49423a30261b1005000000000000000000000000000004111d2935414b55626f7c88959fabac9f92877b6e61544a3f34281c100300000000000000000000000000000714202d3a4753606d7985929eabaca095897c6f63564c413529190f0400000000000000000000000000060b161b21282c2f34383a3d3f42444445464646454442403e3a3936302c29241d17110a02000000000000000000000000040e18222a32373b3c464646464646463e3d39342d241b110600000000000000000000000000000000000000000000000000000000000000000005111c27313a434a4e505353504e4a433a31271c110500000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000c1926333f4c5966727f8c99988c7f7265594c3f3226190c00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000b17222d38424f59626f7c87939fa99f92867b6e61594f42382e23170c020000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000e1b2835414e5b6874818e9ba7afa396897c706356493d3023160a00101c2936434f5c6976828f9ca9aca4978a7d7164574a3e434f5c6976828f9ca9aca4978a7d7164574a3e3124170b0005111d29343f48505658606060606060585651493f2f261b11060000000007121d27314049525759606060606060585650483e34291d1105000000000000000205070e1b2835414e5b6874818e9b9e9184786b5e5145382b1e12050000000000000000000a1723303d4a5663707d8993988a7d70635763707d8993988a7d7063575663707d8993988a7d7063574a3d31261b0f03000000000000000000060f19232b333b42464e54555a5d5e5f5f5f5d5b5854524c4641424a5053575c5e5f5f5d5b54534d453b31251a0e020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f29333b42464853535353535353535346413a32281e13080000000000070f151b1f22222d2d2d2d2d2d2c2b281e24292c2d3235383939383731302d28221a12080000000915212c37424b54595c6060606060606060606060606060606060606060606060606060606060606060605c5a544c42382d2115090000000000000000000000000000010d18242f3a47535f6a7683909da9afa3998c7f73665c5044382b1f14090a0a0a0a0a0a0a0a0a0a0a0a0a0a121f2b37434e5864717e8b97a2adaa9d9083776b6054443a2f241907000000000000000000000000020a111721272c3338394045474a4c4e50515253535252514f4d4a4746413a39352f28231c140c0600000000000000000000000a15202a343c434749535353535353534b49453e362d22170c0000000000000000000000000000000000000000000000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a00000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000d192633404c5966737f8c99998c7f7266594c3f3326190c00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000000000000000006111c262f3d47535f6a74818e97a2a3988e82756b60544a3f34281f14090000000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000f1b2835424e5b6875818e9ba8b0a396897d7063564a3d3023170a00101d293643505c6976838f9c9f9f9f978b7e7164584b3e43505c6976838f9c9f9f9f978b7e7164584b3e3125180b000815212d3945505a62646c6c6c6c6c6c65625b5141382d22170b000000000c18232f3943525b63666c6c6c6c6c6c64625a5045392d211508000000000002090e1114141b2835414e5b6874818e9b9e9184786b5e5145382b1e12050000000000000000000815222f3b4855626e7b88959a8d81746758626e7b88959a8d8174675855626e7b88959a8d817467584e43372b1f12060000000000000000030e18222b353d454d53585f6266696b6c6c6b6a6865615e56524c4c545b6064696b6c6c6a67615e574d42362a1e1205000000000000000000000000000000010406070b0e101213131312100e0b07060401000000000000000000000000000000000000000000000000000000000000020d17212930363a3b4646464646464646463936302820160c02000000000000040a0f1315162020202020201f1e1c13191d202125282b2c2c2c2a2423211d171008000000000c1925313d49545d65686c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c69665e54493e3226190d00000000000000000000000000000007131d2b37434e5864717e8b97a2adab9e9184786d6053463b31251a16161616161616161616161616161616212e3a47535f6a7683909ca9aea2988b7f7265594f4332281e13080000000000000000000000030b141c222832383e44484b515356595b5d5e5f5f5f5f5f5d5c5a5754524c47454039342e261e170f07000000000000000000030f1b26323c464e535560606060606060585650483e34291d110500000000000000000000000000000000000000000000000000000000000000000d1a26323e4a545e66696c6c69665e544a3e32261a0d00000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000d1a2633404d596673808c99998c7f7366594c403326190d00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000000000000000a141d2b37434e58616d7a85929fa79e93897d70665c50443b30251a0d0300000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000f1c2835424f5b6875828e9ba8b0a3968a7d7063574a3d3024170a00101d2a3643505d6976839093939393938b7e7165584b3e43505d6976839093939393938b7e7165584b3e3225180b000b1724303d4956626c71797979797979726d6253493f33271b0f03000004101c2934404b55636e73797979797979716c6256493d3024170a00000000050d14191e2021272835414e5b6874818e9b9e9184786b5e5145382b1e12050000000000000000000714202d3a4753606d7a86979e9184786a5f606d7a86979e9184786a5f53606d7a86979e9184786a5f53473a2e21150800000000000000000a15202a343d474f575f616a6f7376787979787775716d68615e56565d666c717578797877746e695e53463a2d2114070000000000000000000000000001070d111314181b1d1f1f201f1f1d1b181413110d07010000000000000000000000000000000000000000000000000000000000050f171f252a2d2e39393939393939392e2d2a251e160e0500000000000000000003060809131313131313121210080d111314181c1e1f201f1d181714110c0600000000000e1b2834414d59656f757979797979797979797979797979797979797979797979797979797979797979797670665a4e4135281c0f000000000000000000000000000000010f1b26323c4753606d7985929fabada1968a7d7063574d42362a23232323232323232323232323232323232934404b55626e7b88949fabac9f92867a6d6054473d3221160c0100000000000000000000030c151d262d333d44484f55555c606366686a6b6b6c6c6c6b6a696664615e5653514b443f38302921191007000000000000000006131f2b37434e585f626c6c6c6c6c6c6c64625a5045392d21150800000000000000000000000000000000000000000000000000000000000000000f1c2935424e5a66707679797670665a4e4235291c0f00000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000000d1a2733404d5a6673808d99998c807366594d4033261a0d00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000000000000000000020b1b26323c46525e68727f8c95a0a59d9083786d60574d42362a1f150b01000000000000121f2c3845525f6b7885929eabada194877a6e6154473b2e211408000000000000000000000000000000000000000000000000000000000000000f1c2936424f5c6975828f9ca8b0a3978a7d7064574a3d3124170a00101d2a3743505d6a7683868686868686867f7265584b3f43505d6a7683868686868686867e7265584b3f3225180c000b1825313e4b5864717e8686868686867f72655b5044372b1f150a000006131f2c3845515c6773808686868686867e7164584b3e3125180b000000050e171f252a2d2e342d35414e5b6874818e9b9e9184786b5e5145382b1e120500000000000000000006131f2c3945515d677885929e96887b6f625d677885929e96887b6f62555d677885929e96887b6f6255483c3025190d01000000000000020f1a26313c464f5960696e767c80838585868583817e7a746d68605d686d787e8285868584817b6e6154483b2e211508000000000000000000000002080e13181d202024272a2b2c2d2c2b2a272421201d18130e090300000000000000000000000000000000000000000000000000000000050d141a1e20212d2d2d2d2d2d2d2d21201d19130c05000000000000000000000000000006060606060606050300010406070c0f11121312100b0a0805000000000000000f1c2935424f5c6875828686868686868686868686868686868686868686868686868686868686868686868276695c504336291d10000000000000000000000000000000000a151f2c3845515d6774808d9aa6b0a89c8f8275695e5346382e3030303030303030303030303030303030303845515c6774808d9aa6b0a79b8e8174685d5245392c20130400000000000000000000000b151e272f383f444f54596163676d70727577777879797978777573716d6865605d55504a423b332a22190f06000000000000000815212e3b47535f6a7679797979797979716c6256493d3024170a0000000000000000000000000000000000000000000000000000000000000000101d2a3643505d69768386868376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000010d1a2734404d5a6773808d9a998d8073665a4d4033271a0d00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000000000000000000000000000a15202a36414c56606d7883909aa4a0958c7f72695e52463e31271d1207000000000000121f2c3845525f6b7885929eabaca194877a6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976828f9ca9aca4978a7d7164574a3e3124170b00101c2936424f5b66717679797979797979726d62564a3d424f5b66717679797979797979726d62564a3d3124180b000713202d3a4653606d7984919393939184786c6053463c31261a0f02000714202d3a4753606d7985929393939184796d6053463a2d2013070000020d17202930363a3b413a38414e5b6874818e9b9e9184786b5e5145382b1e120500000000000000000004101d2935404b556a7783909d998c7f7266566a7783909d998c7f726656556a7783909d998c7f7266564c41362a1d110500000000000006121f2b37434e58606b707b82888d9091929292908e8b86817a706b606d7a828a8f91929290897d7063564a3d3023170a00000000000000000000050d14191d24292c2d31343738393939383634312d2c29241d1a140d050000000000000000000000000000000000000000000000000000000002090e12141520202020202020201413110d080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424f5c6875828f939393939393939393939393939393939393939393939393939393939393938f8276695c504336291d100000000000000000000000000000000004101d2935404b55626e7b88949fabac9f93877b6e61544a3f3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d4753606d7985929eabaca095897c6f63564c4135291d11040000000000000000000007121d273039424a505960636b7075797d7f81838485868685858482807d7a76716d67605c544d453c342a21180c030000000000000916222f3c4955626f7c868686868686867e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000010e1a2734414d5a6774808d9a9a8d8073675a4d4034271a0d01000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000040d1925303a44515c666f7d88939fa79f92867b6e61594f43392f24180c020000000000121f2c3845525f6b7885929e9f9f9f94877a6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000000101d293643505c6976838f9c9f9f9f978b7e7164584b3e3125180b000e1a26323e4a555f666a6c6c6c6c6c6c6c65625b51453a3e4a555f666a6c6c6c6c6c6c6c65625b51453a2e2215090006131f2c3845515c66727f8c97a2a0958a7d7063584e43372b1e13080714202c38444f5965717e8b97a1a2978c7f72665c5144382c1f1206000009141f29323b4246474d4745404e5b6874818e9b9e9184786b5e5145382b1e1205000000000000000000000c18242f424f5c6875828f9b9c908376685e6875828f9b9c908376685e5c6875828f9b9c908376685e5246392d2013070000000000000814212e3a47535f6a707d858f94999c9e9f9c9b9c9b98928e857d706b75828f949c9e9f9f96897d7063564a3d3023170a000000000000000000080e171e252a2f35393a3e4143454646464543413e3a39352f2a251f170f09000000000000000000000000000000000000000000000000000000000002050708131313131313131307070501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424f5c6875828f9b9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9c8f8376695c504336291d1000000000000000000000000000000000000c18242f3947535f6a7683909ca9afa4998c8073665c504949494949494949494949494949494949494949494e5864717e8b97a2adaa9d9083776b6054443a2f24190d01000000000000000000040e18232e39434b545b606b70767d8185898c8e90919292929292908f8d8a86837e79726d665f574e463c332a1e150b0000000000000916222f3c4955626f7c8893939393938b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000010e1b2734414e5a6774818d9a9a8d8074675a4d4134271a0e01000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000030709090c0c0c0c0c0c0c0c0c0c0c0c0c0c08131e2834404a54606b74818e97a1a2988e81756b61554b4035291e140a0000000000121f2c3845525f6b7885929393939393877a6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000000101d2a3643505d6976839093939393938b7e7165584b3e3225180b000a16222d38434d555b5d60606060606060585651493f3438434d555b5d60606060606060585651493f34291d11050004101c2834404b54606d7a85929fa89c8f82766a5f53473a3025190d0916232f3c4855606b7783909da99f92857a6d60544a4034281c100400020e1925303b444d52545a53514b4e5b6874818e9b9e9184786b5e5145382b1e120500000000000000000000071a2734414d5a6774808d9a9f93867a6d616774808d9a9f93867a6d615a6774808d9a9f93867a6d6154473a2e23180c000000000007131f2c38434e58626e7c8692989fa29f97928f8e8f9196999792877d707d89949ea69e989291897d7063564a3d3023170a00000000000000010a121a202930363a4045474b4e505252535252504e4b4745413a363029211b120a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424f5c6875828f939393939393939393939393939393939393939393939393939393939393938f8376695c504336291d10000000000000000000000000000000000007121d2b37434e5864717e8a97a1adab9e9184796d6056565656565656565656565656565656565656565656565f6a7683909ca9aea2988b7f7265594f4332281e1308000000000000000000020c16202834404b555c666c737d838a8e9298999b9d9e9e9f9f9f9e9d9c999993908b857f786e695f584e453c30271d120700000000000916222f3c4955626f7c88959f9f9f978b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000010e1b2834414e5b6774818e9a9a8d8174675a4e4134271b0e01000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000040b0f1315161919191919191919191919191919191918232e39424f59616d7a85929ea69e938a7d70675d51453c30261c110600000000121f2c3845525f6b7885868686868686867a6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000000101d2a3743505d6a7683868686868686867e7265584b3f3225180c0005111c27313b434a4f50535353535353534b4a453f372d313b434a4f50535353535353534b4a453f372d23180c0100000c18232e3945515d6773808d98a39f94887c6f62564c41362a1c12121f2b37434e5863707d8995a0a3988c8073675d5142392e23180c000005111e2a36424d565e6167605c554e5b6874818e9b9e9184786b5e5145382b1e1205000000000000000000000c1926323f4c5965727f8c98a4998b7e716465727f8c98a4998b7e71645465727f8c98a4998b7e7164544a4034281c1004000000000915222e3b4854606a76828f98a2a298928b8583828284878c929792857b818e9aa69e948f8684867d7063564a3d3023170a000000000000000a131c242c323b41464b5153575a5d5e5f605f5e5d5a5754514b46423b332d241c140a01000000000000000000000000000000000000000000000000000106090b0c13131313131313090806030000000000000000000000000003060809131313131313130b0b0905010000000000000000000000000000000000000000000f1c2935424f5c6875828686868686868686868686868686868686868686868686868686868686868686868376695c504336291d100000000000000000000000000000000000010f1a26313c4653606d7985929eacada1968a7d70646363636363636363636363636363636363636363636363636e7b88949fabac9f92867a6d6054473d3221160c0100000000000000000008131e28323a45515c676d78808990959b9fa2aaaba39f9d9d9c9d9ea1a9aba49f9d97928b837b6f6a5f574d42392e23180c02000000000916222f3c4955626f7c8895a2aca4978b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000020e1b2835414e5b6874818e9b9a8e8174675b4e4134281b0e01000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000070f161b20222325252525252525252525252525252525252527303d46525e68717e8a949ea59e9184796d60584e42382e23170b02000000111e2b3744505d6873787979797979797976685e5246392d20140700000000000000000000000000000000000000000000000000000000000000101c2936424f5b66717679797979797979726d62564a3d3124180b00000a151f2931383e4243464646464646463f3d3a342d242931383e4243464646464646463f3d3a342d241b110600000007121d2935414c55616e7b86929fa69a8e8174685e5246392e231814212e3a47535f6a76828f9ca79f92867a6d61554b4030271c120700000714202d3a46525e696e746d675f585b6874818e9b9e9184786b5e5145382b1e1205000000000000000000000b1724313e4a5764717d8a97ab9b8e82756664717d8a97ab9b8e8275665c64717d8a97ab9b8e8275665c5144382c1f1206000000000916232f3c4956626f7c89949fa79f92867e79767576777b7f858f948f8283909daa9c8f82797779796d6053473a2d20140700000000000009121c252e363e444c52555d6064676a6b6c6c6c6b696764605d55524d453f362e261c1309000000000000000000000000000000000000000000000000060d12161819202020202020201615130f0a04000000000000000000040a0f13151620202020202020181715110c0600000000000000000000000000000000000000000e1b2834414d59656f757979797979797979797979797979797979797979797979797979797979797979797670665a4e4135281c0f00000000000000000000000000000000000009151f2c3845515c6673808d9aa4afa99c8f82757070707070707070707070707070707070707070707070707074808d9aa6b0a79b8e8174685d5245392c201304000000000000000000010d1925303a44515b606d79828d929d9fa7a8a19e999992919090919297979b9fa4a9a19e9590857c6f695f544b4034281e1408000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000020f1b2835424e5b6875818e9b9b8e8174685b4e4135281b0e02000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000007111921272c2f30323232323232323232323232323232323232323235414c56616c75828f98a2a1968d80736a5f544a3f34281d140a0000000f1c2834404c5761686b6c6c6c6c6c6c6c6c5e564c41362a1e1105000000000000000000000000000000000000000000000000000000000000000e1a26323e4a555f666a6c6c6c6c6c6c6c65625b51453a2e2215090000030d171f272d3236373939393939393932312e29231b1f272d3236373939393939393932312e29231b120900000000000d19242f3a46525e6874818e9aa49f92867a6d61544a4034281c1d2a36414c56626e7b88949fa3998d8174685e52433a2f1e150b0000000814212e3b4754616e7b80796f6a605b6874818e9b9e9184786b5e5145382b1e1205000000000000000000000916232f3c4956626f7c8995ab9f9285796d626f7c8995ab9f9285796d60626f7c8995ab9f9285796d6053463a2d201309000000000d1a2733404d5a6673808d99a69f958a7d716d666869696e737a828e938f90959fa298887b6f676d6d675c5145382c1f13060000000000050f1b242e37404850565e61676d71747678797979787674716d67615e57504840382e251b0f06000000000000000000000000000000000000000000010911181e2224252d2d2d2d2d2d2d23221f1b160f0700000000000000070f161b1f22232d2d2d2d2d2d2d2524211d171109000000000000000000000000000000000000000c1925313d49545d65686c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c69665e54493e3226190d00000000000000000000000000000000000004101c2834404b54616e7b87939facac9f93877d7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7d85929fabaca095897c6f63564c4135291d110400000000000000000005111d2935414c56626d75818e949ca4aba39f96918c88868483838485878a8f939a9fa7a79f9791857b6e665c51453b3025190d000000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000020f1c2835424f5b6875828e9b9b8e8175685b4e4235281b0f02000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000040f19232b32383b3c3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f44505a616e7b86929fa69f92877c6f665c50443c2f261b110600000c18242f3b454f575d5f606060606060605f524c443b3025190e02000000000000000000000000000000000000000000000000000000000000000a16222d38434d555b5d60606060606060585651493f34291d1105000000040d151c2226292a2d2d2d2d2d2d2d2524221d1811151c2226292a2d2d2d2d2d2d2d2524221d18110900000000000008131e2a36414d56626e7b87939fa3988c7f73665c5144382c1f202d3946525e6874818e9aa69f92877b6e61564c4131281d0c030000000815212e3b4854616e7b87837c726c656874818e9b9e9184786b5e5145382b1e1205000000000000000000000814212e3b4754616e7a8799a3a297897c70636e7a8799a3a297897c7063616e7a8799a3a297897c706356493d31261a0e02000000101d293643505c6976838f9ca99d9083766c605c54575e61686d78818e949d9fa79f9285796a5f60605c554b4034291c100400000000030d17212d364049515a61686e747a7e8183858586858583817e7a746e69625a524a40372d21180e03000000000000000000000000000000000000000009131b23292e3132393939393939392f2e2b2720191007000000000007101920272b2e2f3939393939393932312e29221b12090000000000000000000000000000000000000915212c37424b54595c6060606060606060606060606060606060606060606060606060606060606060605c5a544c42382d211509000000000000000000000000000000000000000c18232e3946535f6976828f9ca9afa499938a89898989898989898989898989898989898989898989898989899297a2adaa9d9084776b6054443a2f24190d010000000000000000000713202d3946525e68727f8b939ea6aba399928c84807c7977767677787a7e828790959ea5a9a1979083796d60564c41362a1c11060000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b0000000000000000000000000000000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000020f1c2935424f5c6875828f9b9b8e8275685b4f4235281c0f02000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000203101d2a3643505d69768390908376695d5043362a1d10030200000000000000000b16212b353d4448494c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c525e69727f8b949fa3999083786d60574d41382d22170b000007131e29333d454c5052535353535353535346413b32291e1408000000000000000000000000000000000000000000000000000000000000000005111c27313b434a4f50535353535353534b4a453f372d23180c0100000000030a11161a1c1d20202020202020181815110c060a11161a1c1d20202020202020181815110c0600000000000000010e1925303b47535f6975828f9ba69e9184796d6053463d32272834404b55616d7a86929fa69b8e8175695f53443a301f160c000000000815212e3b4854616e7b8790867f776e6974818e9b9e9184786b5e5145382b1e1205000000000000000000000613202d394653606c7986929fa99a8d8073676c7986929fa99a8d807367606c7986929fa99a8d807367574d42372b1e1206000000111e2b3744515e6a7784919da6998d80736659504a4d52565e666d78829099a3aa9e9184776b585353514b43392f23180c000000000009141f29333f48515b636c717a80868a8d909192939291908d8a86817b716d645c52493f332a2015090000000000000000000000000000000000000009121b252d343a3e3f464646464646463c3b38322b22190f04000000040f19222b32383b3c464646464646463e3d3a342d241b1108000000000000000000000000000000000004101b26303942494d4f535353535353535353535353535353535353535353535353535353535353535353504e49423a30261b10050000000000000000000000000000000000000007121d2a36424d5764707d8a96a1adaba49f9796969696969696969696969696969696969696969696969696969fa2a9aea2988b7f7265594f4332281e130800000000000000000003101c28343f4a54616d7a85929fa5aea39992877f79736f6d666a696a686e71757c838f939ea7a9a0958c8073685e5246382d22170b0000000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b0204050606060504020000000000000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000000000000000000000030f1c2936424f5c6975828f9c9b8f8275685c4f4235291c0f02000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000050a0f12101d2a3643505d69768390908376695d5043362a1d10120f0a050000000000030f1b27323d474f54565858585858585858585858585858585858585858585858585857606c77828f97a2a0958c7f72695f53493f33271b0f0300020d17212b333b404445464646464646463b3936302920170d020000000000000000000000000000000000000000000000000000000000000000000a151f2931383e4243464646464646463f3d3a342d241b110600000000000000050a0e1010131313131313130c0b0905010000050a0e1010131313131313130c0b09050100000000000000000008141f2b37424d57626f7c89949fa1978a7e7164594f44382c2c3845515c67737f8c98a39f94887c6f62574d4232291e0d04000000000815212e3b4854616e7b8798928c827b7174818e9b9e9184786b5e5145382b1e12050000000000000000000005121f2b3744505b657784919eaa9d91847769657784919eaa9d918477695f657784919eaa9d918477695f53473a2d211408000000121e2b3845515e6b7884919ea5988b7e7265584b3f42464c545c666f7c87929faa9d9084776a5d514745403931271d120700000000020e1a25313b45505a636d737e858d92989a9d9a9998999a9c9a98928d867e736e645b51463c31261a0f04000000000000000000000000000000000008111a242d373f464a4c535353535353534947433d342b20160a0000000a16202b343d434749535353535353534b4a453f362d241a1107000000000000000000000000000000000009141e2730373d414246464646464646464646464646464646464646464646464646464646464646464643413e3830281e140a0000000000000000000000000000000000000000000e1a26313b4653606d7984919eabb5afaca3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3abadb3ac9f92867a6d6054473d3221160c0100000000000000000006121f2b3844505c6673808d97a2aba79f92877d726d6762605c545d565e61646a6f79818f95a0aba79f92867a6e61544a3f33281c0f0300000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180c0e101213131312100e0b08070502000000000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000003101c2936434f5c6976828f9c9c8f8275695c4f4236291c0f03000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000010910161b1e20202a3643505d69768390908376695d5043362a20201e1b161009010000000713202c38444f596063656565656565656565656565656565656565656565656565656565656e7b85929fa79f92867b6e655b5044372b1f12050000060f1921292f343738393939393939392e2d2a251e170e0500000000000000000000000000000000000000000000000000000000000000000000030d171f272d3236373939393939393932312e29231b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020e1a26313c4854606a7683909ca79d9083776b6054483b312d3a4653606d7985919ea79c8f82766a5f54453b3120170d00000000000815212e3b4854616e7b879298948f857e74818e9b9e9184786b5e5145382b1e120500000000000000000000030f1b27333f49536976838f9ca9a096887b6e6976838f9ca9a096887b6e616976838f9ca9a096887b6e6155483b2f24190d010000111e2a3744515d6a7784909da5988b7f7265544a413d3b424b545f6a75828f9ca89d9084776a5d514438342f271f150b010000000005121e2a36424d57626c737f8a92979f9f97918e8c8b8c8e91969e9f98928b80736d62584e43372b21160b0000000000000000000000000000000007101a232c363f495156586060606060606056544e463d32271b0f0300030f1b27323d464e545660606060606060585650483f362c2319100700000000000000000000000000000000020c151e262c3134353939393939393939393939393939393939393939393939393939393939393939393635322d261e160c0300000000000000000000000000000000000000000009141f2c3844505c6673808c99a3afbbb9b1acaa9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9fa7a9afb8bab1a79b8e8174685d5245392c201304000000000000000000000713202d3a4653606d7985929b9d9e9f958b7e716b605c5553514a504c5254585f676d78839099a3aea2988c8073665b5044382b1f120600000916222f3c4955626f7c8895a2afa4978b7e7164584b3e312518191b1d1f1f201f1f1d1b181414110e080200000000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000003101d293643505c6976838f9c9c8f8276695c4f4336291c1003000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000010a131b21272b2d2d2d3643505d69768390908376695d5043362d2d2d2b27211b130a0100000915222f3b4854606b6f7272727272727272727272727272727272727272727272727272727272727e8b97a1a3989082776c605346392d201306000000070f171e24282b2c2d2d2d2d2d2d2d21201e19140d05000000000000000000000000000000000000000000000000000000000000000000000000040d151c2226292a2d2d2d2d2d2d2d2524221d181109000000000000000000000105070810101010101010101010101010101010101010101008070501000000000000000000000000000000000915202c38434e5863707d8a95a0a095897c6f63574d423638444f5964717e8b97a1a095897d7063584e43332a1f0e0500000000000613202d394653606c787f86909597928a81818e9b9e9184786b5e5145382b1e120500000000000000000000000b17222d414e5b6874818e9ba7a8988c7f726874818e9ba7a8988c7f72656874818e9ba7a8988c7f7265554c4135291d11040000101c2936434f5c6976828f9ca79a8d8074665c524c4a4847464e5865717e8b98a49d9084776a5d51443729231d150d0300000000000714212d3a46535e69717e8b919fa297928b85817f7f8081848a9196a09f928c7f726a5f53473d32271b10010000000000000000000000000000061019222c353e48515b62656c6c6c6c6c6c6c6260584e43382b1f13060006131f2b38434e5860626c6c6c6c6c6c6c65625a50483e352b22190f0600000000000000000000000000000000030c141b212528292d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d292826211b140c040000000000000000000000000000000000000000000003101c28343f4a54616e7b87929facb9b1a7a0939393939393939393939393939393939393939393939b9ea5afb8aca095897c6f63564c4135291d1104000000000000000000000a1623303d495663707c898c8e9092979083786c6059514b464440434146474e555d666f7c86929facaa9e9184786c605346392d20130600000916222f3c4955626f7c8895a2afa4978b7e7164584b3e31252225282a2b2c2d2c2b2a282521201e19140f0a040000000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000003101d2a3643505d697683909c9c8f8376695c504336291d1003000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000009131c252c33373939393943505d69768390908376695d50433939393937332c251c13090000091623303c4956636f7c7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f85919eaa9f948b7f7265584b3f3225180c00000000060d13181c1e1f202020202020201414110e08020000000000000000000000000000000000000000000000000000000000000000000000000000030a11161a1c1d20202020202020181815110c0600000000000000000002080d1114141c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1414110d08020000000000000000000000000000030f1b27323d4653606c7884919da79b8f8275695f53463a3c4854606b7783909da89d9083776b6054463c3221180e00000000000006121f2b3844505b666c727c838c9299938e8e939e9e9184786b5e5145382b1e12050000000000000000000000061a2633404d596673808c99a6a99c8f82766773808c99a6a99c8f8276676673808c99a6a99c8f8276675d5145392c20130600000c1926333f4c5966727f8c99a59e9184796d605d5656555453505663707c8996a39d9084776a5d5144372a18120b03000000000006121f2b37434e58616e7b86929fa29792857e787473727374787d849095a09f92867c6e62594f44382c1e130800000000000000000000000000060f18222b343e47505a626d72797979797979796f6a6054473b2e221508000815222e3b4754606a6f79797979797979716c625a50473d342b21180f050000000000000000000000000000000002091015191b1c2020202020202020202020202020202020202020202020202020202020202020201d1c1915100a030000000000000000000000000000000000000000000000000c17232e3846525e6975828f9ca8b2aca095898686868686868686868686868686868686868686868e939ea9b4aa9d9084776b6054443a2f24190d01000000000000000000000814212e3b4754616e7b7e7f81838587887e71655b5045403a38343036393c434b545f6a75818e9baaada196897c6f6256493c2f23160600000916222f3c4955626f7c8895a2afa4978b7e7164584b3e312d2e32353738393939383735312e2d2a251f1b150d0701000000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000004101d2a3743505d6a7683909d9c908376695d5043362a1d1003000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000005101b252e373e434646464646505d69768390908376695d504646464646433e372e251b1005000e1b2734414e5a6774808b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b9197a1ada69b8e8175685b4f4235281c0f000000000002070c0f11121313131313131308070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000050a0e1010131313131313130c0b090501000000000000000000050d14191e202129292929292929292929292929292929292929292921201e19140d0500000000000000000000000000000a161f2b3744505b65717e8b96a19f93877b6e61554c41424e5763707d8995a0a0968a7e7164594f44342a200f06000000000000030f1c28333f4a545b606a6e787f8690959b9b9ea59e9184786b5e5145382b1e120500000000000000000000000b1825323e4b5865717e8b98a4ac9f92867a6d717e8b98a4ac9f92867a6d65717e8b98a4ac9f92867a6d6054473a2d22170b00000915222f3c4855626f7c88939ea0968c7f746d6865636261605c5f626f7b8895a29d9084776a5d5144372a1e07010000000000000815212e3a47535f6a76828f98a29f92857b716c66666566656c707a839099a3989083766b6054483a2f24190d010000000000000000000000050e17212a343d474f59616c727f868686868686867c6f6256493c2f231609000916232f3c4956626f7c868686868686867e716c61594f463c332a21170e05000000000000000000000000000000000004090c0e0f131313131313131313131313131313131313131313131313131313131313131313100f0d0905000000000000000000000000000000000000000000000000000006111c2a36424d5763707d8a96a1acaa9d9083797979797979797979797979797979797979797979818e9ba7aea2988b7f7265594f4332281e130800000000000000000000000714202d3a46525e696e71737476787a7c796d6053493f46464544423f3b3a39424e5863707d8998a2aea8998c7f7266594c3f2d22170b00000916222f3c4955626f7c8895a2afa4978b7e7164584b3e373a3b3f4143454646464543413e3b3936302b272018130c040000000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000004111d2a3744505d6a7783909d9d9083766a5d5043372a1d1004000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a16212c3740494f5353535353535d69768390908376695d5353535353534f4940372c21160a000e1b2734414e5a6774818d9898989898989898989898989898989898989898989898989898989898989ea1a9b3a89b8e8175685b4f4235281c0f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e171e252a2d2e3636363636363636363636363636363636363636362e2d2a251e170e0500000000000000000000000000030f1b27333f4953606d7984919ea4998d8074675d514547535f6a75828f9ca79e9184786d6053463d3320190e00000000000000000b17222d38424a50585f666d727c838c9299a0a79e9184786b5e5145382b1e120500000000000000000000000a1723303d4a5663707d8996a3aea3998a7d71707d8996a3aea3998a7d7164707d8996a3aea3998a7d7164544a3f33281c0f03000815212e3a47535f6a75828f97a29c918c807a7572706e6d6d666c6c6f7b8895a29d9084776a5d5144372a1e1104000000000003101c28343f4a54626f7c88949fa0958a7e7169605b5458535b60686e7b86929f9f95897d7063564c4135291d110400000000000000000000040d172029333c464f59616b717e88939393939791847a6d6154473a2e211407000714212e3a4754616d7a84919793939392877e706b60584e453c332920160d0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a25303b4653606c7884919eabaca095897c6f6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6d7a86929facac9f92867a6d6054473d3221160c01000000000000000000000005111e2a36424d575e616466686a686d6f6d675d515152535352514e4c4847423c4653606c7885929faba89b8f82756853493f33271b0f03000916222f3c4955626f7c8895a2afa4978b7e7164584b3e4246484c4e505252535252504e4b4746413b373229241d160d0500000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000004111e2a3744515d6a7784909d9d9083776a5d5044372a1d1104000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000f1b27333e49525a5f60606060606069768390908376696060606060605f5a52493e33271b0f000e1b2734414e5a6774818d9aa5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5abadb3aca89b8e8275685b4f4235281c0f00000000000000020507080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0b0906010000000000000000000000000000000000000000000000020d1720293036393b4343434343434343434343434343434343434343433b3936302920170d02000000000000000000000000000b17222d3844515c66727f8c97a29f92857a6d60544a4c56626e7b87939fa1978b7e72665c5044382b1f1207000000000000000006111c262f383f444e545c606a6f788087909593939184786b5e5145382b1e120500000000000000000000000815222f3b4855626e7b8895a99f9f9b8e81746e7b8895a99f9f9b8e8174666e7b8895a99f9f9b8e8174665b5044382b1f12060006121f2b37434e58616e7b8592979f9c928d86827f7d7b7a79797978787c8895a29d9084776a5d5144372a1e1104000000000006121f2b3844505c6674818d9aa69d9083786c6057504a4c4950565f6974818d9aa79b8e8175685d5245392c201306000000000000000000030d161f29323b454e58606b707d87929aa4a29791857b6e685e5246392d201307000713202d3946525e686e7b859197a2a39992867d706a60574e453b32281f160c030000000000000000000000000000060a0e1011131313131313130b0a08080b0d0e131313131313130e0d0b07030000000000000000000000000000000000000000000000000000000000000000000000000000000009141f2b3844505b66727f8c99a3aea79a8d8174675c606060606060606060606060605765717e8b98a2aea79b8e8174685d5245392c201304000000000000000000000000020e1a25303b454d525457595b565d6062605d555c5e5f5f5f5f5d5b5955534d4644505b6576838f9ca9aa9e918477655b5044372b1f1205000916222f3c4955626f7c8895a2afa4978b7e7164584b464d5355585b5d5e5f605f5e5d5b5854524d47433d352f281f170f05000000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000004111e2b3744515e6a7784919d9d9084776a5d5144372a1e1104000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c7683909083766c6c6c6c6c6c6c6c645a4f43372b1e12000e1b2734414e5a6774818d9a9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9b8e8275685b4f4235281c0f000000000003090e12141519191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191816120d070000000000000000000000000000000000000000000008141e29323b4146474f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4746413b32291e14080000000000000000000000000006111b2834404a54606d7a85929fa2988b7f72665b50525e6874818d9aa49e9285796d60544a3f34281c10030000000000000000000a141d262d333c424a50585f666d737c838686868684786b5e5145382b1e120500000000000000000000000714202d3a4753606d7a8697939393939285796d7a8697939393939285796c6d7a8697939393939285796c605346392d20130600030f1b26313c46535e696f7c858f949c9f98928f8c898887868685858584919eaa9d9084776a5d5144372a1e110400000000000713202d3a4653606d7885929fa9988b7f72655b50443f3f3f444d57626f7c8897a19f92867a6d6054473a2d2114070000000000000000030c151f28313b444d575f6a6f7d869299a3a29892857c6f695f564c4135291d11050005111d2935414c565f696f7c859298a2a39892867c6f6a5f574d443a31281e150c020000000000000000000000040b11161a1d1e2020202020202018171514171a1b202020202020201a1a17130e08010000000000000000000000000000000000000000000000000000000000000000000000000000030f1c28333f4a54616e7a86929facab9f9285796d60535353535353535353535353535f697683909caaaca095897c6f63564c4135291d11040000000000000000000000000009141f29333b4246474a4c4e4c52545c606366696b6c6c6c6b6a6865625f5753504a536773808d9aa6ac9f9286796c605346392d201306000916222f3c4955626f7c8895a2afa4978b7e7164585053575f6165686a6b6c6c6c6b6a6864615e56544e45403a312921170f050000000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000005111e2b3844515e6b7784919e9d9184776a5e5144372b1e1104000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000013202d3946535f6c767979797979797979839090837979797979797979766c5f5346392d2013000e1b2734414e5a6774808d9393939393939393939393939393939393939393939393939393939393939393939393938e8275685b4f4235281c0f00000000060d141a1e2122262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262525221e1811090100000000000000000000000000000000000000010d1925303b444c52545c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c54524c443b3025190d01000000000000000000000000000c18232e3945515d6773808d98a39e9184786c605354616d7a86929fa2988c7f73675c5142382e23170b00000000000000000000020b141c222830383f444e545c606a6f77797979797872685c5043372a1d1104000000000000000000000006131f2c3945515d677885868686868686867c6f7885868686868686867c6f677885868686868686867c6f6256493c2f23160900000a15202a36424d57606a6f7b828a8f9299999b9896959499929292919196a1aa9d9084776a5d5144372a1e110400000000000915222f3c4855626f7c8897a2a197887b6e6153493f332d333b4653606c7985929ea399897d706356493d3023160a00000000000000020b151e27313a434c565f696f7c859298a2a39992867d6f6a5f574d443a3025190d0100010d1925303a444d575f6a6f7d869299a3a29892857c6e695e564c433a30271e140a00000000000000000000050d151c2227292a2d2d2d2d2d2d2d2524211f2426272d2d2d2d2d2d2d2726231f19120b0200000000000000000000000000000000000000000000000000000000000000000000000000000b17222d3846525e6875828e9ba8ada2978a7e7164574d42464646464646463f4a54626e7b88949fabaa9d9084776b6054443a2f24190d0100000000000000000000000000020d17202930363a3b404850565d60666d70737677787979787775726e6964605c545966727f8c99a5aea399877a6d6154473a2e211407000916222f3c4955626f7c8895a2afa4978b7e7164545c6064696e72747678797979787674716e68626058514b433b332921170d0300000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000005121e2b3845515e6b7884919e9e9184776b5e5144382b1e1105000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000013202d394653606c798686868686868686909494908686868686868686796c605346392d2013000e1b2734414e5a67748086868686868686868686868686868686868686868686868686868686868686868686868686868175685b4f4235281c0f000000060f181f262a2d2e3232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232312e29231b13090000000000000000000000000000000000000005111e2a36414c565e61696969696969696969696969696969696969696969615e564c41362a1e11050000000000000000000000000007121c2935414b55616e7a86929fa0968a7d7064585c66737f8c98a29f92857a6d60554b4030261c11060000000000000000000000020a11171e262e343c424a51585f626a6c6c6c6c6b6860564b3f33271b0f02000000000000000000000004101d2935404b55687378797979797979796f6a7378797979797979796f6a687378797979797979796f6a6054483b2e2215090000030e1a25313b454e5860696e767d8286898c8e8f90909191919292929399a4aa9d9084776a5d5144372a1e110400000000000b1825323e4b5865717e8b98a99e928578695f5341382d222b3744505b6575828f9cab998c7f7266594c3f3326190c000000000000000a141d263039434c565e686e7b859197a2a49a92877d706b60584e453b32281e130800000008131e28323b454e58606b707d879299a4a19791847b6e685e554b433930261c11060000000000000000040d171f272e3336373939393939393931302d2b303334393939393939393433302b241d140b010000000000000000000000000000000000000000000000000000000000000000000000000006111c2a36414c5663707d8996a0aca99c8f8276695e5246382d393939393844505c6673808d99a6aea2988b7f7265594f4332281e1308000000000000000000000000000000050e171f252a38404a525a61686d73797d8082848586868584817f7b77716d66605865717e8b98a4b4ab94887b6e6155483b2e221508000916222f3c4955626f7c8895a2afa4978b7e716460666d71777b7f8183858586858583817e7b756f6a605d554d453b33291f150b01000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000005121f2b3845525e6b7885919e9e9184786b5e5145382b1e1205000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000013202d394653606c7986939393939393939c9f9f9c9393939393939386796c605346392d2013000d1a26333f4c58646e747979797979797979797979797979797979797979797979797979797979797979797979797979756f65594d4034271b0e0000030d18212931363a3b3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3e3a342d251b11070000000000000000000000000000000000000714202d3946525e686e7676767676767676767676767676767676767676766e685e5246392d20140700000000000000000000000000000d18242f3a46525e6874818e99a49c9083766a60606d7984919ea3998d8073685d5243392f1e140a0000000000000000000000000000060c141c2328303940444e54555d606060605e5c564e443a2f23170b000000000000000000000000000c18242f39435761686b6c6c6c6c6c6c6c6260686b6c6c6c6c6c6c6c626061686b6c6c6c6c6c6c6c6260584e43382c1f130700000009141f29333c464e575f626c70757a7d7f8182838484848585858687939faa9d9084776a5d5144372a1e110400000000000e1b2734414e5a6774808d9aa79d9083766a574d422f261b27333f49536774808d9aa79b8f8275685c4f4235291c0f00000000000006111b262f38424b555d686e7a849197a1a49f93887e716b61594f463c332a20160c02000000020c16202a333c464f59616b717e87939fa3a19691847a6d675d554b42382e2317130a000000000000000b151f2931393f4244464646464646463e3d39363c3f4146464646464646413f3c362f261d120800000000000000000000000000000000000000000000000000000000000000000000000000000d1925303b4854606b7784919daaac9f93877b6e6153493f33272d2d2d3a4653606d7984919eabac9f92867a6d6054473d3221160c01000000000000000000000000000000020c16202c36404a525c646c717a8085898d8f9192929292908e8c88837e786f6a6264717d8a97a4aea195887b6e6255483b2f221508000916222f3c4955626f7c8895a2afa4978b7e71646a6f787e83888b8e909192939291908e8b86827c746d675e574d453b31271d1207000000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000005121f2c3845525f6b7885929e9e9185786b5e5245382b1f1205000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000013202d394653606c798689898989898989909595908989898989898986796c605346392d2013000b1724303c47525c64676c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c68655d53483d3125180c000009141f29333b4246484c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4a463f372d23180d0100000000000000000000000000000000000814212e3b4754616e7a8282828282828282828282828282828282828282827a6e6154473b2e211408000000000000000000000000000007131d2a36414c56626e7b87939f9f94887c6f6264717e8b97a19f92867b6e61564c4131271d0c02000000000000000000000000000000020a11171e272e343c434749515353535351504b443c32281d12070000000000000000000000000007121d2731454f575d5f6060606060606056545d5f606060606060605654575d5f6060606060606056544e463d32271b0f030000020e1a25313b454d5354575a6164686d7072747576777778787878797c8895a29d9084776a5d5144372a1e110400000000000f1c2936424f5c6975828f9ca89b8e8175685b4e42312817222d3f4c5865727f8b98a59d9083766a5d5043372a1d100000000000091217222d38414a545d676d7a839096a0a49c928b7f726c61594f473d342a21180e040000000000040e18212a343d464f59616c727f8b919ca4a0969083796d675c544a3f3428251c1209000000000006111c27313b434a4f51535353535353534b494541474c4e535353535353534d4c4740382f24190e030000000000000000000000000000000000000000000000000000000000000000000000000008141e2c38444f5965727f8c98a3aea4998c7f73655b5044372b1f2a36414c5663707d8a97a1ada79b8e8174685d5245392c2013040000000000000000000000000000000008131e28323e48525c646e737e858d9297999c9e9f9f9f9e9d9b9895908b847c726d64717d8a97a4aea295887b6f6255483c2f221509000916222f3c4955626f7c8895a2afa4978b7e716c717c838b9095989b9d9e9f9f9f9e9d9b99928f8781796e695e574d43392f23180c030000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000006121f2c3945525f6c7885929f9e9285786b5f5245382c1f1205000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1723303d4a5663707d7d7d7d7d7d7d7d839090837d7d7d7d7d7d7d7d7063564a3d3023170a0008141f2b36414a52585a60606060606060606060606060606060606060606060606060606060606060606060606060605b59534b41372c20140800020e1a26313b454d535559595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959585651493f34291e120600000000000000000000000000000000000815212e3b4854616e7b878f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f877b6e6154483b2e2115080000000000000000000000000000010e1925303b47535f6975828f9ba69b8e8175686b7783909da49a8e8174695e52443a301f150b000000000000000000000000000000000000060c151c232832373b3c444646464645433f3a322a20160c0100000000000000000000000000010b151f333d454c505253535353535353494850525353535353535349484c5052535353535353534948433d342b21160a00000005121e2a36424d575e6163646566676663666869696a6b6b6b6b6c6f7b8895a29d9084776a5d5144372a1e11040000000000101d2a3643505d697682909ca79a8d8174675a4e4134271b25313e4b5864717e8b97a49d9184776a5e5144372b1e110000000008121b2427333f49535c666d79829095a0a59d928c7f736d625a50473e352b22180f0600000000000000060f18222b343d47505a626d727f8c929da59f958f82796d665c504440372e241b1208000000000a16222e39434d555b5d606060606060605856504a52585a606060606060605a58524a40362b1f13070000000000000000000000000000000000000000000000000000000000000000000000000002101c27333d4754616d7a86929facab9e9184786c6053463a2f242d3946525e6875828f9ba9aca095897c6f63564c4135291d1104000000000000000000000000000000010d1925303a44505a646e73808a92979ea1a9a9a8a19e9c9b9a9b9d9f9d9591877f736e717d8a97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa4978b7e71717e8790959da09e9c9b9a9b9c9ea1a9aba39f9a938e847b6e695e554b4034292015090000000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000006131f2c3946525f6c7985929f9f9285786c5f5245392c1f1200000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000916222f3c4854606b70707070707070768390908376707070707070706b6054483c2f22160900030e1a242f3841474c4e53535353535353535353535353535353535353535353535353535353535353535353535353534f4d4841392f251a0f040005121e2a36424d575f616565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565625b51463a2e22160900000000000000000000000000000000000815212e3b4854616e7b87949c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c94877b6e6154483b2e21150800000000000000000000000000000008141e2b37424d57626f7c89949f9f92867b6e707d8995a09f93877c6f62574d4232281e0d0300000000000000000000000000000000000000030b121820262b2e2f37393939393837332f2820180f05000000000000000000000000000000030d212b333b404445464646464646463c3b4445464646464646463c3b404445464646464646463c3b38322b22190f040000000714212d3a46535e696e7071727374736d63545c5d5d5e5e5e5f626f7b8895a29d9084776a5d5144372a1e11040000000000111e2a3744515d6a7783909da69a8d8073675a4d4034271a24313e4a5764717d8a97a49e9185786b5e5245382b1f12000000060f1a242d363f44505b656d78828f949fa69e938d80746d635b51483e352c23191006000000000000000000061019222c353e48515b636d73808d939da59f948f81786d605c52493f362d241a0f060000000e1a27333f4a555f676a6c6c6c6c6c6c6c64625a525c64676c6c6c6c6c6c6c67645c52473c3023170b00000000000000000000000000000000000000000000000000000000000000000000000000000b16202d3946525d6875818e9ba7aca096897c7063554b4135292e3a4754616d7a86929facaa9d9084776b6054443a2f24190d0100000000000000000000000000000005111d2935414c56616c73808d929fa2a9aaa29f9996918f8e8d8e9092999d99928c8073717d8a97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa4978a7e717e8892999e9896918f8e8d8e8f92979b9fa4aca49f9691847b6e675c51453c31261a0e0200000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000613202c3946535f6c7986929f9f9285796c5f52462e23170b00000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000713202c38444f5960636363636363697683909083766963636363636360594f44382c201307000008131d262f363c3f41464646464646464646464646464646464646464646464646464646464646464646464646464642403d372f271e130900000714212d3a46535f696e72727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272726d62564a3e3125180b00000000000000000000000000000000000815212e3b4854616e7b8794a1a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a194877b6e6154483b2e211508000000000000000000000000000000020e1a26313c4754606a7683909ca3998c807375828f9ca69c8f82756a5f53453b3020160c00000000000000000000000000000000000000000000070c151b1f22222a2d2d2d2d2b2a27231d160f0600000000000000000000000000000000000f1921292f343738393939393939392f2e3738393939393939392f2e343738393939393939392f2e2c2721191007000000000815212e3b4854616e7b7d7e7f7f807f73665b50505151515256636f7c8996a29c8f8376695c504336291d10030000000000111e2b3844515e6b7784919ea6998c807366594d4033261a24303d4a5763707d8a96a39f9285796c5f5246392c1f130000030e18212c363f48515b606c77818e949ea69e948e81776c605b52493f362c231a1007000000000000000000000007101a232c363f49515b646e74818e939ea69e938e81746e635b51483f362c21180e030000101d2936424f5b67717779797979797979716c6258646e7479797979797979746e64584c3f33261a0d000000000000000000000000000000000000000000000000000000000000000000000000000005111d2935414c56636f7c8995a0aca89b8e8174675d5145392c37434e5865727f8b99a3aea2988b7f7265594f4332281e1308000000000000000000000000000000000713202d3946525e68717e8a929da4ada79f98928d88848281818183868b91959f928b7f727d8a97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa4978a7e7c86929a96918c8784828181818285898e939aa1a9a8a0969083796d60574e42372b1f140900000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000000000000000000000000000000006121f2b3844505c667986939f9f9286796c5f4a3f34281c1003000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000004101c27333d474f5456565656565d69768390908376695d5656565656544f473d33271c10040000010b141d242b30333439393939393939393939393939393939393939393939393939393939393939393939393939393534312c251e150c0200000815222e3b4855616e7b7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7265584c3f3225190c00000000000000000000000000000000000815212e3b4854616e7b87949f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f94877b6e6154483b2e211508000000000000000000000000000000000915202b38434e5863707d8a95a09e9285797b87939f9f94897c6f63584e4333291f0e040000000000000000000000000000000000000000000000040a0f1315161e202020201e1d1b17120c05000000000000000000000000000000000000070f171e24282b2c2d2d2d2d2d2d2d23222b2c2d2d2d2d2d2d2d2322282b2c2d2d2d2d2d2d2d23221f1b160f0700000000000b1724313e4a5764717d8a8b8b8c8d86786c60544c4a494a4e5764717e8b97a49b8e8275685b4f4235281c0f020000000000111e2a3744515d6a7783909da6998d8073665a4d4033271a24313d4a5764707d8a97a39f9285786c5f5245392c1f1200000915202a333e48505a636d73808d939ea69f948f82786d655b504940372d241a11080000000000000000000000000008111a242d374049525c606d78818f949fa59d938d80736d635a50483e332a2015090000111e2a3744515d6a7783868686868686867e71645a677480868686868686868074675a4d4134271a0e0000000000000000000000000000000000000000000000000000000000000000000000000000010d1924303a4854606b7783909daaac9f92857a6d6054473c313b4754606a7783909dabac9f92867a6d6054473d3221160c0100000000000000000000000000000004111d2935414c56616d7a85929ea4aea79f959086807b7875747475767a7e848c939992867c7d8a97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa3978a7e839098938d847f7b777574747476797c81889297a1a9a89f958d80736a5f53473b30251a0e02000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000713202d3a4653606d79869aa49f938679665c5044382b1f1206000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b16212b353d44484a4a4a4a505d69768390908376695d504a4a4a4a48443d352b21160b00000000020b131a1f2426272d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d282725201a130c030000000a1724303d4a5763707d8a8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c86796c5f5346392c201300000000000000000000000000000000000815212e3b4854616e7b8793939393939393939393939393939393939393877b6e6154483b2e21150800000000000000000000000000000000030f1b27323d4653606c7883909da1978b7e808d9aa49c9083766b6054463c3121170d000000000000000000000000000000000000000000000000000003060809111313131312110f0b07010000000000000000000000000000000000000000060d13181c1e1f2020202020202016151e1f2020202020202016151c1e1f202020202020201615130f0a040000000000000814212e3b4754616e7a8793989998897d70665e56565657585f6975818e9ba7998c7f7266594c3f3326190c000000000000101d2a3643505d697682909ca79a8d8174675a4e4134271b24313e4b5764717e8a97a49e9184786b5e5245382b1f1200020f1a26313c46505a626d727f8c929da5a0959082796d665c53493f372e251b120800000000000000000000000000000008121b242e374044505c666d79828f959fa59c928c7f726c625a50463c31261a0f0200111e2a3744515d6a77849093939393938b7e71645a6774818d93939393938d8074675a4d4134271a0e00000000000000000000000000000000000000000000000000000000000000000000000000000008131e2c38434f5965727f8b98a2aea2988b7e7165574d4237404b55626f7c8895a0aca79b8e8174685d5245392c201304000000000000000000000000000000000713202c3945525d6873808d97a1adaa9f9590837b736e6969686768676d71797f87929890837e8a97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa89b8e818e9593878079726e6969686768656c6f757d859297a2ada79f92877b6e62574d42362a1e1105000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0a49a86796d6053463a2d201307000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000050f19232b33383c3d3d3d43505d69768390908376695d50433d3d3d3c38332b23190f05000000000001080e14171a1b20202020202020202020202020202020202020202020202020202020202020202020202020201c1b18140f0902000000000a1724303d4a5763707d8a96989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989286796c5f5346392c201300000000000000000000000000000000000815212e3b4854616e7b8686868686868686868686868686868686868686867b6e6154483b2e21150800000000000000000000000000000000000a161f2b3744505b65717e8b96a19e918486929fa0958a7d7064594f43342a200f05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002070c0f111213131313131313090911121313131313131309090f1112131313131313130909070300000000000000000714202d3946525e6875828f9aa49d9083786e6865636363656a6e7b86929f9f95887c6f6255483c2f2215090000000000000f1c2935424f5c6875828f9ba79b8e8174685b4e4130251a25323f4b5865727e8b98a59d9083776a5d5144372a1e110006121f2b37434e58616c717f8b919ca4a09690837a6d675d544a41382d251c1309000000000000000000000000000000000009121c2528343f4a545c676d79839095a0a49c918b7e716c61584e43372b1f120600111e2a3744515d6a7784909d9f9f9f978b7e71645a6774818d9a9f9f9f9a8d8074675a4d4134271a0e000000000000000000000000000000000000000000000000000000000000000000000000000000020f1b27323d4754606d7a86929facaa9c908376695f53473845515c6774808d9aa7aca095897c6f63564c4135291d1104000000000000000000000000000000000714212d3a4754606d7a85929fa9aea2989083796e69625f575b5a555d60666d737e8692958f828f9ca8afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afaa9e938e9393877e736d67615e575b5a535b60626b707c85929fa6afa3998e8175695e52463a2d201408000000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000714212d3a4754606d7a8793a0a093867a6d6053473a2d201407000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000005101a232c33393c3d3d3d43505d69768390908376695d50433d3d3d3c39332c231a10050000000000000003080b0d0e13131313131313131313131313131313131313131313131313131313131313131313131313130f0e0c08040000000000000a1724303d4a5763707d8a969f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9286796c5f5346392c201300000000000000000000000000000000000714212d3a46535e697679797979797979797979797979797979797979797976695e53463a2d2114070000000000000000000000000000000000030f1b27333f4953606d7984919ea096919298a29d9184786c6053463d3220180e0000000000000000000000000000000000000000000000000000020507080c1011131311100c0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111e2a36414c56626f7c87939f9f958f827a757270707072757c849198a39a9083766a5f53473a2e2115080000000000000e1b2734414e5a6774818d9aa79c90837669574d42362a1e2733404d5a6673808d99a69c8f8276695c4f4336291c10000814212e3a47535f6a717e87939fa3a19691847a6e685d554b42382f261b130a010000000000000000000000000000000000000a1317232e38424b555d676d7a839196a1a39f92877e716a5f53473a2e21140800111e2a3744515d6a7784909daaaca4978b7e71645a6774818d9aa7aca79a8d8074675a4d4134271a0e000000000000000000000000000000000000000000000000000000000000000000000000000000000a16202c3945515d6774818e9aa7ab9f94887b6e62544a3f4653606d7985929fabaa9d9084776b6054443a3024190d0100000000000000000000000000000004111d2935414c5665727e8b98a2aeab9f92867b6e675e57534d4e4e4b51545c606c717e8a92948f949eaaafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afafa59e9b958c7f736c605c55524d4e4e49505359606a717e8a949fabab9f92877b6e6154473b3025190e020000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000714212e3a4754616d7a8794a0a093877a6d6054473a2d211407000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000b17222c363e44494a4a4a4a505d69768390908376695d504a4a4a4a49443e362c22170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724303d4a5763707d8a93939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939286796c5f5346392c2013000000000000000000000000000000000005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5e574d42362a1e12050000000000000000000000000000000000000b17222d3844515c66727f8c97a2a09e9fa2a1968b7e71655b5044372b1f120600000000000000000000000000000000000000000000000003090e121415191c1e1f1f1e1c191514120e090300000000000000000000000000000000000105090b0b1313131307060400000105090b0b13131313070604000000000000000000000000000000000000000000000000010d1925303b4754606a73808d939f9e948f86817e7d7c7d7f82879196a09f93887d6f63584e43372b1f12060000000000000b1825323e4b5865717e8b98a99e918578695e52463a2d232b37424d576875828e9ba79a8d8074675a4d4134271a0e000815222f3b4855626e7b869299a4a29891847b6e685e564c433930261d140a01000000000000000000000000000000000000000006111c263039434b555e686e7b849197a2a39992867b6e6255483b2f22150800111e2a3744515d6a7784909daab1a4978b7e71645a6774818d9aa7b3a79a8d8074675a4d4134271a0e0000000000000000000000000000000000000000000000000000000000000000000000000000000004111d2935414c55626f7c88959faba6998d8073665c50444d5764717e8a97a2ada2988b7f7265594f4332281e1308000000000000000000000000000000000713202c3945525d687683909caaaea3998c8073695e554d4742414140454a515a616c74808d979c9ea6b0afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afb7afa89d9083786d605a514b464241413f44464f58616c76828f9ca9afa3998c7f7266564c41362a1e11050000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000814212e3b4754616e7a8794a1a094877a6d6154473a2e211407000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000004101c28333e48505557575757575d69768390908376695d57575757575550483e33281c10040000000000000000000000000000000000000000000000000000000000000000050a0d0f101313100f0d0a05000000000000000000000000000000000a1724303d4a5763707d8686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c5f5346392c20130000000000000000000000000000000000020e1a25313b454d535f6060606060606060606060606060606060606060605f534d453b31251a0e0200000000000000000000000000000000000006111b2834404a54606d7a85929393939393939184796d6053493f33271b0f030000000000000000000000000000000000000000000002090e141a1e212226292b2c2c2b292521211e1a140e09020000000000000000000000000000060c111517182020201f1413100c070c111517182020201f1413100c07010000000000000000000000000000000000000000000008141e2b38434e58606d78818c92999f98928e8b89898a8b8f92999f98928b7f726b6054463c31261b0f030000000000000915222f3c4855626f7c8897a2a197877b6e6154483d342e303947535f697784919ea7978b7e7164584b3e3125180b000a1723303d4a5663707d8999a3ab9f92857b6f695e564c433a31271e150b02000000000000000000000000000000000000000000000a141e27303a434c565e696e7b85929faba398897d7063564a3d3023170a00111e2a3744515d6a7784909daaa89f978b7e71645a6774818d9aa7a09f9a8d8074675a4d4134271a0e00000000000000000000000000000000000000000000000000000000000000000000000000000000010d19242f3a47545f6a7783909da9ab9e9184796d605346525e6976828f9ca9ac9f92867a6d6054473d3221160c02000000000000000000000000000000000714212d3a4754606d7a86929facac9f92867a6d61574d433b37312f35394044505a606d7a85919eaab0b8afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afb9ada1968a7d70665c5045403936302d33373d46505a63707d8a97a1adab9d908377685e5246392d2014070000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000815212e3b4854616e7b8794a1a194877a6e6154473b2e211408000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000814202d3944505a616464646464646976839090837669646464646464615a5044392d201408000000000000000000000000000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a0300000000000000000000000000000916232f3c4855616b707979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979746a5e5145382b1f1200000000000000000000000000000000000009141f29333b4246485353535353535353535353535353535353535353534846423b33291f140900000000000000000000000000000000000000000c18232e3945515d67738086868686868686867f72665c5141382d22170b00000000000000000000000000000000000000000000050d141a1f262a2d2e32363839393836322e2d2a251f19140d050000000000000000000000000911181d2124252d2d2d2c201f1c1812181d2124252d2d2d2c201f1c18120b03000000000000000000000000000000000000000000020f1b27323d44505c666d777f868e92999a9b98969696989b9a98928e867f726d62594f44342a20150a000000000000000713202d3a4653606d7985929fa9988b7e7165594f443f3f3f424c56616e7b8896a0a095877b6e6154483b2e211508000a1723303d4a5663707d8996a1a9a2988b7e716b61584e463c332920160d03000000000000000000000000000000000000000000030c161f29323c454e58606b717e87939fa9a196897d7063564a3d3023170a00101d2a3743505d6a7683909d9e9b93938b7e71645a6773808d9aa19393938d8074675a4d4134271a0e000000000000000000000000000000000000000000000000000000000000000000000000000000000008131e2b37434e5865717e8b97a2ada1968a7d7063564c54616e7b87939faca79b8e8174685d5245392c20130400000000000000000000000000000000000a1724313d4a5764707d8a99a3afa99c8f8276685e52453b312b2624292e343e45525d68727f8c98a2aebaafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afb7ab9e9184786c60544a3f342e2a2522272b343e4653606c7885919eabac9f93877a6e6154473b2e2114080000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000000000000000000000000000815222e3b4855616e7b8894a1a194877b6e6154483b2e211508000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1623303c4955616c70707070707070768390908376707070707070706c6155493c3023160a0000000000000000000000000000000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d04000000000000000000000000000714202c38444f5961636c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6a62584d4135291d10000000000000000000000000000000000000030d17212931363a3b4646464646464646464646464646464646464646463b3a36312921170d03000000000000000000000000000000000000000007121c2935414b55636e737979797979797979726d62544a402f261b1106000000000000000000000000000000000000000000080e171f252a31363a3b3f4344464644433f3b3a36312a251f170e070000000000000000000009121b22292e3132393939392d2c29231d22292e3132393939392d2c29231d150d030000000000000000000000000000000000000000000a162028343f4a545c656c737b82868b8e909192929291908d8b86817b726d625b51473d3222180e040000000000000006121f2b3844505c6674808d9aa69c9083766b6157504a4c4c4e545d68737f8c99a89d908377695e53463a2d211407000814212e3b4754616e7a849197a2aa9f92877d706a60584e453b32281f150c0200000000000000000000000000000000000000020b151e28313b444d57606a707d879299a4a29791847a6e6154473b2e21140800101d293643505c6976828f9c938e8686867e7164596673808c9997898686868074675a4d4134271a0e0000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1b26323c4753606d7985929faba99b8e8275685d525966737f8c99a4aca095897c6f63564c4135291d110400000000000000000000000000000000000d1a2733404d5a6673808d99abb5ab988b7f7265564c4133291f1a181c232935414c56606d7a85929fabb8afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afb6ac9a8d8073665b5042382e231d1a171b222b3744505b6574818e9ba7afa49a8a7e7164574b3e312418070000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000000000010406070c0b0a09080815222f3b4855626e7b8895a1a194887b6e6155483b2e22150808090a0b0c07070501000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1724313d4a5764707d7d7d7d7d7d7d7d839191837d7d7d7d7d7d7d7d7064574a3d3124170a00000000000000000000000000000000000000000000000000000000030d161f272d32353639393635322d271f160d0300000000000000000000000004101c28333e474f5557606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605f5e5850473c3125190d00000000000000000000000000000000000000050f171f252a2d2e3939393939393939393939393939393939393939392e2d2a251f170f05000000000000000000000000000000000000000000000d18242f3a43525c63666c6c6c6c6c6c6c6c65625b5142392e1d140a00000000000000000000000000000000000000000009111a202930363b4246484c4f515252514f4c4846423b36302920191109000000000000000006111b242d343a3d3e464646463a38342f272d343a3d3e464646463a38342f271f150b010000000000000000000000000000000000000000040b17232e38424a535b60696e757a7e8183848586858483817e7a756e69625b51493f352b211006000000000000000003101c28343f4a54626e7b88949e9f94897d7069605c5458595860666d7a85929fa1978b7f7265574d42362a1e1205000714202d3946525e686f7c859298a3a39992867d6f6a5f574d443a31271e140a000000000000000000000000000000000000000a141d27303a434c565f696f7c869299a3a29892857c6f685e5246392d201407000f1c2935424f5c6875828f9b8e81797979716c625965727f8c989285797979746e64584c3f33261a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2c3945515d6774808d9aa6ac9f92867a6d6154606b7784919eabaa9d9084776b6054443a3024190d010000000000000000000000000000000003101c28343f4a546975828f9ca8afa399887c6f6255493c3022170d0d1219242f3a45525d6875818e9ba8b4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afafa49a897d7063544a3f30261c120e0b0f1b27333f495364717e8b97abb5ac9a8d8073675a4d402e23180c0000101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000000001080d11131419181716151415222f3c4855626f7b8895a2a195887b6e6255483b2f22151415161718181413110d080200000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000013202d394653606c79868a8a8a8a8a8a8a919595918a8a8a8a8a8a8a86796c605346392d2013000000000000000000000000000000000000000000000000000000000a151f2831383e4243464643423e3831281f150a000000000000000000000000000b16212c353e44484a5353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353514d473e352a1f14090000000000000000000000000000000000000000050d141a1e21212d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d21211e1a140d05000000000000000000000000000000000000000000000007131d2831404a52585a6060606060606060595751493f30271c0b02000000000000000000000000000000000000000009121b232b333b42464d5355595c5e5f5f5e5c5854534d46423b322b231b1209000000000000010c18222d363f454a4b535353524745403931363f454a4b535353524745403931271d120700000000000000000000000000000000000000000006111c263038414950575f62686d71747778787978787674716d68615f5751493f372d23190f000000000000000000000b17232e3847535f6a75828f97a29e92857b716d66666566676a6f78828f97a29e9285796d6053473b31251a0e020005111e2a36414c565f6a6f7d869299a3a29892857c6e695e564c433930261c1106000000000000000000000000000000000006111c262f39434c565e686e7b859298a2a39992867d6f6a5f564c41362a1e1105000f1b2835424e5b6875818e9b9083766c6c64625a5865727e8b989386796d6c67645c52473c3023170b00000000000000000000000000000000000000000000000000000000000000000000000000000000000004101d2935404b55626f7b88949faba3998b7e726557636f7c8996a0aca2988b7f7265594f4332281e1308000000000000000000000000000000000006121f2b3844505c667884919eabac9f9286796d6053463a2d2013070008131e2935414c5664717d8a97a8b2afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afac9f93867a6d6053473a2d20140a00000b17222d3c4855626f7b8899a4afa99c8f837669554b4034281c100400101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000000000040c13191d20212524232221201f222f3c4955626f7c8895a2a295887b6f6255483c2f221f20212223242521201d19130c04000000000000000000000203101d2a3643505d69768390908376695d5043362a1d1003020000000000000013202d394653606c798693939393939393939393939393939393939386796c605346392d201300000000000000000000000000000000000000000000000000000005111c27313a434a4e505353504e4a433a31271c110500000000000000000000000005101a232c33383c3d464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464645413c352c23190e0300000000000000000000000000000000000000000003090e1214152020202020202020202020202020202020202020201514120e0903000000000000000000000000000000000000000000000000010c161f2e3840474b4d53535353535353534c4a463f372d1e150b000000000000000000000000000000000000000007111b242d353d454d52575f6165696b6c6c6b6965615e57524d443d352c241b1107000000000005111d29343f485056586060605f53514b43393f485056586060605f53514b43392f23180c000000000000000000000000000000000000000000000a141e262f383f444d53565e6165676a6b6c6c6c6b696764605d56534d453f372d251b11070000000000000000000006111c2b37434e58616e7b85929fa19792857e797573727274777c838f949f9e938b7e71675d514539291f14090000020e1925303b444e58606b707e87929fa3a29791847b6e685d554b42382e23171309000000000000000000000000000000091317222d38424b555d686e7a849197a1a39f92877d706b60584e443b3025190e02000d1a2633404d596673808c99918477695e5856505663707d89969a877b6e615a58524a40362b1f1307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18242f3947535f6a7683909ca9ab9d908376695f6774818e9aa8ac9f92867a6d6054473d3221160c0200000000000000000000000000000000000713202d3a4653606d7986929facaa9e918477665c5145382c1f130600010d19242f3a4754616d7a8796a0acafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afaa9e918477675d5145392c20130200000613202d3a4653606d7986939facab9e918478675c5145382c1f130600101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000000040d161e24292c2d3231302f2e2d2c292f3c4956626f7c8995a2a295887b6f6255483c2f292c2d2e2f3031322e2d29241e160e0400000000000000050a0f12101d2a3643505d69768390908376695d5043362a1d10120f0a05000000000013202d394653606c798686868686868686868686868686868686868686796c605346392d20130000000000000000000000000000000000000000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a0000000000000000000000000008111a21282c2f3039393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393835312a231a11070000000000000000000000000000000000000000000000000205070813131313131313131313131313131313131313131308070502000000000000000000000000000000000000000000000000000000040d1c262e363b3f4046464646464646463f3e3a352d251b0c0300000000000000000000000000000000000000050e19232d363e474f575e61696e72767779797776726e69615e564f473e362c23190e04000000000915212e3a45505a62656c6c6c6c605c554b4045505a62656c6c6c6c605c554b4034291c1004000000000000000000000000000000000000000000020c141d262d333c42474c5254585b5d5e5f5f5f5e5d5a5854524c46423b332d251b13090000000000000000000000000f1a26313c46525e69717e8a939aa197928b8581807f7f80848890959f9f948e81756c62554b403529170d0300000008141e29323c464f59616c717e8b919ca4a19691837a6d675d544a3f3428251b12080000000000000000000000000008121b2528333f4a545c676d7a839096a0a49c918b7e716b61594f463c32291e140800000b1724313e4a5764717d8a9796877b6e6154474754616e7a8797978a7e7164544a4740382f24190e030000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d2b37434e5864717e8a97a1ab9f95887b6e616d7985929faba79b8e8174685d5245392c2013040000000000000000000000000000000000000815212e3b4854616e7b8799a3afa99c8f827669544b4034281c100400000813202d3946525d687784919eaaafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa89c8f827569554b4035291d1104000006131f2c3845515c677884919eabac9f9386796d6053463a2d20130700101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000000010c161f282f35393a3f3e3d3c3b3a38352f3c4956636f7c8996a2a295887c6f6255493c2f34383a3b3c3d3e3f3a3935302820160c0200000000010910161b1e20202a3643505d69768390908376695d5043362a20201e1b1610090100000013202d3946535f6c767979797979797979797979797979797979797979766c5f5346392d20130000000000000000000000000000000000000000000000000000010d1a26323e4a545e66696c6c69665e544a3e32261a0d01000000000000000000000000000810161c2023242d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2b29251f191108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141c242a2f3233393939393939393932312e29231b130900000000000000000000000000000000000000020c17202b353e48505960696e747b7f8284858584827f7b746e69605950483e352b20160c020000000b1724313d4a56626c71797979796d675c51454a56626c71797979796d675c5145382c1f130600000000000000000000000000000000000000000000020b141b222731373a4146474b4e505152535251504e4b4745413a36312a211b1309010000000000000000000000000a15202a36424d57616c727f8892979f9e97928e8c8b8c8d90959d9f99938d82796d605a5043392f24180500000000020d17202a343d47505a626c737f8c929da5a0959082796d665c504440372d241a1107000000000000000000000007111a242d373f44505b666d79828f95a0a59d928c7f726c62594f463d342a20170d0200000815222f3b4855626e7b8897978b7e7164574d46525e697885929a8e8174665c5044382c261d12080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010f1a26313c4653606d7985929eaca7998c7f7366717d8a98a2aca095897c6f63564c4135291d11040000000000000000000000000000000000000916222f3c4955626f7c8895abb5a79b8e8174685b4e412e23180c00000005111d2935414c566875828f9ba8afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa79a8d8174675a4e412f24180d01000004101c2834404b556a7683909da9afa49a887b6e6155483b2e22150800101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000008131e28313a4145474c4b4a49484745404443495663707c8996a3a295897c6f625649434440454748494a4b4b4746413a32281e1308000000010a131b21272b2d2d2d3643505d69768390908376695d5043362d2d2d2b27211b130a010000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e120000000000000000000000000000000000000000000000000000030f1c2935424e5a66707679797670665a4e4235291c0f030000000000000000000000000000050b1014161720202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1d19140e070000000000000000000000000000000000000000000002070a0c0d131313130e0d0b0803000407090a131313131006050300000000000000000000000000000000000000000000000000000000000000000000020a12191f2326272d2d2d2d2d2d2d2d2625221e181109010000000000000000000000000000000000000008131e29323d47505a626b707b81878c8f919292918f8b87817b706b615a50473d32281e13080000000b1825323e4b5865717e86868686796d6053474b5865717e86868686796d6053473a2d20140a0000000000000000000000000000000000000000000000020a11171f262b3035393a3e4144454546454543413e3a3935302a261f180f090100000000000000000000000000030e1a25303b45505a626d727e858d92989a9c9b9998999a9d9b99938f8780786d675c51483e31281d12070000000000050e18222b353e47505a636d74808d939ea69f948f82786d605c52493f362c23191007000000000000000000071019232c363f49525c606c78818f949fa69e938d80746d635a50473e342b22180e050000000713202d3a4653606d7985929b8f8275695f53464d566975828f9c9184796d6053463e31271d12070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151f2c3845515c6773808d9aa4aa9d9184776a75828e9baaaa9d9084776b6054443a3024190d010000000000000000000000000000000000000a1623303d495663707c8996a3afa69a8d8073675a4d4034271a07000000010d192430414d5a6774808d9aa7afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa6998c807366594d4033261a07000000000c18232e424f5c6975828f9ca8b6ac95887c6f6255493c2f22160900101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013060000000000000000010d19242f3a434c5154585756555453514b504f4e5663707c8996a3a296897c6f63564e4f504b5153545556575854524c443a3024190d01000009131c252c33373939393943505d69768390908376695d50433939393937332c251c130900000f1b27333e49525a5f60606060606060606060606060606060606060605f5a52493e33271b0f000000000000000000000000000000000000000000000000000003101d2a3643505d69768286868276695d5043362a1d1003000000000000000000000000000000000407090a131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131312100d090300000000000000000000000000000000000000000000070e1316191a202020201b1a18140f0b10141617202020201d13120f0b0600000000000000000000000000000000000000000000000000000000000000000000080e1317191a2020202020202020191816120d070000000000000000000000000000000000000000010d1925303a444f59626c717d858e92999c9a98989a9c99928e857d716c61594f443a3024190d0200000a1723303d4a5663707d8993988a7d7063574a4a5663707d8993988a7d7063574a3d31261b0f03000000000000000000000000000000000000000000000000060b151a1e25292d2e32343738393939383634312d2c29241e1a140e060000000000000000000000000000000009141f29333e48515b626c707a80858a8d909192939291908e8b87827c736d665c554b40362d1f160c01000000000000061019232c353f48515b606c78818e949fa69e948e81746e635b51483e352b22190f0600000000000000060f18222b353e48515b636e74808d939ea69f948e81776c605b51483f352c221910060000000006121f2b3844505c6675818e9b93877b6e61574d4b5864717e8b98978a7e7164594f43392f23180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c2834404b55616e7b87939faca095887b6f7985929faca3988b7f7265594f4332281e1308000000000000000000000000000000000000000a1724313d4a5764707d8a97a3b0a6998c807366594d4033261a0d00000000081926323f4c5965727f8c98a5afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa5988b7f7265584c3f3225190c00000000071b2835424e5b6875818e9ba8b0a396897d7063564a3d3023170a00101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201306000000000000000004111d2935414c555d606564636261605d555d5c5b5a63707d8996a3a396897c70635a5b5c5d555c606162636465615d564c4135291d11050005101b252e373e434646464646505d69768390908376695d504646464646433e372e251b1005000a16212c3740494f535353535353535353535353535353535353535353534f4940372c21160a000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a12191f2325262d2d2d2d282724201a161c2022232d2d2d2d2a201f1b17110a0200000000000000000000000000000000000000000000000000000000000000000002070a0c0d13131313131313130c0b09060100000000000000000000000000000000000000000005111d2a36414c56606b717e8792979e96918d8c8c8d91969e9792877e716b60564c4135291e130800000815222f3b4855626e7b88959a8d817467584e4855626e7b88959a8d817467584e43372b1f12060000000000000000000000000000000000000000000000000003090e13191d202125282a2b2c2c2c2b2a272521201d19130e09030000000000000000000000000000000000020d17202c363f49515a61686d73797d8083848586858583817e7b756f6a605c544b43392f241b0d04000000000000000007101a232d364044505b666d79828f95a0a69d938d80736d625a50473d342a21180d040000000000040d18212a343d47505a626d73808c929da59f958f82786d655b50493f362d231a1007000000000003101c28343f4a5463707d8995998d8074695e534754606d7a86929d9083766b61554b4034291c10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18232e3946535f6976828f9ca9a7998c7f737d8a98a2ac9f92867a6d6054473d3221160c02000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0a5998c7f7266594c3f3326190c000000000b1825323e4b5865717e8b98a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa5988b7e7265584b3f3225180c000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a00101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000613202c3945515d676d7271706f6e6d676b6a69686766707d8a96a3a396897d70666768696a6b676d6e6f7071726d685d5246392d201307000a16212c3740494f5353535353535d69768390908376695d5353535353534f4940372c21160a0005101b252e373e4346464646464646464646464646464646464646464646433e372e251b1005000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000000000000010406070a0d10111213131211100d0a07060400000000030505060606060606000000000000000000000000000000000000040613131313131313131312110e0904000000000000000a131c242a2f3233393939393433302b2521272c2f3039393939372d2b27221b140b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3946525e68707d87929997918a84807f7f81848a92979992877d6f685d52453a3024190d01000714202d3a4753606d7a86979e9184786a5f534753606d7a86979e9184786a5f53473a2e21150800000000000000000000000000000000000000000000000000000002080d111314181b1d1e1f201f1e1d1b181413110d08020000000000000000000000000000000000000000050e1a242d373f4850565e61676d70747678797979787774716e68625f58504a423931271d12090000000000000000000008111b2428333f4a545c676d79839096a0a59c928b7f726c61594f463c332a1f160c01000000010c161f2a333c464f59616c727f8b929ca4a0969083796d665c53493f372e241b1108000000000000000b17232e394653606c7883909d92867b6e615a50515d6774818e99958a7d70675c5145382c1f130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d2b37424d5764717d8a97a1aa9d908377818e9baaa79b8e8174685d5245392c20130400000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1a5988c7f7265594c3f3226190c000000000b1824313e4b5764717e8a97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa4978b7e7164584b3e3125180b000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b00101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000714212d3a4754606d797f7e7d7c7b7a79787776757473727d8a97a3a3968a7d72737475767778797a7b7c7d7e7f7a6d6154473a2e211407000f1b27333e49525a5f60606060606069768390908376696060606060605f5a52493e33271b0f000009131c252c33373939393939393939393939393939393939393939393937332c251c130900000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000000000000000001080d111314171a1d1e1f1f201f1e1c1a171413100c07010c0f111213131313131309090703000000000000000000000001070c10132020202020202020201f1d1a150f08000000000007121c252e353b3f404646464641403c362f2b33383c3d46464646433937332d261d140a00000000000000000000000000050a0d0f10131313130b0a0805050a0d0f10131313130b0a08050000000000000000000000000000000000000000000000000000000000000005111e2a36414c56616d7a8592999691857e7774727274787e8591969992857a6d60564c4135291d11040006131f2c3945515d677885929e96887b6f625548515d677885929e96887b6f6255483c3025190d0100000000000000000000000000000000000000000000000000000000010507070b0e111212131212100e0b07070401000000000000000000000000000000000000000000000008121b252d363e444c52555c606467696b6c6c6c6b6a6865615e56544e443f3830271f150b000000000000000000000000091217222d38424b555d676e7a849197a1a49f93887e716b60584e453b31281d130700000007131d28313b454e58606b717e87939fa4a19691847a6d675d544a41382d251c1209000000000000000006121f2b3744505b65717e8a94988f82756c61554c55616e7b8692939184796d6053473a2d201407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1a26313c4653606d7984919eaba095887b85929faba095897c6f63564c4135291d110400000000000000000000000000000000000000000b1825313e4b5864717e8b97a4b1a5988b7f7265584c3f3225190c000000000b1724313e4a5764717d8a97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa4988b7e7165584b3e3225180b000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b00101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000815212e3b4854616e7b878a898887868584838281807f7e808d9aa7a79a8d807e7f808182838485868788898a887b6e6255483b2f22150800121e2b37434f5a646c6c6c6c6c6c6c6c7683909083766c6c6c6c6c6c6c6c645a4f43372b1e120000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b27211b130a0100000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000000003090e13191d20212427292b2b2c2c2c2b292724201f1c18120e181c1e1f2020202020201615130f0a040000000000000000030b12181c1f2d2d2d2d2d2d2d2d2c2c2a2620191209000000020e19242e3740474b4d535353534e4c484138353d44484a535353535046443f382f261b110600000000000000000000030a1016191c1d20202020181714111016191c1d20202020181714110c0600000000000000000000000000000000000000000000000000000000000714202d3946525e6874808d979891847b716c676565656c717b849198978d8073685d5245392c2013070004101d2935404b556a7783909d998c7f7266564c4b556a7783909d998c7f7266564c41362a1d1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131b242c323a41464b5153575a5d5e5f605f5e5d5b5854524d47433c342e261e150d030000000000000000000000000006111c262f39434c555e686e7b859298a2a49a92877d706a5f574d433a2f24180d0100010d18242f3a434d575f6a707d869299a4a29791847b6e685e554b42392f261b130a000000000000000000030f1b27333f4953616c7682868686867d7064574a535e69748086868686807366594d4033261a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f2c3844505c6673808c99a4a79c8f828f97a2aa9d9084776b6054443a3024190d0100000000000000000000000000000000000000000b1824313e4b5764717e8a97a4b1a5988c7f7265594c3f3226190c000000000b1825313e4b5864717e8b97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa5988b7e7265584b3f3225180c000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b00101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130600000000000000000815212e3b4854616e7b8794969594989291908f8e8d8c8b8d929da9a99d928d8b8c8d8e8f9091929894959695887b6e6255483b2f2215080013202d3946535f6c767979797979797979839090837979797979797979766c5f5346392d2013000000010910161b1e202020202020202020202020202020202020202020201e1b161009010000000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000000000060e141a1e24292c2d3033363738393939383634302d2c29231d1a24282b2c2d2d2d2d2d2d23221f1b160f07000000000000030d151d23292c3939393939393939393836312b241b1208000007131f2a354049525759606060605b59534a413d474f5456606060605d53504941382d22170b000000000000000000040d151b212628292d2d2d2d2423211d1b212628292d2d2d2d2423211d171008000000000000000000000000000000000000000000000000000000000814212e3b4754616e7a86929f92867c6e69615a59535b60696e7c86929f92867a6d6054473a2d21140700000c18242f424f5c6875828f9b9c908376685e524f5c6875828f9b9c908376685e5246392d20130700000000000000000000000106090b0c13131313130d0c0a070200050a0d0f1013131313130a0907040000000000000000000000000000000000000000000000000000000000000109111a20283035394045474a4d505152535252504e4b4746413b373228231c150c030000000000000000000000000000000a141d27303a434c565f696f7c869299a3a39992867c6f695f554b4035291d11040004111d2935404b555f696f7c869298a3a39892857c6f695e564c433930271d140a01000000000000000000000b17222d3841505a66707679797979706c6155494d57646e7479797979736e63574b3f3225190c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101c28343f4a54616e7b87939fac9e948f949ea9a3988b7f7265594f4332281e13080000000000000000000000000000000000000000000b1724313e4a5764717d8a97a4b0a5998c7f7266594c3f3326190c000000000c1825323f4b5865727e8b98a5afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa5988b7f7265584c3f3225190c000000010e1b2834414e5b6774818e9aa7b0a4978a7d7164574a3e3124170b00101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693a0acac9f9286796c5f5346392c20130600000000000714202d3a4753606d7a8693a0acac9f9286796c5f5346392c20130600000000000000000815212e3b4854616e7b8794a1a2aaa29f9e9d9c9b9a99989a9da4aeaea49d9a98999a9b9c9d9e9fa2aaa2a195887b6e6255483b2f2215080013202d394653606c798686868686868686909494908686868686868686796c605346392d20130000000000050a0f1213131313131313131313131313131313131313131313120f0a0500000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000000000070f181f262a2f35393a3d404344454646454443403d3a38342f2a252f3437383939393939392f2e2c272119100700000000010b151f272f343846464646464646464645423d352d24190f04000a16232f3b47525c63666c6c6c6c67645d5346444f5960636c6c6c6c6a605b53493f33271b110600000000000000000d161f262d3235363939393931302d28262d3235363939393931302d28221a12080000000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b99998c7f736a5f57504c4950575f6a73808d99988a7e7164574b3e3124180b0000071a2734414d5a6774808d9a9f93867a6d61544d5a6774808d9a9f93867a6d6154473a2e23180c00000000000000000000070d1216181920202020201a1917130e0a1015191c1d2020202020161613100b05000000000000000000000000000000000000000000000000000000000000080e161e25292f34383a3d4143454646464544413e3b3936302b262017110a0300000000000000000000000000000000020b151e28313b444d57606a707d87929aa4a29892857b6e675d5145392c201306000613202c3945515d676e7b859198a2a39992867d6f6a5f574d443a31281e150b02000000000000000000000006111b262f3e48545e66696c6c6c6c64615a504445525c64676c6c6c6c66635b52473b2f23160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c17232e3846535e6975828f9ca8a69e9c9ea6ac9f92867a6d6054473d3222170b020000000000000000000000000000000000000000000a1724303d4a5763707d8a96a3b0a6998d8073665a4d4033271a0d000000000d192633404c5966737f8c99a6afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa6998c7f7366594c4033261907000000020f1b2835424e5b6875818e9ba8b0a3978a7d7064574a3d3124170a00101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a86939f9f9f9f9286796c5f5346392c20130600000000000714202d3a4753606d7a86939f9f9f9f9286796c5f5346392c20130600000000000000000815212e3b4854616e7b8794a1aaa29f9e9d9c9b9a999796999ca4aeaea49c999697999a9b9c9d9e9fa2aaa195887b6e6255483b2f2215080013202d394653606c798693939393939393969696969393939393939386796c605346392d2013000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000000030b1218212a31363a4145474a4d505152525352514f4d4a4745403936313a4044454646464646463c3b38322b22190f0400000007121d2731394045535353535353535353524e473f352b201509000c1925323f4b57636e7379797979746f64584e4854606b7079797979766c655b5044382d22170b0000000000000008111f2831383e4243464646463e3d393431383e4243464646463e3d39342c241a100600000000000000000000000000000000000000000000000000000f1c2835424f5b6875818e9b92867a6d61574e453f3f444e58616e7b87969b8e8174685b4e4135281b0e00000c1926323f4c5965727f8c98a4998b7e7164544a5965727f8c98a4998b7e7164544a4034281c100400000000000000010911181e2225262d2d2d2d2d2726231f19141b212628292d2d2d2d2d2322201c160f07000000000000000000000000000000000000000000000000000000000000040c13191d23292c2d31343638393939383735322e2d2a251f1b150c0600000000000000000000000000000000000000030c161f29323c454e58606b717e8893939393979184796d6053473a2d201407000714202d3a4753606d7984919793939392877e706b60584e453b32281f160c03000000000000000000000000000a141d2c36424c545a5c60606060575550483e414a52585a606060605957524940352a1e1307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b151e2834404b545c66707d8a96a3b0aaa8aab0a79b8e8174685d544a3f33281d140a0000000000000000000000000000000000000000000916232f3c4956626f7c8995a2afa79a8d8174675a4e4134271b08000000010e1b2734414e5a6774818d9aa7afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa79a8d8174675a4e412e23180c000000030f1c2936424f5c6975828f9ca8afa296897c6f6356493c3023160900101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d7a8693939393939286796c5f5346392c20130000000000000714202d3a4753606d7a8693939393939286796c5f5346392c20130600000000000000000815212e3b4854616e7b87949594989291908f8e8d8c8b8a8c929ca8a89c928c8a8b8c8d8e8f90919298949595887b6e6255483b2f2215080013202d394653606c79868989898989898989898989898989898d929386796c605346392d2013000000000000000105070810101010101010101010101010101010101010101008070501000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000000030c151c2328333b42464c5254575a5c5e5e5f5f5f5e5c5a5753514b46423b454c50525353535353534948433d342b21160a0000000c18232f39434b515f606060606060605f5e5951473d31261a0e000d1a2633404d596673808686868681746a5f534a5663707d8686868683776c6053493f33271b0f030000000000050f1a23313a42494e50535353534b49453e3a42494e50535353534b49453e362c22170c0000000000000000000000000000000000000000000000000000111d2a3744505d6a7783909d908377685e52453c33333c46525e697784919c8f8276695c504336291d1000000b1724313e4a5764717d8a97ab9b8e8275665c515764717d8a97ab9b8e8275665c5144382c1f12060000000000000009131b23292e3132393939393933322f2a241f262d3235363939393939302f2c272119110700000000000000000000000000000000000000000000000000000000000002080d12181c1f2024272a2b2c2d2c2b2a282521201e19140f0a04000000000000000000000000000000000000000000040d17202a333c464f59616c727f868686868686867b6e6154483b2e211508000815212e3b4854616e7b868686868686867e716c61594f463c332920160d040000000000000000000000000000020b1a24313a42494e50535353534a49443e363841474c4e535353534d4b4740372e24190e0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007121d27303945515c666d78808d99a6a3a0a0a1a4a89c8f82756c665b50443e2f261b110600000000000000000000000000000000000000000815222e3b4855616e7b8894a9b3a89b8f8275685c4f423025190e02000005121e2a36424d576976828f9ca9afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa89b8f827568544a4034281c1004000004101c2934404b556a7683909da9b4aa95887b6f6255483c2f22150900101d2a3643505d69768390908376695d5043362a1d1000000000000000000714202d3a4753606d798686868686868687796c5f5346392c140c0200000000000714202d3a4753606d798686868686868687796c5f5346392c20130600000000000000000815212e3b4854616e7b878a8887868584838281807f7e7d808c99a6a6998c807d7e7f80818283848586878889887b6e6255483b2f221508000a1723303d4a5663707d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d808d9386796c605346392d2013000000000002080d1114141c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1414110d080200000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000000000b151e272e343f454d53565d606366696a6b6c6c6c6b696763605c55534d444f575c5f60606060606056544e463d32271b0f030004101c2934404b555c6c6c6c6c6c6c6c6c6c6a63594e42362a1d11000714202d3a4753606d7984919392877b6e62564c54606b75818e98958a7e71655b5044372b1f120600000000000b16212b35424c545a5c6060606057555048424c545a5c60606060575550483e34281d110500000000000000000000000000000000000000000000000000121f2b3845525e6b7885919b8f827568564c41332a2a36424d566976838f9c9184776a5e5144372b1e1100000916232f3c4956626f7c8995ab9f9285796d605356626f7c8995ab9f9285796d6053463a2d20130900000000000007111b252d353a3e3f4646464646403f3b352e2830383e424346464646463d3b38332b23190f050000000000000000000000000000000000000000000000000000000000000001070c101314171a1d1e1f201f1f1d1b181414110e0802000000000000000000000000000000000000000000000000050e18212b343d47505a626d727979797979797976695e53463a2d211407000714212d3a46535e697679797979797979716c625a50473d342a21170e050000000000000000000000000000000008121f2831383e4243464646463d3c39332c2f363c3f4146464646403f3b352e251c1207000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c18232e3943505a606d78828d929c9c97949394979d9e948e81786c60594f41382d22170b00000000000000000000000000000000000000000714202d3a4753606d7a8697a1ada99d9083766a564d41362a1e110500000714202d3a46525e697885919eabafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afaa9d908477665c5144382c1f1206000006131f2c3845515c677884919eabaea298877a6d6154473a2e21140700101d2a3643505d69768390908376695d5043362a1d10000000000000000006131f2c3845515c67767979797979797979756a5e52452e261e140a000000000006131f2c3845515c67767979797979797979756a5e5245382c1f120600000000000000000714212d3a4754606d797e7d7c7b7a7978767574737271727f8c98a5a5988b7f7271727374757678797a7b7c7d7e7a6d6054473a2d211407000916222f3c4854606b707070707070707070707070707070727e8b9386796c605346392d201300000000050d14191e202129292929292929292929292929292929292929292921201e19140d05000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000000007121c273039404451575f61686d7073767778797978777673706d67615e57505761686b6c6c6c6c6c6c6260584e43382c1f13070006131f2c3845515c67767979797979797979756a5e5245382c1f120006131f2c3845515c67707d8a95998e8275685e524f59616e7b86929d9184786c605346392d22170b0000000004101c27333d47545e66696c6c6c6c64615a5047545e66696c6c6c6c64615a5045392d21140800000000000000000000000000000000000000000000000000121f2b3845525e6b7884919b8f827568564c4135292a36414c566976828f9c9184776a5e5144372b1e1100000814212e3b4754616e7a8799a3a297897c70635654616e7a8799a3a297897c706356493d31261a0e0200000000010d18232d373f464a4c53535353534d4b474038303a42494e5053535353534948443d352b21160b000000000000000000000000000000000000000000000000000000000000000000000406070a0e101213131312110e0b08070502000000000000000000000000000000000000000000000000000000060f19222b353e48515b62656c6c6c6c6c6c6c6c5e574d42362a1e12050005121e2a36424d575e6c6c6c6c6c6c6c6c65625a50473e352b22180f050000000000000000000000000000000000000d161f262d3235363939393931302d2822242b3033343939393933322f2a241c130a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c2834404b55616c75818e949c94908a8786878a90959d938d80746b6153493f33271b0f030000000000000000000000000000000000000006131f2c3945515d677885919eabab9f928578685e5246392d20140600000815212e3b4854616e7b8797a1adafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afac9f9286796d6053463a2d20130900000714202d3a4753606d7a86939facac9f928579685e5246392d20130700101d2a3643505d69768390908376695d5043362a1d10000000000000000004101c2934404b555c6c6c6c6c6c6c6c6c6c6a6359443f3830261c110600000006111c263038404b555c6c6c6c6c6c6c6c6c6c6a63594e42362a1d110400000000000000000613202c3945515d676d71706f6e6d676b6a696867666673808c99a6a6998c7f7366666768696a6b676d6e6f70716d685d5245392c201307000713202c38444f5960636363636363636363636363636365727e8b9386796c605346392d2013000000050e171e252a2d2e3636363636363636363636363636363636363636362e2d2a251e170e050000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000000000c18232e39424a515b63696e747a7d808384858586858482807d79746e69605b536873787979797979796f6a6054483b2e221509000714202d3a4753606d798686868686868687796c5f5346392c20130004101c2934404b55616b7683909d92867a6e615447525e6974808d9995897d7063544a3f33281c0f030000000714202c38444f5966707679797979716c61554f5966707679797979716c6155493d3023170a00000000000000000000000000000000000000000000000000111d2a3744505d6a7783909d908377685d52463c33333b46525e687784919c8f8276695c504336291d1000000613202d394653606c7986929fa99a8d8073675753606c7986929fa99a8d807367574d42372b1e12060000000006121e29353f4951575960606060605a57524a4038424c545a5c606060606056544f473d33271c10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101a232c363f49515658606060606060605f534d453b31251a0e0200020e1a25313b454d535f60606060606060585650483f352c2319100600000000000000000000000000000000000000040d151c212629292d2d2d2d2423201c171a1f2426272d2d2d2d2625231e19120a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006131f2c3845515c67717e8b939c928c837d7a797a7e838e939d928a7d70655b5044372b1f12050000000000000000000000000000000000000004101d2935404b55697683909ca9ada297877a6e6154473b2d22170b0107111e2a36414d5665717e8b98a9b3afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afaea399887c6f6255493c31261a0d06030615222f3c4855626f7b8899a4afaa9d9084776a564c41362a1e110500101d2a3643505d69768390908376695d5043362a1d100000000000000000000c18232f39434b515f6060606060606060605f5e504a42382e23170b0000000b17232e38424a505e5f60606060606060605f5e5951473d31261a0200000000000000000004111d2935414b555d6064636261605d555d5c5b5a5a6774818d9aa7a79a8d8074675a5a5b5c5d555d6061626364605d564c4135291d11040004101c27333d474f54565656565656565656565656565865727e8b9386796c605346392d20130000020d1720293036393b4343434343434343434343434343434343434343433b3936302920170d0200000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000004101c2834404a545c606d727b81868a8d8f9191929292918f8d8a85807b726c655c6b78858686868686867c6f6256493c2f231609000714202d3a4753606d7a8693939393939286796c5f5346392c201300000c18232f39434f5964717e8a97998b7f7265554b4d56616e7b87929b8e8175665b5044382b1f12060000000916222f3c4854606b7682868686867e71645754606b7682868686867e7164574b3e3124180b000000000000000000000000000000000000000000000000000f1c2835424f5b6875818e9b92867a6d61574d453f3f454e57616e7a87939b8e8174685b4e4135281b0e000005121f2b3744505b657784919eaa9d918477695f535b657784919eaa9d918477695f53473a2d211408000000000916222e3a46515b62656c6c6c6c6c66635c52473e49545e66696c6c6c6c6c6360594f44382c201307000000000000000000000000000000020507080c10121312110f0c080705020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a242d373f464a4c535353535353534846423b33291f140900000009141f29333b424648535353535353534b4a453f362d231a1107000000000000000000000000000000000000000000030a1016191c1d20202020171614100b0e14171a1b202020201a1916130e070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713202d3a4653606d7984919e938c8076706d6d6e7178818e949d9083786c605346392d20130600000000000000000000000000000000000000000c18242f414d5a6774808d9aa7b3a9978a7d706453493f33271b100d1218252d3946525e6875828f9ca8b5afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afb5ab998c7f7266574d42372b1f15120f121c2834404a5465717e8b98abb5a89b8e8175685b4e423025190d0100101d2a3643505d69768390908376695d5043362a1d100000000000000000040c131d2731394045534d545b60666c6c6c6c6c6a5c544a3f34281c10030003101c28343f4a545c6a6c6c6c6c6c66605b544d524e473f352019130c040000000000000000010d18242f3a434b51545857555453514b504f4e4f5b6875828e9ba8a89b8e8175685b4e4e4f504b51535455565854524c443a2f24190d0100000b16212b353d44484a4a4a4a4a4a4a4a4a4a4a4a4b5865727e8b9386796c605346392d2013000008141e29323b4146474f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4746413b32291e140800000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000000030e18212c3844515c666d757f878d9298999c9d9e9f9f9f9e9c9a98928d867f776d666679869293939393887b6e6255483b2f221508000714202d3a4753606d7a86939f9f9f9f9286796c5f5346392c2013000007121d27313e4653606d7984919d908376675d5146535e6975828f9b9285796c605346392d201306000006131f2b37434e5863707d8994998f82766c61555863707d8994998f82766c6155493d3023170a000000000000000000000000000000000000000000000000000b1825323e4b5865717e8b99998c7f72695f57504c4c50575f6a73808c9a988a7e7164574b3e3124180b0000030f1b27333f49536976838f9ca9a096887b6e6155536976838f9ca9a096887b6e6155483b2f24190d010000000b1825313e4a57626d727979797979736e63574b424e5a6670767979797979706b6054483b2f2216090000000000000000000000000003090e121415191d1e1f1f1e1c181414110e080200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008121b252d343a3e3f464646464646463b3a36312921170d03000000030d17212931363a3b464646464646463e3d3a342d241b1108000000000000000000000000000000000000000000000000050a0d0f10131313130a0a08040003080b0d0e131313130d0c0a0702000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1724303d4a5763707d8a96998e81756e64616061666d78828f9c95897c6f6256493c2f2316090000000000000000000000000000000000000000071825313e4b5864717e8b97a8b2a79a8d8074655b5044372b221c191d242a36414c56616e7b86929facb9afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afb6a99c908376695f53473c3127201f1c1f232c3844515c6675818e9ba8b3a9988c7f7265594c3f322619080000101d2a3643505d69768390908376695d5043362a1d1000000000000001070e161e2529323b424651575f666c72797979797975665c5044382b1f12060006121f2b3844505c66757979797979726c665f575146423b3229251e160e07010000000000000007131d28313a4145474b4a4948474540434243505c6976838f9ca9a99c8f8276695c4f43424340454748494a4b4745413a32281e1308000000050f19232b33383c3d3d3d3d3d3d3d3d3d3d3d3f4b5865727e8b9386796c605346392d201300010d1925303b444c52545c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c54524c443b3025190d01000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000000915202c38434f59606d78818c92999fa2aaa9a8aaa29f9e9e9e9fa29f98928c81786d6d798699a39f9f94877a6e6154473b2e211408000714202d3a4753606d7a8693a0acac9f9286796c5f5346392c2013000008121d262c3844505c6674818e9b92867a6d6053474d5765717e8b9897887b6e6255483b2f22150800000815212e3b47535f6a7683909d92867b6e615a535f6a7683909d92867b6e615a5045392d211408000000000000000000000000000000000000000000000000000814212e3b4754616e7a86929f92857b6e69615a59595a61696e7c86929f92867a6d6154473a2e2114070000000b17222d414e5b6874818e9ba7a8988c7f7265555b6874818e9ba7a8988c7f7265554c4135291d11040000000c1926323f4c5965727f86868686868073665a4d43505c69768286868686867d706356493d3023160a000000000000000000000002080e141a1e212226292b2c2c2b292521201e19140d0801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009131b23292e3132393939393939392e2d2a251f170f050000000000050f171f252a2d2e3939393939393932312e29221b12090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e1b2734414e5a6774818d9a93877b6e615c5453545c666f7c8997998c807366594d4033261a0d00000000000000000000000000000000000000000815212e3b4854616e7b8796a0acab9e9184786c6053463e342c2924292f353e46525e6873808c99a3aebbafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afb7ab9f94887b6e62574e4339312d2b282b2e343f4953606d7985929fabada297897c6f6356493c302316090000101d2a3643505d69768390908376695d5043362a1d100000000000040c1318202830353e444d525b62696e787f8686868687796d6053463a2d201307000713202d3a4653606d7987868686867f786e69625b524d443e3530282018130c04000000000000010c161f282f35393a3e3d3c3b3a38352f3744515d6a7784909daaaa9d9083776a5d50442e2f35383a3b3c3d3e3a39352f2820160c0100000005101a232c33393c3d3d3d3d3d3d3d3d3d3d3d3f4b5865727e8b9386796c605346392d20130005111e2a36414c565e61696969696969696969696969696969696969696969615e564c41362a1e1105000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000000020e1a26313b4854606b74808d939fa3ababa49f9b979892919192939a989d9f938f82786d7a8794abb4a094877a6d6154473a2e211407000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201300030e19242f3840474a5464717e8a9799897c6f6256494854616e7b8796978a7d7164574a3e3124170b00000916222f3c4955626f7c88959b8e8174695f5355626f7c88959b8e8174695f53483e34281d1105000000000000000000000000000000000000000000000000000714202d3946525e6874808d979891837b706c676565676c717b849198978d8073685d5246392d201307000000061a2633404d596673808c99a6a99c8f8276675d596673808c99a6a99c8f8276675d5145392c2013060000000d192633404c5966737f8c9393938d8074675a4d43505d6a7683909393938a7d7064574a3d3124170a00000000000000000000050d14191f262a2d2e32363839393836322e2d2a251e19130c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010911181e2225252d2d2d2d2d2d2d21211e1a140d0500000000000000050d141a1e21212d2d2d2d2d2d2d2524211d18110900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004060709090909090909090706030000000000000000000000000000000000000000000000000000000000000000000003101c2936434f5c6976828f9c908377695e5247464a54606a7885919b8e8175685b4e4235281b0f02000000000000000000000000000000000000000714212d3a46535e697784919eaaaca196897d70635a50463e38343035394045515b616e7a85929fabb2baafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afbdb0a69a8d81746a5f554b433c39383338393f44505b65717e8a97a2adab9f9285796d6053463a2d2013070000101d2a3643505d69768390908376695d5043362a1d1000000000070d161d2429323a414650565e616d727b828c929992877e71665c5044382b1f12060006121f2b3844505c66717e879399928c827b726d615e565046413a3229241d160d07000000000000040d161d24292c2d31302f2e2d2c292935404b556b7884919eabaa9e9184776b544a403428292c2d2e2f30312d2c29241e160d04000000000b17222c363e44494a4a4a4a4a4a4a4a4a4a4a4a4b5865727e8b9386796c605346392d2013000714202d3946525e686e7676767676767676767676767676767676767676766e685e5246392d201407000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000006121e2b37424e57636f7c87939fa5afa9a199938f8a878584848586888c90959e948d80747b8794a1ada093877a6d6054473a2d211407000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130007131f2b36404a52585a616e7b879a978a7e7164575055575e69788491998c7f7366594c403326190d0005121e2a36424d576673808d9994887c6f62574d576673808d9994887c6f62574d42362c22170c000000000000000000000000000000000000000000000000000005111e2a36414c56616d7a8592999591847d7774727274777e8591969992857a6d61564c4135291d11050000000b1825323e4b5865717e8b98a4ac9f92867a6d605865717e8b98a4ac9f92867a6d6054473a2d22170b0000010d1a2734404d5a6773808d9a9f9b8e8174685b4e44515e6a7784919d9f978a7e7164574b3e3124180b000000000000000000070e171f252a31363a3b3f4345464544423f3b39363029241e160d060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070d12161819202020202020201514120e090300000000000000000003090e12141520202020202020181715110c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c10131316161616161616161312100c06000000000000000000000000000000000000000000000000000000000000000004111d2a3744505d6a7783909c8f827569574d423a424e586a7783909c8f8276695c4f4336291c10030000000000000000000000000000000000000005121e2a36424d576673808d99a6b0a89c9083766c6258504745404241464b515a626d75818e989ea0a8b2afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afb5aba39f92877b6e675d554e4846443f44464a5059606c7883909da9b1a89b8e8175665c5044382b1f12060000101d2a3643505d69768390908376695d5043362a1d100000000710191f282f353e444c525a61696e767f8690949a93877e716c61544a3f34281c10030003101c28343f4a54616c717e87939a9490867f766e69615a524c443e352f281f191007000000000000040c13181d202125242221201f1f2c3845515d677985929facab9f928578665c5144382c1f1f202122232521201d19130c040000000004101c28333e485055575757575757575757575757575865727e8b9386796c605346392d2013000814212e3b4754616e7a8282828282828282828282828282828282828282827a6e6154473b2e211408000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000814212e3a47535f6a76828f9aa4afaba1979287827d7a79787778797b7f838a9196928a7e7b8895a1ada093867a6d6053473a2d201407000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000b1723303c47525c64676c6d798693998c7f7266595a61646c6c7683909b8e8174685b4e4135281b0e000714212d3a46535e697884919c8f82766a5f53535e697884919c8f82766a5f53453c31241a10060000000000000000000000000000000000000000000000000000020e1925303b46525e68707d87929996918a84807f7f81848a91979992877d70685e52443a3024190d010000000a1723303d4a5663707d8996a3aea3998a7d71645463707d8996a3aea3998a7d7164544a3f33281c0f0300010e1b2734414e5a6774818d9aa79b8e8275685b4f45515e6b7884919ea5988b7e7265584b3f3225180c0000000000000000081019202930363b4246484c50515252514f4b4746413b352f282018100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000106090b0c13131313131313080705020000000000000000000000000002050708131313131313130b0b09050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b12181c1f202323232323232323201f1c17110a0300000000000000000000000000000000000000000000000000000000000003101d293643505c6976838f9c908376675d51464446535f697884919b8e8275685b4f4235281c0f0200000000000000000000000000000000000000020e1a25313b4855626e7b88949eacab9f948b7e716a615a53514b4e4c52555d606c727f8b93969196a0acafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afafa39992999083796d6760585553504a5053545c606b727f8b95a0acaca095897d7063544a3f34281c10030000101d2a3643505d69768390908376695d5043362a1d100000040f19222b313a41454f565e616c717b828b92989a93887e716c615a5042382e23170b0000000b17232e3842505a616c717e88939a98928b827b716c615e564f45413a312b22190f0400000000000001070d111314181716151414202d3a4753606d7a8698a2aeaea29886796d6053463a2d201314151617181413110d080100000000000814202d3944505a61646464646464646464646464646465727e8b9386796c605346392d2013000815212e3b4854616e7b878f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f877b6e6154483b2e211508000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000815222f3b4855626e7b88949facaea39992857d75716e686b6b666d6e72767d84909492857d8996a3aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000d1a26333f4c58646e7479797985929a8d8073675a616c71797979828f9b8f8275685c4f4235291c0f000815212e3b4854616e7b8796988c7f7265584e54616e7b8796988c7f7265584e433b33291f140900000000000000000000000000000000000000000000000000000008141e2a36414c56606b717e8792989e96918d8c8c8d91969e9892877e716b60564c4132281e1308000000000815222f3b4855626e7b8895a99f9f9b8e8174665b626e7b8895a99f9f9b8e8174665b5044382b1f120600020e1b2835414e5b6874818e9ba79c8f8276695c4f45525f6b7885929ea5988c7f7265594c3f3226190c0000000000000008111a222b323b41464d5355595c5e5f5f5e5c5854524c45413a322a2219100700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c151d23282c2d30303030303030302d2c28231c150c030000000000000000000000000000000000000000000000000000000000020f1b2835424e5b6875818e9b92867a6d605a5351535b616e7b88969a8d8073675a4d4034271a0d0100000000000000000000000000000000000000000914212e3a47535f6975828f9aa4afa69f92867d716c64605c555b565d61676d737e8792989184919eaaafa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afac9f928692958f81796f6a6462605b545b6062666d727d87929fa7b0a69d9184786c605346392e23170b000000101d2a3643505d69768390908376695d5043362a1d1000000a16212b343d434b515961686d757e858f949f9f93887f716c625a50483e30261c110600000006111c26303e48505a626c717f88939f9f948f857e756d686159514b433d342b21160a0000000000000000010406070b0a09080815212e3b4854616e7b8794aab4b3aa94877a6e6154473b2e21140808090a0b07070401000000000000000a1623303c4955616c707070707070707070707070707070727e8b9386796c605346392d2013000815212e3b4854616e7b87949c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c94877b6e6154483b2e211508000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000000d192633404c5966737f8c99a6b0ac9f92877c6f6b64615e56545c6062656c707a8290949083909daaaca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a67748086868689979a8d8174675a64717e8686868f939c8f8276695c504336291d10000a1724313d4a5764707d8a9798887b6e6255525764707d8a9798887b6e6255524d453b30251a0e020000000000000000000000000000000000000000000000000000020d1925303a444f59626c717d868e93999c9a98989a9c99938e857d716c62594f443a3020160c02000000000714202d3a4753606d7a8697939393939285796c60606d7a8697939393939285796c605346392d20130600020f1c2935424f5c6875828f9ba89c908376695d5044505b667985929fa6998c807366594d4033261a0d00000000000006101a232c343d444d52575f6165696b6c6c6b6965615e56524c443c342b22190f0500000000000000000000050a0d0f1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100f0d09040000000000000000000000050a0d0f1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100f0d090400000000000000000b151e272e34383a3c3c3c3c3c3c3c3c3a38342e261e150a0000000000000000000000000000000000000000000000000000000000000b1825313e4b5864717e8b98988d80736d63605c60636d75818e9b97897d7063564a3d3023170a00000000000000000000000000000000000000000006121e2b37424d57626f7c87939fa7aea29892867e76706d67686869686d72798088929992867e8a97a4afa295887c6f6255493c2f221609000916222f3c4955626f7c8895a2afa6998c7f8c93938f837c76716e6c666b666c6e72787f879299a3aea99f948a7e71665b5044382b1c1106000000101d2a3643505d69768390908376695d5043362a1d1000030f1b27323d464e555d606b707a818a92979f9b918b7f726d625a50483e362c1e140a00000000000a141e2c363e48505a626d727f8b919b9e97928a817a706b605d554e463d32271b0f030000000000000000000000000000000915222f3c4855626f7b8895a2aeaea195887b6e6255483b2f2215080000000000000000000000000000000a1724313d4a5764707e7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d808d9386796c605346392d2013000815212e3b4854616e7b8794a1a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a194877b6e6154483b2e211508000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d1003000000000000000005111e2a36424d576976838f9ca9b1a79a8d80736a605954524c4a5053555a61676d798290959095a0abaca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d939393a19a8e8174675b64717d8a93939b9e9d9083766a5d5043372a1d10000c1926333f4c5966727f8c999285796a63615e5766727f8c999285796a63615e574d42362a1e110500000000000000000000000000000000000000000000000000000008131e29323d47505a626b707b81878c8f919292918f8c87817b706b625a50473d32281e0e04000000000006131f2c3945515d677885868686868686867c6f625d677885868686868686867c6f6256493c2f2316090003101c2936434f5c6976828f9ca99d9084776a5d514653606c798698a3a69a8d8073675a4d4034271a0d0100000000020c18222c353e474f565e61696e72767879787775726e68605d564e463d342b21170b0200000000000000030a1016191c1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1c1b1915100a0200000000000000030a1016191c1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1c1b1915100a02000000000007121d273039404546494949494949494946443f3830261c110600000000000000000000000000000000000000000000000000000000000714212e3a4754616d7a86929f93887f756f6d666d7076808c939e9185796d6053463a2d201307000000000000000000000000000000000000000000020e1a26313c4754606a74818d95a0a9aaa298928a827d7977757575777a7f848d939a948c7f7c8895a2afa295897c6f6256493c2f231609000916232f3c4956626f7c8995a2afa296897d818e96959087827e7b79787778797b7f848c9299a3abaaa2978f82776c60544a3f33281c0a00000000101d2a3643505d69768390908376695d5043362a1d100007131f2c38434e5860676d747d858e939fa29b918b7f726d625a50483f362d241a0c020000000000020c1a242d363f48505a626d727f8b919ba29f938e857d746d6760584e43382c1f13070000000000000000000000000000000a1623303d495663707c8996a3acaca296897c6f6356493c3023160900000000000000000000000000000013202d394653606c79868a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8d929386796c605346392d2013000815212e3b4854616e7b87949f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f94877b6e6154483b2e211508000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000714202d3a46525e697885929fabaca095877b6e61584f4746413f44464850555d676e7b85929da0a7b1aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d9a9fa0a79b8e8174685b64717d8a979fa8aa9d9084776a5d5144372a1e11000e1a2734414d5a6774808d9a91847770706e695e6774808d9a91847770706e695e52463a2d201407000000000000000000000000000000000000000000000000000000020d17202b353f48505961696e747b7f8284858584827f7b746e69615950483f352b20160c00000000000004101d2935404b55687378797979797979796f6a6055687378797979797979796f6a6054483b2e2215090003101d2a3643505d697683909ca99e9184776b5e514754606d7a8793aaa79a8d8174675a4e4134271b0e01000000000a141e2a343e474f5960686e747b7f8384858584827e7a736d685f584f473d33291d140a000000000000040d151c2126292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292825211b140c040000000000040d151c2126292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292825211b140c04000000000c18232e39424b5153565656565656565653504a42382e23170c00000000000000000000000000000000000000000000000000000000000713202d3946525e6873808c959a938b817c7978797d828c929c948b7e71665c5145382c1f13060000000000000000000000000000000000000000000009151f2b37434e58606d79839197a0a8aaa29f948f8a868382818284878b91969f958f82787b8894a1aea296897c6f6356493c3023160900091623303c4956636f7c8996a2aea295887c7a84919899938f8b888685848486888c91969fa3aba9a29892857b6e655b5042382d22170b00000000101d2a3643505d69768390908376695d5043362a1d10000915222e3b4854606a6f79818a91979ea39c918c7f726d625b51483f362d241b12080000000000000008121b242d363f48515b626d727f8c919ca39e97918a81796f6a6054483b2e2215090000000000000000000000000000000b1724313e4a5764717d8a979f9f9f9f978a7d7064574a3d3124170a00000000000000000000000000000013202d394653606c798693939393939393939393939393939393939386796c605346392d2013000815212e3b4854616e7b8793939393939393939393939393939393939393877b6e6154483b2e211508000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000814212e3b4754616e7b8798a2aeaa9d908377695e53463d393634383a3e434c555e69717e8b97a1adb9aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d9aa7b3a79b8e8174685b64717d8a97a4b0aa9d9084776a5d5144372a1e11000f1b2835424e5b6875818e9b91847d7d7d7b6e616875818e9b91847d7d7d7b6e6154473b2e21140800000000000000000000000000000000000000000000000000000000050e19232d363f474f575e61696e72767779797776726e69615e574f473f362d23190e05000000000000000c18242f39435761686b6c6c6c6c6c6c6c6260585761686b6c6c6c6c6c6c6c6260584e43382c1f13070004111e2a3744515d6a7784909daa9e9285786b5f4a4754616e7a8794a1a89b8e8175685b4e4235281b0f0200000006111c26303c464f59616b6f7a81878c8f919292918f8b86807a6f6a60594f453b2f261b110600000000030d161f262d323536363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363635312c261e160c02000000030d161f262d323536363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363635312c261e160c02000004101c2834404b545c606363636363636363605c544a3f34281c10030000000000000000000000000000000000000000000000000000000005111d2935414c56606d798390969f938e89868586898f949c958f82786c60544b4034281c100400000000000000000000000000000000000000000000030f1b27323d45515d676e7b8591969fa4aca69f9c9892908f8e8f90939a9e9f9490837a6d7a8794aab4a396897c706356493d3023160a000a1623303d495663707c8996a3aca194887b6f7d8692989f9c9799929291919298989ea0a8aba69f9792867d70695f53493f2f261c110600000000101d2a3643505d69768390908376695d5043362a1d10000916232f3c4956626f7c848e9393939393918c7f726d625b51493f362d241b120900000000000000000009121b242d363f49515b626d727f8c9193939393938e847c6f6256493c2f2316090000000000000000000000000000000c1825323f4b5865727e8b9393939393938b7e7165584b3e3225180b00000000000000000000000000000013202d394653606c798686868686868686868686868686868686868686796c605346392d2013000815212e3b4854616e7b8686868686868686868686868686868686868686867b6e6154483b2e211508000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d10030000000000000000091623303c4956636f7c8996aab4a79a8e817467574d42342d2a282b2d313a434d57606d7985929eabb8aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d9aa7aca79b8e8174685b64717d8a97a4acaa9d9084776a5d5144372a1e11000f1c2936424f5c6975828f9c95918989897e72656975828f9c95918989897e7265584b3f3225180c000000000000000000000000000000000000000000000000000000000007111b242d353e454d52575f6165696b6c6c6b6965615f57524d453d352d241b1107000000000000000007121d2731454f575d5f6060606060606056544e4f575d5f6060606060606056544e463d32271b0f030005111e2b3844515e6b7784919eaa9f928579665b504855616e7b8894a1a89b8f8275685c4f4235291c0f020000000b17232e38424e58616b707d858e92999c9e9f9f9e9c98928d847c6f6b60574d41382d22170b000000000a151f2831383e42434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343413d3830281e140a0000000a151f2831383e42434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343413d3830281e140a000006131f2c3845515c666d6f6f6f6f6f6f6f6f6d665c5044382c1f120600000000000000000000000000000000000000000000000000000000010d1925303a45515d676e7a848f949d9b99929292999c9d938e83796d665b5042392e23180c0000000000000000000000000000000000000000000000000a15202935414b555f696e7b848e939a9fa3aaaaa39f9d9b9b9c9d9f9f99928d827a6d6d798698a29f9f96897d7063564a3d3023170a000a1723303d4a5663707d89969f9fa49a877a6d707d8690959da0a39f9e9e9e9fa3aaa9a8a69f9c948f857d706b60574d41382d1d140a0000000000101d2a3643505d69768390908376695d5043362a1d10000e1b2734414e5a67748186868686868686867f736d635b51493f372d241b1209000000000000000000000009121b242d373f49515b636d737f86868686868686868174675a4e4134271b0e0000000000000000000000000000000d192633404c5966737f86868686868686867f7265594c3f3226190c00000000000000000000000000000013202d3946535f6c767979797979797979797979797979797979797979766c5f5346392d2013000714212d3a46535e697679797979797979797979797979797979797979797976695e53463a2d211407000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f31261e1c1f2028313b45515c6673808d99aab4aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d9a9f9f9f9b8e8174685b64717d8a979f9f9f9d9084776a5d5144372a1e1100101c2936434f5c6976828f9ca09d96968b7e72656976828f9ca09d96968b7e7265584b3f3225180c00000000000000000000000000000000000000000000000000000000000009121b232c333b42464d5355595c5e5f5f5e5c5955534d46423b332c231b1209000000000000000000010b151f333d454c505253535353535353494843454c5052535353535353534948433d342b21160a000005121f2b3845525e6b7885919eaba29886796c60534955626f7c8895a2a99c8f8376695c504336291d1003000003101c28343f4a545f6a707d8692979fa3ababacabaaaaa39f9691867d6f695e53493f33271b0f03000005101c26313a42494e50505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050504f4e49423a30261b10040005101c26313a42494e50505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050504f4e49423a30261b1004000713202d3a4653606d787c7c7c7c7c7c7c7c786d6053463a2d201307000000000000000000000000000000000000000000000000000000000008131e2935404b555e686e7a828a919598999a999795908981796d675d544a3f30271d1207000000000000000000000000000000000000000000000000040d18242f3a434d575f696e7981878e92989a9c9e9f9f9f9e9d9a98928e8680786d6866798592939393938a7d7164574a3e3124170b000b1724313e4a5764717d8a939393939386796d6b707c838b9195989b9d9e9f9f9f9e9d9b9894908a827b706b60594f453b2f261b0b020000000000101d2a3643505d69768390908376695d5043362a1d10000d1a2733404c58646e747979797979797979736d635b51493f372d251b12090000000000000000000000000009121b252d373f49515b636d737979797979797979746e64584c4033271a0d0000000000000000000000000000000c1825323e4b57636d737979797979797979726d63574a3e3125180c000000000000000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c645a4f43372b1e120005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5e574d42362a1e1205000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1824313e4b5764717e8a97a4b0a4978a7d7164574a3e3124171012161f2834404b54626f7c8998a3aeaca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d93939393938e8174685b64717d8a93939393939084776a5d5144372a1e1100101d293643505c6976838f9ca9aaa3988b7e72656976838f9ca9aaa3988b7e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000009111a212930363b4246484c4f515252514f4c4846423b363029211a11090000000000000000000000030d212b333b404445464646464646463c3b383b404445464646464646463c3b38322b22190f04000005121f2b3744505b657985929facaa93877a6d60544956636f7c8996a2a99d9083766a5d5043372a1d1004000006121f2b3844505c666f7c869298a1a9afb5b7b8b8b7b4aea8a19892857b6e655b5044372b1f140900000a16212d38424c545a5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5a544c42382c211509000a16212d38424c545a5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5a544c42382c211509000815212e3b4854616e7b87898989898989877a6d6154473a2e2114070000000000000000000000000000000000000000000000000000000000020c18242f39434c565e686d777e84888b8c8d8c8b87837d746d675d554b42382d1e150b000000000000000000000000000000000000000000000000000007131d28313b454d575f676d747c81868a8d8f9192929291908d8a86817b736d665e6a77838686868686867e7165584b3e3225180b000b1825323e4b5865717e868686868686857866606a6e787e84888c8e909192929291908e8b88837d766e6960594f473d33291d140a000000000000101d2a3643505d69768390908376695d5043362a1d10000b1824303c48535c64676c6c6c6c6c6c6c6c66635b51493f372d251b130900000000000000000000000000000009131b252d373f49515b63666c6c6c6c6c6c6c6c67645c53483c3024180b0000000000000000000000000000000a16222f3b46515b63666c6c6c6c6c6c6c6c65635b51463a2e2216090000000000000000000000000000000f1b27333e49525a5f60606060606060606060606060606060606060605f5a52493e33271b0f00020e1a25313b454d535f6060606060606060606060606060606060606060605f534d453b31251a0e02000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825313e4b5864717e8b97a4b0a396897d7063564a3d3023170a060d18232e3a4653606d7986929facaca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a677480868686868686868174685b64717e8686868686868683776a5d5144372a1e1100101d293643505c6976838f9ca9b1a5988b7e72656976838f9ca9b1a5988b7e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000000080f171f252a31363a3b3f4344464644433f3b3a36312a251f170f08000000000000000000000000000f1921292f343738393939393939392f2e2c2f343738393939393939392f2e2c27211910070000000613202d394653606c7986939faca194877a6e61544a5663707d8996a3aa9d9184776a5e5144372b1e070000000713202d3a4653606d78839198a2aab3bbc0c4c5c5c4bfbab2aaa1979083776c6053463b31261a0e02000d1926323e49545e66696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969655e54493d3125190d000d1926323e49545e66696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969655e54493d3125190d000815212e3b4854616e7b87949696969694877a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000007121d27313b444c565d656c71777b7e80807f7e7b76706b605c554b43392f261c0c030000000000000000000000000000000000000000000000000000010c161f2a333b454d555d606a6f757a7d8183848586858583817e7a746e69605c54677177797979797979716c62564a3d3124170b000b1724313d4a56626c71797979797979787368585f666d71777b7f8183858586858583817e7b76706b615e574f473d352b21180b02000000000000101d2a3643505d69768386868376695d5043362a1d10000814202b36414a53585a60606060606060605957514940372e251b1309000000000000000000000000000000000109131b252e37404951575960606060606060605a58534a41362b20140800000000000000000000000000000006121e2a3540495157596060606060606060595751493f352a1e12060000000000000000000000000000000a16212c3740494f535353535353535353535353535353535353535353534f4940372c21160a000009141f29333b4246485353535353535353535353535353535353535353534846423b33291f140900000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa296897c6f6356493c302316090007131f2c3845515c667683909da9aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000d1a26333f4c58646e7479797979797979746f6459616c71797979797979797771675b4f4236291d1000101d293643505c6976838f9ca9aca5988b7e72656976838f9ca9aca5988b7e7265584b3f3225180c000000000000000000000000000000000000000000000000000000000000000000050d141a1f262a2d2e32363839393836322e2d2a261f1a140d050000000000000000000000000000070f171e24282b2c2d2d2d2d2d2d2d23221f24282b2c2d2d2d2d2d2d2d23221f1b160f07000000000714202d3a4753606d7a869aa4afa195887b6e62554a5764707d8a97a3ab9e9184786b5e51452f23180c000006121e2b37424e5765717e8b95a0aab4bcc5cbd1d2d2d0cbc4bcb3a99f958a7e7164574d42362a1e1205000f1c2935424e5a667076767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767670655a4e4135281b0f000f1c2935424e5a667076767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767670655a4e4135281b0f000815212e3b4854616e7b8794a1a2a2a094877a6d6154473a2e211407000000000000000000000000000000000000000000000000000000000000010b151f29323b444c535b6064696e71737473716e69636059514b433931281d140a00000000000000000000000000000000000000000000000000000000040d18212a333b434b51585f62686d71747678787979787674716d67615f5750555f676a6c6c6c6c6c6c65625a50453a2e211509000915212e3a45505a62656c6c6c6c6c6c6b686157545c60646a6e72757778787979787675726e69636159534d453d352b23190f06000000000000000f1c2935424e5a66707679797670665a4e4235291c0f00030f1a252f3841484c4e53535353535353534c4b4640372e251c1309010000000000000000000000000000000000010a131c252e3740464b4c53535353535353534e4c4841382f251a0f03000000000000000000000000000000020d19232e3740464b4c53535353535353534c4a463f372d23180d0100000000000000000000000000000005101b252e373e4346464646464646464646464646464646464646464646433e372e251b10050000030d17212931363a3b4646464646464646464646464646464646464646463b3a36312921170d0300000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090004101c2834404b546875828f9ba8aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000b1723303c47525c64676c6c6c6c6c6c6c68645d535a61646c6c6c6c6c6c6c6a675f554a3f33271a0e00101d293643505c6976838f9c9f9f9f988b7e72656976838f9c9f9f9f988b7e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000000000003090e141a1e212226292b2c2c2b292622211e1a140e090300000000000000000000000000000000060d13181c1e1f20202020202020161513181c1e1f202020202020201615130f0a0400000000000814212e3b4754616e7a8794a1b6a295887c6f62554b5864717e8b97a4ab9f9285786c554b4034291c1004000814212e3a47535f6a7784919ea7b1bcc5cfd7dcdfdedcd6cec5bbb1a79d908377695f53463a2d21140700101d293643505c697683838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838276695c4f4336291c1000101d293643505c697683838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838276695c4f4336291c10000815212e3b4854616e7b8794a1aeada094877a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000000030d172029323a41495053575f626566676664615e57544f45403931281f160b020000000000000000000000000000000000000000000000000000000000060f182129313a40454e53565d606467696b6c6c6c6b6a6764605d55534d444d555b5e606060606060585650483f34291d11050005111d29343f485056586060606060605f5c574f4a5153585f6265686a6b6c6c6c6b6a6865615f57554f46423b332b2319110700000000000000000d1a26323e4a545e66696c6c69665e544a3e32261a0d000008131d262f363c40414646464646464646403e3b352e251c130a0100000000000000000000000000000000000000010a131c252e353b3e40464646464646464641403c362f261d1308000000000000000000000000000000000007121c252e353b3e4046464646464646463f3e3a352d251c1107000000000000000000000000000000000009131c252c33373939393939393939393939393939393939393939393937332c251c130900000000050f171f252a2d2e3939393939393939393939393939393939393939392e2d2a251f170f050000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000c18232e414e5b6874818e9ba7aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130007131f2b36404a52585a606060606060605b59534b505557606060606060605d5b554d43392e22160a00101d293643505c6976828f93939393938b7e72656976838f93939393938b7e7265584b3f3225180c00000000000000000000000000000000000000000000000000000000000000000000000003090e121415191c1e1f1f1e1c191514120e09030000000000000000000000000000000000000002070c0f1112131313131313130909070c0f11121313131313131309090703000000000000000815222e3b4855616e7b8894a1aca396897c7063564b5865727e8b98a5ac9f928679675c5145382c1f1306000815222f3b4855626e7b8896a0acb9c3ced7e1e8ebebe7e0d6cdc2b8aca095887b6e6155483b2e2215080013202d394653606c79868f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f86796c5f5246392c1f130013202d394653606c79868f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f86796c5f5246392c1f13000815212e3b4854616e7b8794a1aeada094877a6d6154473a2e2114070000000000000000000000000000000000000000000000000000000000000000050e1720282f383f44464d535558595a595854534d48443d342f271f160d0400000000000000000000000000000000000000000000000000000000000000060f181f282f353c43474c5254575a5c5e5f5f5f5e5d5a5754514b46423b444a4f515353535353534b4a453f362d22180c0100010c18222d363f454a4b53535353535352504c454044464e5355595b5d5e5f5f5f5e5d5b5855534d48443e363129211911070000000000000000000a16222d38434c545a5d60605d5a544c43382d22160a0000010b141d252b303334393939393939393933322f2a231c130a01000000000000000000000000000000000000000000010a131c232a2f323339393939393939393433302b251d140b010000000000000000000000000000000000000a131c232a2f3233393939393939393932312e2a231c130a000000000000000000000000000000000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b27211b130a010000000000050d141a1e21212d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d21211e1a140d05000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f2316090000071a2734404d5a6773808d9aa6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201300030e19242f3840474c4d535353535353534e4d484145494a53535353535353514f4a433b31271c110600101d293643505c697682868686868686867f7265697682868686868686867e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000000000000000000020507080c1011131311100c0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915222f3c4855626f7b88959f9f9f968a7d7063574c5965727f8c989f9fa399867a6d6053473a2d201407000c1825323f4b5865727e8b98a8b2bdccd5e0e9f3f9f8f2e8dfd4c8bcb1a7988b7e7165584b3e3225180b0013202d394653606c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9286796c5f5246392c1f130013202d394653606c7986939c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9286796c5f5246392c1f13000815212e3b4854616e7b8794a1acaca094877a6d6154473a2e211407000000000000000000000000000000000000000000000000000000000000000000050e161d262d33373c4247484b4d4d4c4b4846423b383329231d150d04000000000000000000000000000000000000000000000000000000000000000000060d161d242932373a4145474a4e505152535252504e4b4745413a3631393f43444646464646463e3d3a342d241b110600000006111b242d343a3d3e4646464646464544403b34383c4347484c4e505252535252504e4b4846423b38332a251f170f070000000000000000000005111c27313a434a4e505353504e4a433a31271c1105000000020b131a202427272d2d2d2d2d2d2d2d2625231e19120a010000000000000000000000000000000000000000000000010a12191e2325262d2d2d2d2d2d2d2d272724201a130b0200000000000000000000000000000000000000010a12191e2225262d2d2d2d2d2d2d2d2625221e18110a0100000000000000000000000000000000000000010910161b1e202020202020202020202020202020202020202020201e1b161009010000000000000003090e1214152020202020202020202020202020202020202020201514120e090300000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000008121d262f363c3f414646464646464641403c37393c3e4646464646464644423f3931291f150b00000f1c2835414e5a66707679797979797979726d6266707679797979797979726d62564a3d3124180b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091623303c4956636f7c8993939393938a7e7164574c5966737f8c9393939393877a6d6154473a2e211407000d1a2633404d596673808c99a6b3bfced9e7f2fbfffffaf1e4d9cebfb3a6998c807366594d4033261a0d0013202d394653606c7986939f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9285796c5f5246392c1f130013202d394653606c7986939f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9285796c5f5246392c1f13000815212e3b4854616e7b87949f9f9f9f94877a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000000000000040b141b22272b31373a3b3e4041403e3b3a36312c272118120b030000000000000000000000000000000000000000000000000000000000000000000000040c131820262b2f35393a3e4143454546464543413e3a39352f2a262e33363739393939393932312e29221b1209000000000009121b22292e31323939393939393837342f282c31373a3b3f4244454546464543423f3b3a36312c28211a140d050000000000000000000000000a151f2831383e4243464643423e3831281f150a000000000001080f14181a1b2020202020202020191916120d07000000000000000000000000000000000000000000000000000000070d1216191920202020202020201b1a18140f080100000000000000000000000000000000000000000000070d121618192020202020202020191816120d070000000000000000000000000000000000000000000000050a0f1213131313131313131313131313131313131313131313120f0a0500000000000000000000000205070813131313131313131313131313131313131313131308070502000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130000010b141d242b303334393939393939393534302b2d3031393939393939393736332e271f170d0400000d1926323e49545e66696c6c6c6c6c6c6c65625b5e66696c6c6c6c6c6c6c65625b51453a2e2215090000000000000000000000000000000000000000000000000000000000000000050a0d0f10131313130b0a080500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a1723303d4a5663707d868686868686867e7165584d5a677380868686868686867b6e6155483b2e221508000e1b2734414e5a6774818d9aa7b4c0cddae7f7fffffffff5e7dacdc0b4a79a8d8174675a4e4134271b0e0013202d394653606c79869393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939285796c5f5246392c1f130013202d394653606c79869393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939285796c5f5246392c1f13000815212e3b4854616e7b87939393939393877a6d6154473a2e2114070000000000000000000000000000000000000000000000000000000000000000000000020a11171b1f262b2e2f32333433312e2d2a251f1c160c07010000000000000000000000000000000000000000000000000000000000000000000000000001070d151b1e24292c2d31343638393939383734312d2c29241d1a22272a2b2d2d2d2d2d2d2524211d181109000000000000000911181d2124252d2d2d2d2d2d2c2b28241c1f262b2e2f32353738393939383735322e2d2a261f1c170e090300000000000000000000000000030d161f272d32353639393635322d271f160d030000000000000003080b0d0e13131313131313130d0c0a0602000000000000000000000000000000000000000000000000000000000002060a0c0d13131313131313130e0d0b08030000000000000000000000000000000000000000000000000002060a0c0d13131313131313130c0c09060100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000000020b12191f2326272d2d2d2d2d2d2d282724202123242d2d2d2d2d2d2d2a2927221c150d050000000915212d38424c545a5c60606060606060585651545a5c60606060606060585651493f34291d1105000000000000000000000000000000000000000000000000000000000000030a1016191c1d20202020181714110c060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000916232f3c4855606b7079797979797979716c62564b58646e737979797979797976695f53463a2d211407000d1a2733404d5a6673808d99a6b3c0cfdae6f3fcfffffbf2e9d9ccc0b3a6998d8073665a4d4033271a0d0013202d394653606c79868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c5f5246392c1f130013202d394653606c79868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686796c5f5246392c1f13000815212e3b4854616e7b86868686868686867a6d6154473a2e21140700000000000000000000000000000000000000000000000000000000000000000000000000060b0f151a1e2122252627262521211e1a14100b050000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f13191d20212427292b2c2c2c2b2a272421201d18130e171b1d1e202020202020181715110c06000000000000000000060c111517182020202020201f1e1c1810151a1f212226282a2b2c2c2c2b2a282522211e1a14100b0500000000000000000000000000000000040d151c2226292a2d2d2a2926221c150d0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060712131313131311110e0b0601000000000000000000000000060a0e1011131313131313100f0d0a050000000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130000000001080e13171a1a202020202020201b1a1814141717202020202020201e1d1a16110b040000000005101b26303a42494e50535353535353534b4a45494e50535353535353534b4a453f372d23180c010000000000000000000000000000000000000000000000000000000000040d151b212628292d2d2d2d2423211d17100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202c38444f5960636c6c6c6c6c6c6c65625a5047525c64676c6c6c6c6c6c6c6c5f574d42362a1e1205000c1925323f4c5865727f8b98a9b3bec9d5e1eaf4f9f8f3e9e0d5c9bdb2a8988b7f7265584c3f3225190c0013202d3946535f6c7679797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797974695d5144382b1f120013202d3946535f6c7679797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797974695d5144382b1f12000714202d3a46525e6976797979797979797976685e5246392d20130700000000000000000000000000000000000000000000000000000000000000000000000000000003090e121415181a1a19181514120e090300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001080d111314171b1d1e1f201f1f1d1b181413110d07010b0e10111313131313130b0b09050100000000000000000000000105090b0b13131313131312110f0c040a0f121415191b1d1f1f201f1f1d1b181514120e090300000000000000000000000000000000000000030a11161a1c1d20201d1c1a16110a030000000000000000000000000000000000000000000000000000000000000000000000000000000000020507080b0e111112131312110f0c0908060300000000000000000406070b0f1213131211100e0c0b09060100000000000000000000000000000000000000000000000000000406070a0d0f11121313131212100e0c09060603000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c1012131f20202020201e1d1b17120c04000000000000000000040b11161a1d1e2020202020201d1c1916100a03000000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201300000000000003070b0d0e131313131313130e0e0c08080a0b1313131313131311100e0a06000000000000000a141e2830383e4143464646464646463f3d3a3e4143464646464646463f3d3a342d241b11060000000000000000000000000000000000000000000000000000000000000d161f262d3235363939393931302d28221a12080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101c27333d474f55566060606060606058565048404a52585a606060606060605f534d453b31261a0e0200091623303c4956636f7c8997a1adb9c4cfd9e2e8ebebe7e1d7cec6b9ada196887c6f6255493c2f22160900121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6962584d4135291c1000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6962584d4135291c100005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c5e564c41362a1d11050000000000000000000000000000000000000000000000000000000000000000000000000000000000020608080b0d0e0d0b0807050200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010407070b0e101212131312100e0b07060401000000020404060606060606000000000000000000000000000000000000000000060606060606050503000000020608080c0f111212131312100f0c080705020000000000000000000000000000000000000000000000050a0d0f101313100f0d0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e121415181b1d1e1f201f1f1d1b191515120f0a0401000000070c101313181c1e1f201f1e1d1b181815120d060000000000000000000000000000000000000000000001070c10131416191c1d1f1f20201f1e1d1b191613120f0b060000000000000000000000000000000000000000000000000000000000000000000000000000030a11171c1f202c2d2d2d2d2d2b2a27231d160e0600000000000000050d151c2227292a2d2d2d2d2d2d292926211c150d040000000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c161e262d3235363939393939393932312e3235363939393939393932312e29231b120900000000000000000000000000000000000000000000000000000000000008111f2831383e4243464646463e3d39342c241a1006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16212c353d44484a535353535353534b4a453f3840474b4d535353535353534846423b33291f140900000613202d394653606c7885929ea9b3bdc7d0d8dddfdedcd7cfc6bcb2a89e9184776c605346392d201306000f1b27333e49525a5f60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605f5d5850463b3025190d000f1b27333e49525a5f60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605f5d5850463b3025190d00020e1a25303b454d525f60606060606060605f524c443a3025190d010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f141a1e212125282a2b2c2c2c2b2a282622211f1b15110d08030b12181c1f2025292b2c2c2c2b2a272524221d18110901000000000000000000000000000000000000040a0f12181c1f202326282a2b2c2c2c2c2b2a282523201f1c17110f0a0300000000000000000000000000000000000000000000000000000000000000000000030c151c23282c2d3939393939393837332e2820180e040000000000040d171f272e3336373939393939393635322d261f160d0300000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201300000000000002070a0c0d131313130e0d0b080303070b0d0e131313130d0c0a06020000000000000000000000040c141b212628292d2d2d2d2d2d2d2524222628292d2d2d2d2d2d2d2524221d181109000000000000000000000000000000000000000000000000000000000000050f1a23313a42494e50535353534b49453e362c22170c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050f1a232c33383c3d464646464646463e3d3a342e363b3f40464646464646463b3a36312921170d03000006121f2b3844505b6673808c97a1abb5bdc5ccd2d2d2d1cbc4bcb4aaa0968c7f72655b5044372b1f1205000a16212c3740494f53535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535352514d463e342a1f1408000a16212c3740494f53535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535352514d463e342a1f1408000009141f29333b42464853535353535353535346413a32281e13080000000000000000000000000000000000000000000000000000000000030608091313131313120707050100000000000000000000000000000003060809131313131313131313131313131313131313131313131313130b0a080400000000000000000000000000000306131313131313131308070502000000000000000000000005080a0b13131313130e0d0b0803000000000000000000000306080913131313131313130603000000000000000000000000000004090c0e0f13131313131313130908060300000000000000000000000000000000000000000000000000000000020507081213131313131313100706040000000000000000000000000000000000060c161b1f252a2d2e31343738393939383735322f2e2b26201d19130c151d23282c2d32353839393838363432312e29231b130900000000000000000000000000000000040a0f161b1d23292c2d303335373839393939383635322f2d2b28221c1b150e090300000000000000000000000000000000000000000000000000000000000000000a151e262e34383a45464646464644433f39322a20160c01000000000b151f2931393f424446464646464643423e3831281f150a00000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130000000000070e1316191a202020201b1a18140f0e13171a1a20202020191916120d070000000000000000000000030a1015191c1d20202020202020181815191c1d20202020202020181815110c06000000000000000000000000000000000000000000000000000000000000000b16212b35424c545a5c60606060575550483e34281d11050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008111a21272c2f303939393939393932312e29242a2f3334393939393939392e2d2a261f170f06000000030f1c28333f4a54606d79859199a3abb3bbc0c4c5c5c4bfbab2aaa2989184796d6053493f33271b0f030005101b252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464644413b342c22180d020005101b252e373e434646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464644413b342c22180d020000020d17212930363a3b4646464646464646463936302820160c02000000000000000000000000000000000000000000000000000000040a0f12151520202020201f1413110d08020000000000000000000000040a0f12151520202020202020202020202020202020202020202020202020171714110c0500000000000000000000060c101220202020202020201514120e090200000000000000060c1114171820202020201b1a18140f0801000000000000040a0f131516202020202020202012100c060000000000000000000002090f15191b1c20202020202020201615130f0a0400000000000000000000000000000000000000000000000002090e1114141f202020202020201d1312100c0700000000000000000000000000030a111720272b31363a3b3e4144444546464544423f3c3b37322c29241e191e272e34383a3e42454646454443413f3d3a342d251b11060000000000000000000000000000060b151b21272c2f34383a3d40424445464646454543413f3c3938332d2b26201a150b0600000000000000000000000000000000000000000000000000000000000006111c2630383f4446525353535353514f4b443c32281d120600000006111c27313b434a4f51535353535353504e49423a31261c1005000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000000010a12191f2325262d2d2d2d282724201a1a1f2426272d2d2d2d2625231e19120a01000000000000000000000005090d0f10131313131313130c0b090d0f10131313131313130c0b0905010000000000000000000000000000000000000000000000000000000000000004101c27333d47545e66696c6c6c6c64615a5045392d2114080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f161c2023232d2d2d2d2d2d2d2524211d191f2326272d2d2d2d2d2d2d22211e1a140d0600000000000b17222d3845515d67707d879299a2aaafb6b7b8b8b7b4aea8a19892867c6f665c5141382d22170b00000009131c252c3337393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393835302a221a100600000009131c252c3337393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393835302a221a100600000000050f171f252a2d2e39393939393939392e2d2a251e160e05000000000000000000000000000000000000000000000000000000060e151b1f21222c2d2d2d2d2c21201d19130c04000000000000000000060e151b1f21222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2423211c17100800000000000000030a11171c1f2d2d2d2d2d2d2d2d21201e1a140d0500000000000810171d2123242d2d2d2d2d272724201a130b0200000000070f151b1f22222d2d2d2d2d2d2d2d1f1c17110a0300000000000000030c141b202528282d2d2d2d2d2d2d2c22211f1b150e0700000000000000000000000000000000000000000000050d141a1e20212c2d2d2d2d2d2d2d2a201f1c18120b0300000000000000000000030c151c232832373b4246484b4e505152535252504e4c4847433c39352f28222b30394045464b4f5152535251504e4b4a463f372d23180d010000000000000000000000020a111720262b323839404547494c4f50525253535251504e4c4946443f3837312b262017110a02000000000000000000000000000000000000000000000000000000000c17232e38424a50535f60606060605e5c564e44392e23170b0000000a16222e39434d555b5d6060606060605c5a544c42382d21160a000000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130000000a131c242a2f3233393939393433302b25242b3033343939393933322f2a231c130a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202c38444f5966707679797979716c6155493d3023170a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050b1014161720202020202020181715110e1317191a202020202020201514120e090300000000000006111c2935404b55606b717e8792989fa4acabacabaaaaa39f9691867d706a5f544b402f261b1106000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2b29251f18100800000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2c2b29251f181008000000000000050d141a1e20212d2d2d2d2d2d2d2d21201d19130c0500000000000000000000000000000000000000000000000000000006101820262b2e2f3939393939382e2d29251e160e040000000000000006101820262b2e2f3939393939393939393939393939393939393939393939393931302d28221a12080000000000030c151c23282c39393939393939392e2d2a251f170f0500000008121a22282d303139393939393433302b251d140b00000007101920272b2e2f39393939393939392c28231c150c030000000000020c151e252c31343539393939393939392f2e2b26201810070000000000000000000000000000000000000000050e171f252a2d2e3939393939393939372d2c28231c150c030000000000000000030d151e262e343d43474d5354585b5d5e5f5f5f5e5d5b5955534e4745413a3129343c424b5153585c5e5f5f5f5e5d5a585651493f34291d120600000000000000000000040b141c222832373d43484b515356595b5d5e5f5f5f5f5e5d5b585653504a47433c373127221b140b03000000000000000000000000000000000000000000000000000003101c28343f4a545c606c6c6c6c6c6c6b6760564b3f33271b0e0000010e1a27333f4a555f676a6c6c6c6c6c6c69665e54493e3226190d010000000000000000000000000000000003101d2a3643505d69768390908376695d5043362a1d100300000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000007121c252e353b3f404646464641403c362f2f363c3f4146464646403e3b352e251c0e0500000000000000000000060a0e1011121313131212100e0b07070501000000000000000000000000000000000000020507081313131313131313070705010000000000000000000916222f3c4854606b7682868686867e7164574b3e3124180b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407090a131313131313130b0b090502070b0d0d13131313131313080705020000000000000000000d18242f3a434f59626c717d858e939a9c9e9f9f9d9c98928d847c706b61584e42392e1d140a0000000000010910161b1e2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1f1c19140d06000000000000010910161b1e2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201f1f1c19140d06000000000000000002090e12141520202020202020201413110d0802000000000000000000000000000000000000000000000000000000040e18222a31373a3c4646464646453a3935302820160c020000000000040e18222a32373b3c464646464646464646464646464646464646464646464646463e3c39332c241a1005000000000a151e262e343846464646464646463b3a36302921170d020006101a242c34393d3e464646464641403c362f261d0d0300040f19222b32373b3c464646464646464638342e261e150a000000000009141e2730373d414246464646464646463c3b37322a22180d03000000000000000000000000000000000000020b17202930363a3b4546464646464646433a38342e271e150b00000000000000010b151f2730383f444e54575e6164676a6b6c6c6c6b6a6865625f5854524c433f353c464e545c6065686b6c6c6b6b696765625b51463a2e221509000000000000000000040d161d262d333c43474f54555c606366686a6b6c6c6c6c6b69686562605b54534e47423c332d261d150d030000000000000000000000000000000000000000000000000006121f2c3844505c666d7879797979797772675c4f43372a1d11000003101d2936424f5b6771777979797979797670665a4e4235291c0f030000000000000000000000000000000203101d2a3643505d69768390908376695d5043362a1d100302000000000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201300020e19242e3740474b4d535353534e4c4841383840474c4d535353534c4b4640372e20170d0200000000000000040b11161a1d1e1f2020201f1e1d1b181413110d0802000000000000000000000000000002090e12141520202020202020201413110d080200000000000006131f2b37434e5863707d8994998f82766c6155493d3023170a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007131d28313d47505a626b707b81878c8f919292918f8b86807a6f6a61594f463c30271d0b0200000000000000050a0f121313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131312100d0802000000000000000000050a0f121313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131312100d080200000000000000000000000205070813131313131313130707050100000000000000000000000000000000000000000000000000000000000a15202a343c4347485353535353524746413a32281e130800000000000a15202a343c434748535353535353535353535353535353535353535353535353534a49453e362c22170c00000006111c2630383f4453535353535353534846423b33291f1409000c17222c363e45494b53535353534e4c4841382f1f150b010a15202b343c4347495353535353535353443f3830261c1106000000040f1b25303942484d4f53535353535353534947433c342a1f150b0100000000000000000000000000000000000a141d29333b4246475253535353535353504644403930271c120700000000000007121d273139424a50586062696e71747777787979787775726f6a66605d56504540454e5860666d717578797978777674726d62564a3d3124180b0000000000000000030c161f282f383f444e54596063676d707375777879797978787674726f6c66625f58534d443f382f271f150d030000000000000000000000000000000000000000000000000713202d3a4653606d7886868686868684776b5e5144382b1e11000004111e2a3744515d6a77838686868686868276695c504336291d100300000000000000000000000000050a0f12101d2a3643505d69768390908376695d5043362a1d10120f0a0500000000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130007131f2a354049525759606060605b58534a41404a52585a60606060595751494032291e1408000000000000050e161c2227292a2c2c2d2c2c2b29282521201d19130f0a030000000000000000000000050d141a1e20212d2d2d2d2d2d2d2d21201d19130c0500000000000815212e3b47535f6a7683909d92867b6e615a5045392d211408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c161f2b353f48505961696e757b7f8384858584827e7b736d6860584f473e342a1e150b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1b26313c464e53555f606060605f54524c443a3025190c03000000030f1b26323c464e535560606060606060606060606060606060606060606060606060575550483e33281c110400000c17232e38424a505f606060606060605f524d453b30251a0e05111d28343e4850555760606060605a58534a4131271d12070f1b27323c464e5455606060606060605f504a42382e23170c0000000915202c37424b53595b606060606060605f55534e463c31271d12070000000000000000000000000000000006111b262f3b454d52545f606060606060605d53514a42392e23180c0000000000020c18242f39434b545c606a6f757b7e8183848586858583817f7c78726d68625a514b4d57606a6f797e82848586858483817f7265584b3f3225180c00000000000000000b151e283139424a50585f626b6f75797d7f828385858686858483817f7c79746f6a625f575049413931271f150b010000000000000000000000000000000000000000000000091623303c4956636f7c89989393938d8174675a4e4134271b0e000004111e2a3744515d6a778490939393938f8376695c504336291d10030000000000000000000000010910161b1e20202a3643505d69768390908376695d5043362a20201e1b161009010000000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000a16232f3b47525c63666c6c6c6c67645c534547525c64676c6c6c6c66635b51443b3025190e0100000000040e1720272e3336373939393939383634312e2d2a251e1a150e06000000000000000000050f171f252a2d2e39393939393939392e2d2a251e160e05000000000916222f3c4955626f7c88959b8e8174695f53483e34281d110500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040d19232d363f474f575f61696e72767879787775726e69615e564e463e352c22190c0300000000000000000005090d0f101313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130f0f0d09040000000000000000000000000205070813131313131311100e0b0600000407090a1313131313130e0d0b0803000000000000000000000001070c0f11121313131313070705010000000000000000000000000105090b0b13131313100f0d09050000000000000000000000000000000000000000000000000006121f2b37434e585f626c6c6c6c6c6b615e564c4135291e150b00000006121f2b37434e585f626c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c64615a5045392d2114080003101c28343f4a545c6c6c6c6c6c6c6c6c6c5e574d42362a1e120814212d3945505a61646c6c6c6c6c67645c5343392f23180c131f2b37434e5860626c6c6c6c6c6c6c6c5c544a3f34281c100300000c1925313d48535d65686c6c6c6c6c6c6c6c625f584e43392f24180e050000000000000000000000000000030c17222d38414d575e616c6c6c6c6c6c6c6c6a605c544a4034281c1004000000000a141e2935404b555d666d747c82878b8e909192929291908e8c88847f7a716d605d55535f696f7c848b8f9192929291908d86796c605346392d20130000000000000007121d273039434b545b606a6f767c8185898c8e90919292929291908e8b8985817c756e69605b534b433931271d12070000000000000000000000000000000000000000000004111d2935414c566673808c99aaa3998a7d7064574a3d3124170a000004111e2a3744515d6a7784909d9f9f9c8f8376695c504336291d100300000000000000000000010a131b21272b2d2d2d3643505d69768390908376695d5043362d2d2d2b27211b130a0100000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000c1925323f4b57636e7379797979746f64574d4c58646e7479797979736d63564c41362a1d1207000000000b16202932393f434445464646454543413e3a3936302b2620180f0900000000000000020d17212930363a3b4646464646464646463936302820160c02000005121e2a36424d576673808d9994887c6f62574d42362c22170c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007111b242d353e454d53575f6266696b6c6c6a6965615e56524c443d342c231a10070000000000000000020a1015191c1c2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201c1b1915100902000000000000000002080e1114142020202020201e1d1a17110b0b101316162020202020201b1a18140f08010000000000000000050c12181b1e1f20202020201413110d0802000000000000000000060c11151718202020201c1c1915100a0200000000000000000000000000000000000000000000000815212e3a47535f6a6f7979797979786d685e52463d30271c120700000815212e3b47535f6a7679797979797979797979797979797979797979797979797979716c6155493c3023170a0006121f2c3844505c66767979797979797976695e52463a2d20140a1723303d4955616c717979797979746e64554b4034291c1015222e3b4754606a767979797979797976665c5044382c1f120600020e1b2834414d59656f7579797979797979796f6a5f554b40352920170b02000000000000000000000000000b151e27333f49535e696e7879797979797979766d665c5144382c1f120600000006111c26303845515d676d7880898f93999a9d9e9f9f9f9e9d9b9896918c857e756d675d58626e7b8691969b9e9f9f9e9e9c9386796c605346392d2013000000000000040d18232e39434b555d666c737c83898e9298999b9d9e9f9f9f9f9e9c9b9897918d88827b736c655d554b43392f24180e050000000000000000000000000000000000000000000713202c3945525d687683909da99f92867a6d6054473a2d211407000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000009131c252c33373939393943505d69768390908376695d50433939393937332c251c130900000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000d1a2633404d59667380868686868174695f534d5a677480868686867f73685e5246392f23180c00000006111c27323b434a4f51525353535251504e4b4746413a37312a221b120900000000000009141f29333b42464853535353535353535346413a32281e130800000714212d3a46535e697884919c8f82766a5f53453c31241a10060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009121b232c333b42464d5355595c5e5f5f5e5c5854524d46413a322b221a11080000000000000000040c141b212528292d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d292825211b140c03000000000000050d14191e20212d2d2d2d2d2d2a2a27221d16161b2022232d2d2d2d2d2d272724201a130b02000000000000060f171e23282a2b2d2d2d2d2d21201d19130c04000000000000000911181d2124252d2d2d2d292826211b140c04000000000000000000000000000000000000000000000915222f3c4855626f7c8786868686857a6d61594f42392e23180c03000915222f3c4855626f7c868686868686868686868686868686868686868686868686867e7164574a3e3124170b000713202d3a4653606d78868686868686867b6e6154483b2e2115121e2a36424d5764717e86868686868074675c5145382c1f1416222f3c4955626f7c86868686868686786d6053463a2d20130700020f1c2835424f5b68758286868686868686867c6f675d51453e32291d140a00000000000000000000000007121d27303944505b656e7b858686868686868683796d6053463a2d2013070000000b17232e3842505a606d79828d929b9fa4ababa39f9d9c9b9c9d9fa19e97928b82796d685f6a76828f98a1a8aaa39f9995949386796c605346392d20130000000000010c161f2834404b555d676d78808790949b9fa2a9a29e9c9b9a9a9b9d9fa3a9a19e9a948f877f776d675d554b40352920170d0200000000000000000000000000000000000000000714212d3a4754606d7a86939fa99c908376675d5145392c201306000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000005101b252e373e434646464646505d69768390908376695d504646464646433e372e251b1005000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000714202d3a4753606d7984919392877b6e62564c54606d7a85919392867a6e61554b4034291c100400000a16222e39434d555b5d5f5f605f5f5e5c5b5854524c47433c342d241b110800000000020e1a25303b454d525f60606060606060605f524c443a3025190d01000815212e3b4854616e7b8796988c7f7265584e433b33291f1409000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009111a212931363c4247484c50515252514f4b4746423b363028201910080000000000000000020c161e262c3235363939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393635312c261e150c0200000000050e171e252a2d2e3939393939393736332e272021272c2f303939393939393433302b251d140b0100000000050f1821292f3437383939393939392d29241e160e04000000000009121b22292e3132393939393635322d261e160c000000000000000000000000000000000000000000000815212e3a47535f6a73808d9693978e81746b60544a4034281f1409000916232f3c4956626f7c8993939393939393939393939393939393939393939393938a7d7164574a3e3124170b000713202d3a4653606d79869393939393877b6e6154483b2e211514212d3a46535e6976828f9393939285796d6053473b30251a16222f3c4955626f7c88939393939386796d6053463a2d20130700000714212d3a4754606d7a849199939393999183796d605a50443b2f261b110600000000000000000000040d18232e39424e58606c77828f979393939392867b6e665c5144382c1f1206000003101c28343f4a54616c74818e949da4aca7a09d9992908f8f8f9192999a9e9f948f837a6d666f7c88949faaaea398928c88878886796c605346392d2013000000000008131e28313a45515c676d79828d92999fa6a39f9a97928f8e8d8e8e9092989b9fa3a69e99928c82796d675d51453f32291e140800000000000000000000000000000000000000000b1724313e4a5764717d8a99a4a9998c7f7366554b4135291d1104000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000a16212c3740494f5353535353535d69768390908376695d5353535353534f4940372c21160a000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130006131f2c3845515c67707d8a95998e8175685e52515d67717e8a96988d8073675c5145382c1f130600000e1a27333f4a555f676a6c6c6c6c6c6b696764615e56534e463e362d23190b0200000005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c5e564c41362a1d1105000a1724313d4a5764707d8a9798887b6e6255524d453b30251a0e020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f171f262a31373a3b3f4345464544423f3b3a36302a251e160e070000000000000000000a141e2830383d414346464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464642413d3730271e1409000000020d1720293036393b46464646464644433f3932292b32383b3d46464646464641403c362f261d1308000000010c17212a333a4044454646464646463935302820160c0200000006111b242d343a3d3e4646464643413e3830281e110700000000000000000000000000000000000000000006121f2b37434e58606d7984919e9f93887d6f665c51443b31261a0d04091623303c4956636f7c89969f9fa8a19e9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c978a7d7164574a3e3124170b000713202d3a4653606d7986939f9f9f94877b6e6154483b2e21151b27333f4953616e7b87939f9fa2978a7e7164574d42362a1e16222f3c4955626f7c88959f9f9f9386796d6053463a2d20130700000613202c3945525d686f7c87929fa69fa0958d81746c61564d41382d22170d030000000000000000010c161f2834404b545f6a727f8b949fa9a89e938b7e71695f544a4034281c1004000006121f2b3844505c66717e8b939ea6aea59d95908a86838282838486898d92979f959083786d73808d99a6b0a89f9286807c7a7b7d7063574a3d3024170a00000000010d19242f3a43505a606d79828f949fa3a7a099928e898583818181828386898e92999fa7a39f948f82796d605b51443b3025190e0200000000000000000000000000000000000006121e2b37424d576774818e9aaba297897c6f6256493c2f24180d01000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000f1b27333e49525a5f60606060606069768390908376696060606060605f5a52493e33271b0f000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130004101c2934404b55616b7683909d92867a6d61544c55606c7884919d9285796d6053473a2d2014070000101d2936434f5b6771777879797978787674716d68625f5850483e352b1d140a0000000714202d3a46525e6976797979797979797976685e5246392d201307000c1926333f4c5966727f8c999285796a63615e574d42362a1e1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060d141a20262b2e2f33363839393736322e2d2a251f19130c0500000000000000000005101b26303a42494e4f5353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353534f4d49423930261b1004000008141e29323b414653535353535353514f4a443b32353d4448495353535353534e4c4841382f251a0f03000007121e29333c454b505253535353535346413a32281e13080000010c18222d363f454a4b535353534f4e49423a3023190f050000000000000000000000000000000000000000030f1b26313c45515d67707d8a939e9a9183786d60574d42362a1f160c0a1623303d495663707c899aa4aca196918f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8a7d7164574a3e3124170b000713202d3a4653606d798693a0aca194877b6e6154483b2e21151f2b3744505b65737f8c99a4afa99c8f8276695e52463a2d2016222f3c4955626f7c8895a2aca09386796d6053463a2d201307000004111d2935414c56606a727f8c949ea8a89d928a7d70695e53493f33271f150b010000000000000008131e28313a45515c666f7c86929fa6aba1968e81756c62574d42392e23180c0000000713202d3a4653606d7884919ea5afa69d938e837d797776757677797c80858c9298958e81747683909ca9aca0958a7e736f6e6e706b6155483c2f2316090000000004111d2935414c56616c74818e949ea6a69f959087817c79767474747577797d818790959ea5a69e948e81756d62564c41362a1e14080000000000000000000000000000000000000814212e3a47535f697884919eab9e9285796c605346392d20130700000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c7683909083766c6c6c6c6c6c6c6c645a4f43372b1e12000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201300000c18232f39434f5964717e8a97998b7f7265554b505b65727e8b97978a7d7164574a3e2f24180c0000111e2a3744515d6a778385868686858483817e7a756e6a615a50473d2f261b110600000815212e3b4854616e7b86868686868686867a6d6154473a2e211407000e1a2734414d5a6774808d9a91847770706e695e52463a2d2014070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e151a1e212226292b2c2c2b292521201e19140d0802000000000000000000000915212c38424c545a5c6060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060605c5a544c42372c21150900020e1925303b444c525f6060606060605d5b554d44393d474f54566060606060605a58534a41362b20140800000c18232f3a454e575c5e60606060605f524c443a3024190d010005111d29343f48505658606060605c5a544c42352b21160b0000000000000000000000000000000000000000000a15202935404b55616b75818e98a0958c7f72695f53463e31281e130815222f3b4855626e7b87939fa99e91848383838383838383838383838383838383827d706356493d3023160a000713202d3a4653606d798693a0aca194877b6e6154483b2e2115202d394653606c7884919eabb5ac9f93877b6e6154473d32271b222f3c4955626f7c8895a2aca09386796d6053463a2d2013070000010d19242f3a434e58606c77828f96a1aba49e92857b6e655b50443c31271d1207000000000000050e19242f3a434f59606d79839098a3aea39991847a6d605a50453c30271c12070000000b1824313e4b5764717e8a96a0acac9f948e8179716d67696869676d70747a7f869095938a7e7885929fabaa9d9184776c6261616361594f44382c201407000000000613202c3945525d68717e8a939da6a89f948f837c746f6c6668676768666d70757c838f939ea7a69e938b7f72685e52463b3025190d0100000000000000000000000000000000000815222f3b4855626e7b8896a1a89b8e8275665b5044382b1f120600000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000013202d3946535f6c767979797979797979839090837979797979797979766c5f5346392d2013000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000007121d27313e4653606d7984919c908376675d514953606d7985929b8e817468554b4035291d100400121f2c3945525f6c78859292999292918f8e8b87827c716c61594f41382d22170b00000815212e3b4854616e7b87939393939393877a6d6154473a2e211407000f1b2835424e5b6875818e9b91847d7d7d7b6e6154473b2e21140800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003090e121415191d1e1f1f1e1c181414110e09020000000000000000000000000d1925323d49545e66696c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c69655e54493d3125190d0005111e2a36414c565e6c6c6c6c6c6c6c6a675f554a3f444f5960636c6c6c6c6c6c67645c53483c3024180b00030f1b2834404b5760686b6c6c6c6c6c6c5d564c4135291d1105000915212e3a45505a62656c6c6c6c69665e54473d33271c10040000000000000000000000000000000000000000040c18242f39434f59616e7b85929f9f92867b6e615a50433a2f24190c14212e3a47535f6975818e97a29d9084787676767676767676767676767676767676706b6054483b2f221609000713202d3a4653606d798693a0aca194877b6e6154483b2e211d2935414c5563707d8996a0acacafa4998c7f7266584e43382c1d222f3c4955626f7c8895a2aca09386796d6053463a2d20130700000008131e28313d44505b656d7a849199a3ada1978f82776c60584e43392f24180e0500000000020b17202935414c56606b73808d95a0aaa69f92877d6f685d52483e332a1e150b00000005121e2a36424d576875818e9ba8afa49a8f82786d66605d555c555c6063676d727b838f9391857b8797a2ada79a8d8074675a545557554f473e33281c100400000004111d2935414c55606d7a85929ea5aca0968f82796e6a62605b545a5b545c60636a6e78818f959faba59f92857a6e61564c41362a1e11050000000000000000000000000000000003101c28343f4a5465727f8b98a8a7988b7e7165544a3f33281c0f0300000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000013202d394653606c798686868686868686909494908686868686868686796c605346392d2013000b1825323e4b5865717e8b98a4afa295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000008121d262c3844505c6674818e9b92867a6d605347515d6775828f9b918477675d5145392c1f130600121f2c3945525f6c7885929493939496999a99938e867e716b6053493f33271b0f03000815212e3b4854616e7b87949f9f9f9f94877a6d6154473a2e211407000f1c2936424f5c6975828f9c95918989897e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020608080c10121312110f0c0807050200000000000000000000000000000f1c2835414e5a6670767979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797570655a4d4135281b0f000714202d3946525e68767979797979797771675b4f434854606b70797979797979746e64584c4033271a0d0004111e2a3744505c687278797979797976685d5246392d201307000b1724313d4a56626d7179797979767066594f44382c20150a00000000000000000000000000000000000000000007121d27313e46525e69727f8b959f988f82756c61554c4135291e14121e2b37424d57616e7b85929fa0958c80736c6969696969696969696969696969696360594f44382c201307000713202d3a4653606d798693a0aca194877b6e6154483b2e21202c3945515d6775818e9ba8a39fa3ab9d9184776a605448392f24222f3c4955626f7c8895a2aca09386796d6053463a2d201307000000010c161f27333f49535e686f7d87929fa6a99f948c7f726a5f554b40352920170b020000000a141d29333b45525d68707d87939fa7aa9f948c80736b60564c41362d21180c030000000714202d3a46525e697885919eabac9f93877c6f665c54514b4f4b5153555d60696e79818f949083909da9b3a4988b7e7165584b484a48443e352c21160b000000000613202c3945515d6773808d97a1ada69e91847a6d675f5853504a4e4e4b5153585f666d79839099a3ada2978d8174685e5246392d2014090000000000000000000000000000000006121f2c3844505c6675828f9ba8a095877b6e6154483b2d22170b0000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000013202d394653606c7986939393939393939c9f9f9c9393939393939386796c605346392d2013000b1825323e4b5865717e8b98a4aca295897c6f6256493c2f23160900000d1a2733404d5a6673808d99a6aca09386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c201300030e19242f3840474a5464717e8a9799897c6f6256494b5565727e8b9893867a6d6053473a2d20140700121f2c3945525f6c78858887868787898d92979f9892887d70655b5044372b1f1205000815212e3b4854616e7b8794a1acaca094877a6d6154473a2e21140700101c2936434f5c6976828f9ca09d96968b7e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976828686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868275695c4f4236291c0f000814212e3b4754616e7a86868686868683776a5d5144495663707d8686868686868074675a4e4134271b0e0005121f2b3845525e6b788586868686867a6d6154473a2e211407000b1825323e4b5865717e8686868682766b6054483c32261b0f030000000000000000000000000000000000000000010b151f2a36424d56606c788390999e948a7e71675d51453c30261c111a26313c46525e68717e8a929c9f93887e716c605b535c5c5c5c5c5c5c5c5c5c5c56544f473d32271b1003000713202d3a4653606d798693a0aca194877b6e6154483b2e21212d3a4754606d7a86929fa3999299a3a096897c6f62554b403529222f3c4955626f7c8895a2aca09386796d6053463a2d20130700000000040d17222d38414c56606b737f8c949fa9a69f92867c6f675d51453e33291d140a000006111b262f3b45505a606d7a849199a4aea2989083786d60594f443a2f241b0f06000000000815212e3b4854616e7b8797a1adaa9d9083776a5f544b4540424045474b51575f676d78828f9590959fabb0a3968a7d7063574a3d3d3c38332c231a1005000000000714212d3a4754606d7a85929fa9aa9e94897d70685d554e46443f41414045464e545c676f7c87929faca99f92867a6e6154473c31261a0e020000000000000000000000000000000713202d3a4653606d7985929faa9d918477695e52463a2d1c11060000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000013202d394653606c798689898989898989909595908989898989898986796c605346392d2013000b1825323e4b5865717e8b989f9f9f95897c6f6256493c2f23160900000d1a2733404d5a6673808d999f9f9f9386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c20130007131f2b36404a52585a616e7b879a978a7e71645753595b626f7b889599887c6f6255493c2f221609000916232f3c4956626f7c7b7a7a7a7b7d808590959f9a9184796c605346392d201306000815212e3b4854616e7b8794a1aeada094877a6d6154473a2e21140700101d293643505c6976838f9ca9aaa3988b7e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976828f939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393938f8275695c4f4236291c0f000814212e3b4754616e7a87939393939084776a5d5144495663707c89939393938d8174675a4e4134271b0e0004101d2935404b556c788592939393877b6e6154483b2e211508000613202d394653606c7883909994897d7063584e43372b1f1306000000000000000000000000000000000000000000030d1925303b44505b666f7c87929f9e91847a6d60584e42382e231715202a36414d56616c73808d939d9a92877e736c655d554e5050505050505050504948443d352b21160b00000713202d3a4653606d798693a0aca194877b6e6154483b2e212b37434e5865717e8b98a29f9286929fa89a8e8174675d5145382c222f3c4955626f7c8895a2aca09386796d6053463a2d201307000000000006111b262f3a444f59606c77828f97a1aba3999184796d605a50453b2f261b1106030c17222d38414d57616c75818e96a1aba59f92857b6e665c50473d32281e120900000000000916222f3c4955626f7c8895a9b3a79a8d817467584e4239352f34383a40454d555c666d7a85919d9fa7b1afa396897c706356493d302f2c28211a11080000000005111e2a36424d5765727f8b98a2aea99c8f82756b60564c433c38332d2e34383c424b555f6a74818e9ba8aea3988c7f7266574d42372b1e1205000000000000000000000000000000091623303c4956636f7c8998a2aa9a8d807467574d42362a1e0a000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000a1723303d4a5663707d7d7d7d7d7d7d7d839090837d7d7d7d7d7d7d7d7063564a3d3023170a000b1825323e4b5865717e8b9393939393897c6f6256493c2f23160900000d1a2733404d5a6673808d939393939386796d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000b1723303c47525c64676c6d798693998c7f7266595d64686c6d7a8799978a7d7164574a3e3124170b000815222e3b4754606a6f6e6d6d6d6e70737a83909da096897c6f6356493c30231609000815212e3b4854616e7b8794a1acaca094877a6d6154473a2e21140700101d293643505c6976838f9ca9b1a5988b7e7265584b3f3225180c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c6976828f929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292928f8275695c4f4236291c0f000814212e3b4754616e7a87949f9f9d9084776a5d5144495663707c89969f9f9a8d8174675a4e4134271b0e0006131f2c3945515d677986939f9f95887b6e6255483b2f2215080005121f2b3744505b656f7c87939d9083766a5f53473b2e2115090000000000000000000000000000000000000000000009141f28333f4a545f6a74808d96a1978d80746a60544a3f34281f141925303b44505a606c77818e939c99928b80776d675f585045414343434343433d3b38322b23190f0400000713202d3a4653606d798693a0aca194877b6e6154483b2e212e3a47535f6a7683909daa9b8e828e97a19f9285796d6053473b30252f3c4955626f7c8895a2aca09386796d6053463a2d2013070000000000000a141d28323d44505b656d7a859199a4aba0968e81746c61574d41382d22170d0b151e27333f49535e69717e8a939ea8a89e938a7e71695e544a3f352b20160c0000000000000a1723303d4a5663707d8996a3b0a6998c7f7366594c402f2924292c2f353b434b545d68707d8a959fabb7afa396897c706356493d3023201c16100800000000000714202d3a46525e697683909daaada196897d7063594f433a312b282223282c3039434e58626f7c8895a0acaa9d908477695f53463a2d211407000000000000000000000000000004111d2935414c566673808c99aaa3988a7d7063574a3d30251a0e000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000916222f3c4854606b70707070707070768390908376707070707070706b6054483c2f221609000b1825323e4b5865717e868686868686867c6f6256493c2f23160900000d1a2733404d5a66738086868686868686786d6053463a2d201307000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000d1a26333f4c58646e7479797985929a8d8073675a646f747979778692988b7e7165584b3e3225180b0006131f2b38434e586062616160606163686f7c8899a4988b7e7265584b3f3225180c000815212e3b4854616e7b87949f9f9f9f94877a6d6154473a2e21140700101d293643505c6976838f9ca9aca5988b7e7265584b3f3225180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424f5c6875828585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858275685b4f4235281c0f000814212e3b4754616e7a8794a1aa9d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e000714202d3a4753606d7a8699a4a295897c6f6256493c2f23160900030f1b27333f49535f6a75828f9b95887c6f6255493c31261a0e02000000000000000000000000000000000000000000020b17222d38424e58606d7984919e9f93877c6f665c50443b30251a141f29323e44505b656c78818d929f9f928c81796f6a625a514c433c34363636302f2c27211911070000000713202d3a4653606d798693a0aca194877b6e6154483b2e28343f4a54626e7b88959fa398897d85919ea2988a7e7164574d42362a2f3c4955626f7c8895a2aca09386796d6053463a2d201307000000000000020b162027333f49535e68707d87939fa6a89d928a7e70695e53493f33271f15121d27303944505b656e7b85929fa5aba0968e81746c61574d42382e23190d040000000000000a1724313d4a5764707d8a97a3b0a5988c7f7265594c3f2e23181c1f24293139424c56616c7683909da9b3afa396897c706356493d302316100b050000000000000814212e3b4754616e7b87959fabab9e9184786c6053463d31281f1c17181c1f27313c47535f6a7784919daaaca095887b6e6155483b2e22150600000000000000000000000000000713202c3945525d687683909da99f92867a6d6053473a2d201409000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000713202c38444f5960636363636363697683909083766963636363636360594f44382c201307000b1724313d4a56626c71797979797979796f6a6054473b2e22150800000c1926323f4b58636e737979797979797976665c5044382c1f1206000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a67748086868689979a8d8174675b6874818686868999988b7f7265584c3f3225190c00030f1b27323d464e5456555453545456606c7986939f998c807366594d4033261a0d000815212e3b4854616e7b87939393939393877a6d6154473a2e21140700101d293643505c6976838f9c9f9f9f988b7e7265584b3f3225180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1b2834414d59656f75797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979756f65594d4134271b0e000814212e3b4754616e7a8794a1a99d9084776a5d5144495663707c8996a3a79a8d8174675a4e4134271b0e000714212e3a4754616d7a8794a0a396897c706356493d3023160a00000b17222d38414e58636f7c89959a8d807367574d42362a1e12050000000000000000000000000000000000000000000006111c262f3c45515d67707d8a949e999083786d60574d42362a1f15172027333f49535b666c74808b92989c938f847c716c605d554e463e362e292322201b160f07000000000713202d3a4653606d798693a0aca194877b6e6154483b2e2c3844505c6673808d9aa79f928679818e9baa9c8f8276695e52463a2d2f3c4955626f7c8895a2aca09386796d6053463a2d20130700000000000000040e17222d38414c56606b73808c949fa9a59e92857b6e655b50443c31271d18232e39424e58606c77828f97a2ada3999184796d605a50453b30261c1007000000000000000a1723303d4a5663707d8996abb5a6998d807366544a403428211e1a181f27303a44505a64707d8a97a2adafa396897c706356493d3023160a00000000000000000b1824313e4b5764717e8a97a7b1a79a8e8174665b5044382b1f160f0b0c10151f2b37434e586773808d9aa6b1a7988b7e7165584b3e2d22170b00000000000000000000000000000714212d3a4754606d7a86929fa99c8f8276675d5145392c1f1306000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000004101c27333d474f5456565656565d69768390908376695d5656565656544f473d33271c1004000915212e3a45505a62656c6c6c6c6c6c6c6260584e43382b1f130600000a17232f3b47525c63666c6c6c6c6c6c6c6c5c544a3f34281c1003000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d939393a19a8e8174675b6874818e939394a3998c7f7366594c403326190d00000a162027333f49535b606060606062666e7b8799a4988c7f7265594c3f3226190c000815212e3b4854616e7b86868686868686867a6d6154473a2e21140700101d293643505c6976828f93939393938b7e7265584b3f3225180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1925313d49545d65686c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c68655d53483d3125180c000814212e3b4754616e7a87949c9c9c9084776a5d5144495663707c89969c9c9a8d8174675a4e4134271b0e000815222e3b4855616e7b8894a1a3978a7d7064574a3d3124170a000006111b262f3c4854606b7783909d918478695f53463a2d21140700000000000000000000000000000000000000000000000a141d2935414b55616c75828f98a0958b7f72695e52463e31271d1217222d38414a545b606e737e8691969e9691867e756d675f58504840372e261c13100b0400000000000713202d3a4653606d798693a0aca194877b6e6154483b2e2d3a4653606d7985919ea99c8f82767e8a99a39f93877b6e6154483d322f3c4955626f7c8895a2aca09386796d6053463a2d201307000000000000000006111b262f3a444f59606d78828f97a1aca1978f82776c60584e43392f241f2834404b545f6a727f8c949fa9a69f92877c6f675d51483e33291e140a00000000000000000915222f3c4855626f7b8899a3afa89b8f8275665c51443a322d2b2627272628323e4653606d7985929fabafa396897c706356493d3023160a00000000000000010e1b2834414e5b6774818e9aa7b4aa978a7e7164544a3f3328190d040000040d1b26323d4a5764707d8a97aab4a79b8e81746853493f33271b0f03000000000000000000000000000b1724313e4a5764717d8a99a3a9988c7f7265554b4035291d1004000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000b16212b353d44484a4a4a4a505d69768390908376695d504a4a4a4a48443d352b21160b000005111d29343f485056586060606060606056544e463d32271b0f03000007131f2a36404a52585a606060606060605f504a42382e23170c00000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d9a9fa0a79b8e8174685b6874818e9b9fa0a6998c807366594d4033261a0d000005121f2b3744505b656c6d6c6c6d6f7278818e9ba095897c6f6356493c30231609000714202d3a46525e6976797979797979797976685e5246392d20130700101d293643505c697682868686868686867e7265584b3f3225180c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915212c37424b54595c5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5b59534b42372c201509000814212e3b4754616e7a878f8f8f8f8f84776a5d5144495663707c898f8f8f8f8d8174675a4e4134271b0e000915222f3c4855626f7b8895a2a4978a7e7164574b3e3124180b000007111b252c38434f5966737f8c9996887b6e6155483b2e2215080000000000000000000000000000000000000000000000020b18242f3a43505a616e7b86929f9f92867b6e61594f43392f2418111b262f38424a505c636c717c848e939f98928b817a6f6a625a524940382e251c11080000000000000713202d3a4653606d798693a0aca194877b6e6154483b2e36414c5664707d8a97a1a8988c7f727a86929fa4998c7f7366594f43382f3c4955626f7c8895a2aca09386796d6053463a2d2013070000000000000000000a141d29323d44505c666e7b85929aa4a99f948c7f726a60554b40352928313a45515c666f7c86929fa6a99f948c7f736a60554b41362c21170c0200000000000000000714202d3a4753606d7a86929facab9e9285796d60564c443d3a373134333332323845515c6675828f9ca8afa396897c706356493d3023160a0000000000000005111e2a36414c566a7683909da9aea298887b6e6155483b2d221708000000000a15212e3b4854616e7b8798a2aeaa9d908377655b5044372b1f120500000000000000000000000006121e2b37424d576774818e9aaba197887c6f6255483c2f24180c00000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000050f19232b33383c3d3d3d43505d69768390908376695d50433d3d3d3c38332b23190f050000010c18222d363f454a4b535353535353534947433d342b20160a000000020e19242e3840474b4d5353535353535353443f3830261c110600000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d9aa7b3a79b8e8174685b6874818e9ba7b3a6998c807366594d4033261a0d00000613202d394653606c777979797a7b7e838e939e989083786c605346392d2013060005121e2a36424d575e6c6c6c6c6c6c6c6c6c6c5e564c41362a1d1105000f1c2835414e5a66707679797979797979726d62564a3d3124180b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101b26303942494d4f5252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252524f4d48423930251b0f04000714212d3a4754606d7a8283838383838174675b4e414855626f7c8283838383827f7265584c3f3225190c000916232f3c4956626f7c8995a2a5988b7e7265584b3f3225180c00010d18232d373f464956626f7c8999978a7d7164574a3e3124170b00000000000000000000000000000006060606060606060007131d28313e46535e69727f8c95a0988e81756b61554b4035291d14141d262f383f44525a616a6f7a818b92989f938e847c716c635b524a40372e231a0d0400000000000713202d3a4653606d798693a0aca194877b6e6154483b2e3946525e6875828f9ba9a196887b6f76828f9cab9e9184776b605448392f3c4955626f7c8895a2aca09386796d6053463a2d201307000000000000000000020b172028343f4a545e69707d88939fa7a69f92877c6f675d51453e332f3a434f59606d79839098a3ada2979082786c60584e433a2f241a0f0500000000000000000006131f2c3945515d677783909dabada1978a7e71685e564f484742424140403f3f3f404b546673808c99a6afa396897c706356493d3023160a000000000000000713202d3946525e687885929fabac9f9285796c605346392d201306000000000714212d3a46535e697985929facac9f9285796c605346392d2013060000000000000000000000000814212d3a47535f697884919eab9e9185786c605346392d20130700000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000005101a232c33393c3d3d3d43505d69768390908376695d50433630302f2c27211911080000000006111b242d343a3d3e464646464646463c3b38322b22190f040000000008121c262e363b3f40464646464646464638342e261e150a0000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d9aa7aca79b8e8174685b6874818e9ba7aca6998c807366594d4033261a0d00000613202d394653606c7984868687888b90959a9590867c6f665b5044382b1f120600020e1a25303b454d525f60606060606060605f524c443a3025190d01000d1926323e49545e66696c6c6c6c6c6c6c65625b51453a2e22150900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141e2730373d414246464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464642413d3730271e140900000713202c3945525d686d767676767676746f64584c4047535f6a6f767676767676726d62564a3e3125180b000a1723303d4a5663707d8996a3a5988c7f7265594c3f3226190c0006121e29353f49515759606d798692998c7f7366594c403326190d0000000000000000000002060a0c0d131313131313131313130c161f2a36424d57606d788390999e938a7d70675d51453c2f261b11141d262d33404850585f686d757e8690959d9691867e736d645c524940352c1f160c01000000000713202d3a4653606d798693a0aca194877b6e6154483b2e3a4754616d7a86929fab9e9184786a727f8b99a4a096897c6f63554b40353c4955626f7c8895a2aca09386796d6053463a2d20130700000000000000000000050e17232e38424d56616b73808d959fa9a3999184796d605a50453b35414c56606b73808d95a0aaa59f92857b6e665b50463d31281d12080000000000000000000004101d2935404b5566737f8c99a3aea99e91847a6d68615955534d4f4e4d4c4c4c4b4b4c5865727f8b98a5afa396897c706356493d3023160a000000000000000714212e3a4754616d7a8798a2aeaa9d918477665b5044382b1f12060000000005121e2a36424d576a7784919daaaea298877a6e6154473b2e2114080000000000000000000000000815222e3b4855616e7b8896a1ac9b8e8174655b5044372b1f120500000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000b17222c363e44494a4a4a4a505d69768390908376695d5043362a2322201c160f0800000000000009121b22292e3132393939393939392f2e2b27201910070000000000000a141c242a2f323339393939393939392c28231c150c030000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d9a9f9f9f9b8e8174685b6874818e9b9f9f9f998c807366594d4033261a0d000006121f2b3844505b6673808c9993999292908d89837c6f6a5f544a3f33281c0f03000009141f29333b42464853535353535353535346413a32281e130800000915212d38424c545a5c60606060606060585651493f34291d1105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c151e262c3134353939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393534312c251e150c02000004111d2935414c565d6069696969696967645c53483c434e585f6269696969696965625b51463a2e221609000a1724313d4a5764707d8a97a3a6998c807366594d4033261a0d000916222e3a46515b62656c667885919a8d8174675a4e4134271b0e000000000000000000070d121619192020202020202020202020201a25313b44505c666f7c87939f9e9184796d60584e41382d22170b141c2228363e464e565d606c717b838d929f98928b80736e645b51473d31281e1308000000000713202d3a4653606d798693a0aca194877b6e6154483b37434e5865727f8c99a3a99a8d8074676e7b87939fa89a8e8174675d5145393c4955626f7c8895a2aca09386796d6053463a2d201307000000000000000000000006111c26303b444f59606d78839097a2aba0968e81746c61574d423b45525d68707d87939fa7a89d938a7e71695e544a3f342b1f160c0000000000000000000000000c18242f3b4854616e7b86929fa8ada19690827a706b65615f575c5a5a5959585858585865717e8b98a4afa396897c706356493d3023160a000000000000000915222f3c4855626f7b8895aab4a99c8f837669544a3f33281c0f0300000000020e1a2531434f5c6976828f9ca9b4aa95887b6f6255483c2f221509000000000000000000000003101c28343f4a5465727f8b98a8a49a8a7e716453493f33271b0f0300000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000004101c28333e48505557575757575d69768390908376695d5043362a1d1613100b0500000000000000000911181d2124252d2d2d2d2d2d2d23221f1b160f0700000000000000020a12191f2326272d2d2d2d2d2d2d2d1f1c17110a03000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a6774808d93939393938e8174685b6874818e93939393938c807366594d4033261a0d0000030f1c28333f4a54616e7b87939f92878583817d786f6a5f584e42382d22170b000000020d17212930363a3b4646464646464646463936302820160c02000005101b26303a42494e50535353535353534b4a453f372d23180c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030c141b212528292c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c282725201b140c03000000010d1924303a444c52545c5c5c5c5c5c5b58534a41363c464e53555c5c5c5c5c5c585651493f34291e1206000b1824313e4b5764717e8a97a4a69a8d8073675a4d4034271a0d000b1825313e4a57626d7279797983909b8e8275685b4f4235281c0f00000000000000010a12191e2325262d2d2d2d2d2d2d2d2d2d2d2d2d2d28343f4a54606a74808d97a1968d80736a5f53493f33271e13111317242d343c444c525a62696e78808b92999f928c80736d63594f433a2f24190d010000000713202d3a4653606d798693a0aca194877b6e6154483b3b4754606a7784909daba197897c70636876838f9caa9f9285796d6053473b3c4955626f7c8895a2aca09386796d6053463a2d2013070000000000000000000000000a141e29323e44505c666e7b85929fa4a89d938a7e70695e544a45505a606d7a849199a4aba0968e81746c61574d42382d22190d040000000000000000000000000714202d3a46525e6974808d96a1a9a89f9590847d77726e696a6867666665656565646465717e8b98a4afa396897c706356493d3023160a000000000000000a1723303d4a5663707d8996a3b0a89b8e8275685b4f422d22170b000000000000091c2835424f5b6875828e9ba8b0a396897d7063564a3d3023170a000000000000000000000006121f2c3844505c6675828f9ba89f93877a6e6154473b2d22170b0000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000814202d3944505a6164646464646469768390908376695d5043362a1d1007040000000000000000000000060c11151718202020202020201615130f0a0400000000000000000000080e1317191a202020202020202012100c060000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000e1a2734414d5a677480868686868686868174685b68748186868686868686807366594d4033261a0d0000000b17222d3846535e6976828f9b8f82787774706c655f584e463c2f261c110600000000050f171f252a2d2e39393939393939392e2d2a251e160e05000000000a141e2830383e4143464646464646463f3d3a342d241b110600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002091015191b1c1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1c1b18150f0902000000000008131e28323a4145475050505050504e4c4841382f343c4347485050505050504c4a463f372d23180d01000c1825323f4b5865727e8b98a5a79a8e8174675b4e4134281b0e000c1926323f4c5965727f86868689959c8f8275695c4f4236291c0f000000000000000a131c232a2f32333939393939393939393939393939392e38424e58606d7a85919e9f92877c6f655b50443a3025191d202021222a323a414550575f666d747e8792989c928c7f726b61564c4135291d13070000000713202d3a4653606d798693a0aca194877b6e6154483b404b55626f7c8995a0ab9e9184796d6064717e8b98a2a2988a7e7164574d423c4955626f7c8895a2aca09386796d6053463a2d201307000000000000000000000000020c172028343f4a545e69707d8a929da7a59e92857b6e665b504d57616c75818e96a1aba3999184796d605a50453b2f261c10070000000000000000000000000005121e2a36424d57606d79849197a1a9a79f969189837f7b78767574737372727271717171717e8b98a4afa396897c706356493d3023160a000000000000000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b060000000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a00000000000000000000000713202d3a4653606d7985929faa9d908377685e5246392d1b11060000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000a1623303c4955616c70707070707070768390908376695d5043362a1d1003000000000000000000000000000105090b0b13131313131313090806030000000000000000000000000002070a0c0d1313131313131313060300000000000000000714202d3a4753606d7a8693a0adac9f9286796c5f5346392c2013000d1a26333f4c58646e7479797979797979746f6459646f7479797979797979736e63574b3f3226190c00000006111c2a36424d5764717e8a9792877b6e6763605b534e463c342a1d140a000000000000050d141a1e20212d2d2d2d2d2d2d2d21201d19130c050000000000030c161e262d3235363939393939393932312e29231b120900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090c0e0f1313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313130f0e0c090400000000000000020c1620283035393a43434343434341403c362f262a32373b3c4343434343433f3e3a342d251b110700000c1926323f4c5965727f8c98a5a89b8e8175685b4e4235281b0f000c1926323f4c5965727f8c93939d9f9c8f8276695c504336291d1000000000000007121c252e353b3e4046464646464646464646464646464646464645525d68717e8a949f999083776c60564c41362a24292c2d2e2f30302f353e454d545c606c717d8692999f93887d70685d52453a2f24180d0100000713202d3a4653606d798693a0aca194877b6e6154483b45515d6774818d9aa7a6998d8073665c606d7a85929faa9c8f8276695e53463c4955626f7c8895a2aca09386796d6053463a2d20130700000000000000000000000000050e17232e38424d57616c74808d959faaa2978f82786c6058535e69717e8a939ea8a69f92877c6f675d51483e33291d140a0000000000000000000000000000020e1a25303b45515d676f7c8591979ea5a8a09e95908b8885838281807f7f7f7e7e7e7e7d7d808d9aa7afa396897c706356493d3023160a000000000000000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b0a4978a7d7164574a3e3124170b0000000000000000000000091623303c4956636f7c8998a2aa998d807366564c41362a1e0a000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000a1724313d4a5764707d7d7d7d7d7d7d7d8391908376695d5043362a1d100300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202d3a4753606d7a8693a0acac9f9286796c5f5346392c2013000b1723303c47525c64676c6c6c6c6c6c6c68645d535d64686c6c6c6c6c6c6c66635c52473b2f23170a000000000e1a25313b4653606d798592998c8073665c535049413c342a22190b020000000000000002090e12141520202020202020201413110d080200000000000000040c141b212628292d2d2d2d2d2d2d2524221d18110900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e161e24292c2d3636363636363433302b251d20262b2e2f36363636363632312e29231b13090000000d1a2633404d596673808c99a6a89c8f8275695c4f4236291c0f000c1926323f4c5965727f8c989faaa99c8f8376695c504336291d100000000000020d19232e3740464b4c535353535353535353535353535353535353534c56616c76828f989f948b7e71685e52463d302f35393a3b3c3c3d3d3c383b424a515a626b707e87939f9a92857a6d60554b4135291d110400000713202d3a4653606d798693a0aca194877b6e6154483b4753606d7985929fab9f94887b6e62545d6774818e9ba89f93877b6e6154483d4955626f7c8895a2aca09386796d6053463a2d201307000000000000000000000000000006111c26303b45505a606d78839098a2a99f948c7f726a605b656e7b85929fa5a99f948c7f726a60554b40362c21170b0200000000000000000000000000000009141f2935414b555f6a6f7c858f939c9fa4a79f9d989892908f8d8d8c8c8b8b8b8b8a8a8a8d929da9afa396897c706356493d3023160a000000000000000b1825313e4b5864717e8b97a4b1a79a8d8074675a4d4134271a0e0100000000010e1a2734414d5a6774808d9aa7b1a4978b7e7164584b3e3125180b0000000000000000000004111d2935414c566673808c99aaa298897d706356493d3025190d000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000013202d394653606c79868a8a8a8a8a8a8a9195908376695d5043362a1d1003000000000000000000000000000000000000000000010406070d0b0a08050000000003080b0d0e0d070604000000000000000000000000000000000000000000000714202d3a4753606d7a86939f9f9f9f9286796c5f5346392c20130007131f2b36404a52585a606060606060605b59534b53595b606060606060605957524a40352a1f13070000000009141f2c3845515c67748086868685796d6053463f382f2a22191007000000000000000000000205070813131313131313130707050100000000000000000000030a1015191c1d20202020202020181815110c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c13191d2021292929292929282724201a13151b1f21222929292929292525221e181109010000000d1a2734404d5a6773808d9aa6a99c8f8376695c504336291d10000c1926323f4c5965727f8c98a5b2a99c8f8376695c504336291d10000000000006121e2a3540495157596060606060606060606060606060606060606060605a616e7b86929f9e92857a6d61594f42393a4045474848494a4a48443d3940445059616c73808c96a0978d8073675d5145392c20130600000713202d3a4653606d798693a0aca194877b6e615448424d5764717e8a97a2aa9c908376695f535563707d8996a1a49a8c7f7366594f444955626f7c8895a2aca09386796d6053463a2d2013070000000000000000000000000000000a151e29333e45515c666e7b85929fa5a69f92877c6f67606c77828f97a2ada1978f82776c60584e43392f241a0f0500000000000000000000000000000000020d18242f3a434e585f6a6f7a82898f93999c9fa2aaa29f9d9b9a999998989898979797979a9da4aeafa396897c706356493d3023160a000000000000000b1824313e4b5764717e8a97a4b1a79a8d8174675a4e4134271b0e0100000000010e1b2734414e5a6774818d9aa7b1a4978a7e7164574b3e3124180b000000000000000000000713202c3945525d687683909da99f9285796d6053463a2d201308000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000013202d394653606c7986939393939393939393908376695d5043362a1d10030000000000000000000000000000000000000001070d1113141a181715110c0601080f14181a1b191413100c0701000000000000000000000000000000000000000714202d3a4753606d798693939393939286796c5f5346392c201300030e19242f3840474c4d535353535353534e4d4841484d4e535353535353534d4b4740382e24190e020000000004101c2834404b55646e74797979786d665c5044382d261d18100700000000000000000000000000000000000000000000000000000000000000000000000000000005090d0f10131313131313130c0b090501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080d1113141d1d1d1d1d1d1b1a18140f080a0f1215151d1d1d1d1d1d191816120d0700000000000e1b2734414e5a6774818d9aa7aa9d9083776a5d5044372a1d11000c1926323f4c5965727f8c98a5aca99c8f8376695c504336291d1000000000000a16232f3b46515b63666c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6b69727f8c95a0978e81746b60544b40434b51535455565756554f473d343f47505a606d7884919e9f92857a6d6054473a2d21140700000713202d3a4653606d798693a0aca194877b6e61544846535e6976828f9ca9a2988b7e7165574d53606c7884919eac9e9184776b6054484955626f7c8895a2aca09386796d6053463a2d201307000000000000000000000000000000030c17212834404b545f69717e8a929da7a3999184796d6a727f8c949fa9a49e92857b6e655b50463c31281d120800000000000000000000000000000000000007131d28313c464e585f686d757c82878b8f929897999a9b9c9d9d9d9e9e9e9e9f9f9f9fa3abacb5afa396897c706356493d3023160a000000000000000a1724313d4a5764707d8a97a3b0a79a8e8174675b4e4134281b0e0100000000010e1b2834414e5b6774818e9aa7b0a3978a7d7064574a3d3124170a000000000000000000000714212d3a4754606d7a86929fa89c8f8275665c5145382c1f1306000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000013202d394653606c7986868686868686868686868276695d5043362a1d1003000000000000000000000000000000000000040c13181d2020272524211d17100b131a2024272726201f1c18120b030000000000000000000000000000000000000714202d3a4753606d798686868686868687796c5f5346392c2013000008121d262f363c3f414646464646464641403c373c404146464646464646403f3b352e261c12070000000000000c18232e3943525c64676c6c6c6b605c544a3f34281b140b0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010407071010101010100e0d0b08030000030608091010101010100c0b0906010000000000000f1b2835424e5b6875818e9b9f9f9d9184776a5e5144372b1e11000c1926323f4c5965727f8c989f9f9f9c8f8376695c504336291d1000000000000c1925323e4b57636d737979797979797979797979797979797979797979797978736d7883919a9e93897d70665c51454b555d60616263636360594f4438353e44505c66727f8b98a2988a7e7164574b3e3124180b00000713202d3a4653606d798693a0aca194877b6e6154484953616e7b87939fac9f92867a6d605447505b6573808c99a6a096897c6f63554b4955626f7c8895a2aca09386796d6053463a2d20130700000000000000000000000000000000050f18232e39424d57616c74818e95a0aaa0968e81746f7c86929fa6a79d928a7d70695e53493f342b1f160c00000000000000000000000000000000000000010c161f2a343c464e565e616b6f757b7f8285888a8c8d8f8f9090919191919292929292999ba3acafa396897c706356493d3023160a000000000000000a1723303d4a5663707d8996a3b0a89b8e8175685b4e4235281b090000000000020f1b2835424e5b6875818e9ba8b0a3968a7d7063574a3d3024170a000000000000000000000b1724313e4a5764717d8a99a3a8988b7f7265544b4034281c1004000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000013202d3946535f6c7679797979797979797979797670665a4e4235291c0f030000000000000000000000000000000003090d161d24292c2d3431302d28221b141d252b303334332d2c29231d150d09030000000000000000000000000000000006131f2c3845515c67767979797979797979756a5e5245382c1f120000010b141d242b303334393939393939393534302b3034353939393939393933322f2a241c130a0000000000000007121d2730404a52585a6060605e53504a42382e23170a02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2935424f5c6875818f939393939184786b5e5245382b1f12000c1926323f4c5965727f8c93939393938f8376695c504336291d1000000000000d192633404c5966737f868686868686868686868686868686868686868686868578666f7d88939f9d9184796d60574d515d676d6e6f6f70706b6055483d32343f4a54616e7b8899a49a8d8174675a4e4134271b0e01000713202d3a4653606d798693a0aca194877b6e615448505b6573808c9aa4a89b8e8174675d51454953616e7b88949fa89a8e8174675d514955626f7c8895a2aca09386796d6053463a2d201307000000000000000000000000000000000007121d27303b45505a606d79839098a2a89d938a7e79839098a3aaa0958d80746c61564d41382d22190d040000000000000000000000000000000000000000040d18222a343c444c52596063696e7276797b7d7f81828383848484848585858585868b909ba7afa396897c706356493d3023160a000000000000000916222f3c4955626f7c8895aab4a99c8f8276695c4f4330251a0e0200000000030f1c2936424f5c6975828f9ca8b5ab95897c6f6256493c2f23160900000000000000000006121e2b37424d576774818e9aaba196887b6e6255483b2e23180c00000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000121e2b37434f5a646c6c6c6c6c6c6c6c6c6c6c6c69665e544a3e32261a0d01000000000000000000000000000000060e151a1f282f35393a403e3d39342d241d262f363c4041403a38342f271f1a140d0500000000000000000000000000000004101c2934404b555c6c6c6c6c6c6c6c6c6c6a63594e42362a1d11000000020b12191f2326272d2d2d2d2d2d2d282724202427282d2d2d2d2d2d2d2626231f19120a0100000000000000000b151e2f3840474c4d5353535246443f3830261c11060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c2936434f5c69768286868686868685786c5f5245392c1f12000c1926323f4c5965727f868686868686868276695c504336291d1000000000000d192633404c5966737f8c93939393939393939393939393939393939393939185786b6b74818e97a0968c7f73695f5353606d797b7b7c7d7d7063584e4338313a4653606d7986939f9c8f8276695c4f4336291c1003000713202d3a4653606d798693a0aca194877b6e61544853606c7884919eaca096897c7063554b4146535f697683909caa9f92857a6d60534955626f7c8895a2aca09386796d6053463a2d2013070000000000000000000000000000000000000b151e2a333e45515c676e7b86929fa5a59e9285818e95a0aaa3989183796d60594f443b2f261b1007000000000000000000000000000000000000000000050e171e252a323a41464f54575e6165666d6f717374757676777777787878787879797e8b98a4afa396897c706356493d3023160a000000000000000814212e3b4754616e7b8798a3aeaa9d9084776a574d42362a1e12050000000005111d2935414c566a7783909daaafa399877b6e6154483b2e2115080000000000000000000814212d3a47535f697784919eaa9e9184786a5f53473a2e1d120700000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000f1b27333e49525a5f60606060606060606060605d5a544c43382d22160a000000000000000000000000000000060f1820262b313a4045474d4b49453e362d222f3841484c4e4c47454039312a251f170f050000000000000000000000000000000c18232f39434b515f606060606060605f5e5951473d31261a0e0000000001080e13171a1a202020202020201b1a1814181a1b202020202020201a1917130e0700000000000000000000030c1d262f363c3f41464646453a38342e261e150a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1c2835414e5a6670767979797979797873695d5144382b1e12000b1825313e4a57626d72797979797979797670665a4e4235291c0f00000000000d192633404c5966737f8c999999999999999da0a7a9a29f999999999999999185786b616d7a85929e9f92867b6e615a5c6976828788898a85786a605448423f404653606d798699a49c8f8376695c504336291d1003000713202d3a4653606d798693a0aca194877b6e61544c5663707d8996a1ab9e9184786c6053463a424d5765717e8b98a2a2988b7e7164574d55626f7c8895a2aca09386796d6053463a2d201307000000000000000000000000000000000000030c18212934404b555f69717e8b939ea7a297928e939da7a69f92867c6f675d51473e32291d140a000000000000000000000000000000000000000000020c1720293036393a3e3f44484d5354545c606264666768696a6a6a6b6b6b6b6c6c6c717e8b98a4afa396897c706356493d3023160a000000000000000713202d3a4653606d7986929facab9f928578695e52463a2d201407000000000713202d3946525d687885929eabac9f9286796d6053463a2d2013070000000000000000000815222e3b4855616e7b8896a0ab9a8e817467584e43372b1f0b0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000a16212c3740494f535353535353535353535353504e4a433a31271c11050000000000000000000000000000030e18212a31373e434b51535a585650483e322b34414a53585a5953514b433e36312921170d03000000000000000000000000000007121d2731394045535353535353535353524e473f352b20150900000000000003070b0d0e131313131313130e0e0c080c0e0e131313131313130d0c0a07020000000000000000000000000b141d242b303334393939382d2c28231c150c030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1926323e49545e66696c6c6c6c6c6c6c6961574c4135281c10000916222e3a46515b62656c6c6c6c6c6c6c69665e54493e3226190d00000000000d192633404c5966737f8c8c8c8c8c8c8c8c9095a0a297928c8c8c8c8c8c8c8c85786b5d68717e8b949f988f82766c61566673808d959697897c6f625b534d4c4d4f58626f7c8895ab9b8e8275685b4f4235281c0f02000713202d3a4653606d798693a0aca194877b6e6154525d6875818e9ba8a4998c7f73655b5044373b4754606d7a86929faa9c8f8276695e5355626f7c8895a2aca09386796d6053463a2d20130700000000000000000000000000000000000000060f18232f39434d57616c74818e95a0a9a29e9b9da5a99e948b7f726a5f554b40352c20170b0200000000000000000000000000000000000000000008131e29323a4146474b4c4d4e4f51524a50535557595a5c5c5d5d5e5e5e5e5f5f5f65717e8b98a4afa396897c706356493d3023160a0000000000000006121f2b3844505c667784909daaaea298877b6e6154483b2e21150a000000000714212e3a4754616d7a8797a1adaa9e918477665c5145382c1f1306000000000000000003101c28343f4a5465727e8b98a8a4998a7d7164574a3e31261a0f0000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000005101b252e373e4346464646464646464646464643423e3831281f150a0000000000000000000000000000000915202a333c424750555d606764615a50443a323d46535c646766605c554f46423b33291f14090000000000000000000000000000010b151f272f343846464646464646464645423d352d24190f0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b131a1f2426272d2d2d2b201f1c17110a03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000915212d38424c545a5c6060606060605f5d574f463b3024180c0006121e29353f49515759606060606060605c5a544c42382d21160a0000000000091623303c4956636f7d808080808080808083909d9f928580808080808080807f726556626c76828f989f948a7e71685d626f7c89959f9c8f82756d615e57595959616a73808d99a8998d8073665a4d4033271a0d00000713202d3a4653606d798693a0aca194877b6e615454606d7a86929fac9f93877b6e6153493f333945515d6775818e9ba89f93877b6e615355626f7c8895a2aca09386796d6053463a2d201307000000000000000000000000000000000000000007121d27313c45505a606d79839198a2adaba7a9ada1978f82776c60584e43392f231a0e05000000000000000000000000000000000000000000010d1925303a444c525457595a5b5c5d5e5b5953484a4c4e4f5050515151515252525965727f8c98a5afa396897c706356493d3023160a0000000000000003101c28343f4a546875818e9ba8b3aa978a7d7064574a3d32271b0d04000001081623303d495663707c8996a9b3a89c8f827569544b4034281c1004000000000000000006121f2c3844505c6675828f9ba89f93867a6d6054473a2d2114090000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000009131c252c33373939393939393939393939393635322d271f160d030000000000000000000000000000020e1a26313c454e535a61676d73716c61564c4137434e58646e74736d676159534d453b31251a0e020000000000000000000000000000030d151d23292c3939393939393939393836312b241b120800000000000000000000000104060712131313130908060300000000000000000000000000000000000000000000000000000001080e13171a1a2020201f1312100c0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005101b26303a42494e4f53535353535352514c463d342a1f130800010d18232d373f464a4c53535353535353504e49423a31261c100500000000000915222f3b4854606b6f7373737373737374818e9b9e91847873737373737373726d62575a626e7b86929f9e91857a6d60606a7783909a9e948c7f756e69676666676b707c86929fa096897c6f6356493c3023160900000713202d3a4653606d798693a0aca194877b6e61545865727e8b98a3a99c8f8276695e5341382d35414b5563707d8996a1a49a8c7f73655b55626f7c8895a2aca09386796d6053463a2d2013070000000000000000000000000000000000000000010b151f2a333e45515d676f7c86929facb8b4b8ab9e92857a6d655b50463c31271d11080000000000000000000000000000000000000000000005111d2a36414c565e6164656768696a6b68655d534840414243434444444545454d596673808c99a6afa295897c6f6256493c2f23160900000000000000000b17232e3f4b5865727e8b98a8b2a69a8d807367584e43372b1f15100c090e131e2a36414c5666727f8c99a5b3aa998c7f7366594c402e23180c0000000000000000000713202d3a4653606d7985929fa99d908376685d5245392c2013070000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000010a131b21272b2d2d2d2d2d2d2d2d2d2d2d2d2a2926221c150d0400000000000000000000000000000006121e2b37424e575f626c7179807e71685d52453c4754606a74817f79706b615e574d42362a1e1205000000000000000000000000000000030b12181c1f2d2d2d2d2d2d2d2d2c2c2a26201912090000000000000000000001070d1013141e202020201615130f0a0400000000000000000000000000000000000000000000000000000003070b0d0e131313120706030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141e2830383e41434646464646464544413b342b22180d02000007111b252d353a3e3f4646464646464643423e3831281f150a0000000000000713202c38444f5960636666666666666874818e9b9e9184786b66666666666665625b51535f6973808c96a0978d80746a6063707d88939f9c918c817b7673727374777d859298a29e9184786d6053463a2d20130700000713202d3a4653606d798693a0aca194877b6e61545f6a7683909daaa2978a7e7164574d422f262f3a4653606c7884919eac9e9184786c6055626f7c8895a2aca09386796d6053463a2d201307000000000000000000000000000000000000000000030d18212935404b555f6a737f8c99a6b2bdb0a3968a7d70685e53493f342a1f150b00000000000000000000000000000000000000000000000713202d3946525e686d71727374767778756f65594d3d323536373737383835404b556774818e9aa7b2a995887b6e6255483b2f22150800000000000000000615222f3c4855626f7b8896a0acaa9d9184776a6054473c31271f1c181b1a1e242d3946525e6876838f9ca9aea298897c706356493d30231607000000000000000000091623303c4956636f7c8998a2aa998c807366564c4135291d11040000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000010910161b1e2020202020202020202020201d1c1a16110a03000000000000000000000000000000000814212e3a47535f6a6e767e848d857a6d60584e43505a626f7c888c847d756e695e53463a2d2114070000000000000000000000000000000001070c10132020202020202020201f1d1a150f0800000000000000000000040c12181d20202b2d2d2d2d22211f1b150e070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020c161e262d323536393939393939393835302a22191006000000000a131b23292e3132393939393939393635322d261f160d03000000000000030f1b27323d474f545659595959595b6874818e9b9e9184786b5e5959595959595751494d57606d7984919e9f93877c6f66606b73808d939f9c938e8783807f8081848a9297a19f928a7d70665c5044382b1f120600000713202d3a4653606d798693a0aca194877b6e6154626f7c88959fab9f9285796d6053473b31202b3844505b6673808d99a7a096897c706355626f7c8895a2aca09386796d6053463a2d20130700000000000000000000000000000000000000000007121d27313c46505a606d7984919eaab7b9b1a4978b7e71695f554b40342820170b02000000000000000000000000000000000000000000000714212e3a4754616d7a7e7f8081828485817568584e43372e2c2823282c2f3945515d677783909daaada196877a6d6054473a2d21140700000000000000000815212e3a47535f6a7784919eabaca095887c6f62584e4339312c282327262b2f35414c56616d7a86929facab9f9285796d6053463a2d201307000000000000000004111d2935414c566673808c99aaa298897c6f6356493c3024190d010000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000050a0f12131313131313131313131313100f0d0a050000000000000000000000000000000000000815222f3b4855626e7c828a91968d80746a5f534b55616c76839096918a827b6e6154483b2e21150800000000000000000000000000000000000000040613131313131313131312110e090400000000000000000000040d161d24292c2d38393939392f2e2b2620181007000000000000000000000004090d0f0f131313131313130d0c0a060200000000000000000000000105090b0b13131313100f0d0905000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c141b212628292d2d2d2d2d2d2c2b28241f1810070000000000010a11181e2225262d2d2d2d2d2d2d292926211c150d0400000000000000000b16212b353d4448494d4d4d4d4e5b6874818e9b9e9184786b5e514d4d4d4d4c4a463f45515c67707d89939e999083786d60606c77808c92989f9992908d8c8c8e91969e9f99928c80736b61544a3f34281c100300000713202d3a4653606d798693a0aca194877b6e615c6673808d9aa7a79a8d8174675c5145382c1f28333f4a54626e7b88959fa89b8e8174675d626f7c8895a2aca09386796d6053463a2d2013070000000000000000000000000000000000000000060f18242f39434e58626c75818e96a0acafacafac9f92867b6e675c51453e32291d140a000000000000000000000000000000000000000000000815212e3b4854616e7b878c8d8e8f909184786a6054473f3a38342e34383a404b55606d7a86929facab9e918578675d5145392c201306000000000000000006121f2b37434e586673808d99a3afa89b8e81756a5f554b433c38342e3431373a4145525d68737f8c99a3afa79b8e8175675c5145382c1f130600000000000000000713202c3945525d687683909da99f9285796d6053463a2d201308000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d1a2734404d5a6773808d949e9f92877c6f625a515c67717e8a949f9e93867d7063574a3d3024170a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c161f282f35393a45464646463c3b37322a22180e04000000000000000002091015191b1c20202020202020191916120d07000000000000000000060c11151718202020201d1c1915100a030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a1015191c1c2020202020201f1e1c18130d060000000000000000070d12161819202020202020201d1c1916100a03000000000000000000040f19232b32383b3c404040414e5b6874818e9b9e9184786b5e51454040403f3e3a34404b55606b75818e97a0958c7f72695e656c777f868e92999b9c9a99999a9d9b99938f867f736e63594f42382e23170b0000000713202d3a4653606d798693a0aca194877b6e61606d7985929eaba095897c6f62554b4034291c222d3847535f697683909daa9f92857a6d60626f7c8895a2aca09386796d6053463a2d20130700000000000000000000000000000000000000030c18212935404b555f6a717e8b939ea8aba39fa3aba2989083796d60594f443b2f261c11060000000000000000000000000000000000000000000714212d3a46535e697884919a9b9c9d96897c6f625a504a464440434044464b515c67717e8b98a3aeaa9b8f827568554b4135291d11040000000000000000030f1a26313c4854616e7b87929faaac9f92877c6f675d554e46454041414142474c515b606d7a85929eabaca095897d7063554b4034281c100400000000000000000714212d3a4754606d7a86929fa89b8f8275665c5044382c1f1206000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000000000000000000000004080a0a131313130d0c0a070200000000000000000000000713202d3a4653606d78839097a2999083766c6156606d7984919e9f958d80736b6155483c2f23160900000000000000000002070c0f11121313130e0706040000000000000000000000000000000000000000000007121d28313940454751535353534947433c342a20150a00000000000000030c141b212528292d2d2d2d2d2d2d2625231e19120a010000000000000911181d2124252d2d2d2d292826211b140c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005090d0f101313131313131212100c0802000000000000000000000106090b0c13131313131313100f0d0a0500000000000000000000000007111921272c2f30333335414e5b6874818e9b9e9184786b5e514538333332312e2e39434f59616d7a85929f9f92867b6e615b656c727b81868b8e9091929291908e8b87827c726d635c52473e30261c11060000000713202d3a4653606d798693a0aca194877b6e6164707d8a97a1ab9d9083776a605443392f23181c2b37424d5765727e8b98a3a2988b7e7164626f7c8895a2aca09386796d6053463a2d201307000000000000000000000000000000000000000b151e2a333c45515d676f7c86929fa5a79f999299a3aaa0958d80746b61564d42382d22170d04000000000000000000000000000000000000000005121e2a36424d576774818e9aa6a9a89b8e81756c605c5453514a504a5153555d606d7983919daaaea2988b7e7165584b3e2f24180d010000000000000000000a15212d3a46535e6975818e98a3aea3999083796d675f5853514b4e4e4e4d53555d606d74818e97a1ada69d9083776b605443392e23180c0000000000000000000b1724313e4a5764717d8a99a3a8988b7e7265544a3f34281c1003000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d10030000000000000000000000000000000000000000000000000000050b101416171f2020201a1917130e070000000000000000000006131f2c3845515c666e7b85929a9f948b7e71675e68737f8c96a1989083796d60594f44382c2014070000000000000000060d13181c1e1f2020201b1313100c0700000000000000000000000000000000000000010d18242f39434b51535e6060606055534e463c32261b0f040000000000020c151e262c3135363939393939393933322f2a231c130a000000000009121b22292e3132393939393635322d261e160c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070f161b202223262835414e5b6874818e9b9e9184786b5e5145382b2626251d27303d46525e68717e8b949f988f82756c615b606a6e757a7e81838585868584817f7b756f6a635b524940352c1e140a000000000713202d3a4653606d798693a0aca194877b6e616875828f9ca9a3998c7f7265584e4331271d121a26313c4754606d7a86929faa9c8f837669626f7c8895a2aca09386796d6053463a2d20130700000000000000000000000000000000000007121d27303c45505a606d79839198a2aa9f9590869299a4a79d928a7d70695e544a3f332820160c0100000000000000000000000000000000000000020e1a25313c4855626f7c88949faaaa9e938a7e726d6662605c545d545c6062676d75808d95a0aca99f92867a6d6154473a2e2114070000000000000000000005121e2a36424d57616e7b86929fa6aba0958f82796f6a63605c555b5a5b575f62676d747f8c939ea9a99f948a7d7064594f4430271d1207000000000000000005121e2b37424d576774818e9aaba096887b6e6155483b2e23170c00000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d1003000000000000000000000000000000000000000000000000000810171c2023242c2d2d2d2726231f19120a01000000000000000004101c2834404b545e69707d88939f9e91857a6d616e7b86929f9f92867b6e665c51473e33281c1004000000000000000710171e24282b2c2d2d2d28201f1c18120b03000000000000000000000000000000000004101d2935404b555d606b6c6c6c6c625f584e43372b21160a000000000009141e2730373d414246464646464646403e3b352e251c120700000006111b242d343a3d3e4646464643413e3830281e1108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040b0f1315161b2835414e5b6874818e9b9e9184786b5e5145382b1e1918151e2a36414c56606c778390999e938a7d70675d575f62686e717477787979787775726e69625f58514940372e231a0c02000000000713202d3a4653606d798693a0aca194877b6e616e7a86929fac9f92867a6d6154473d3221150b15202c3945525d6875818e9ba99f93877b6e626f7c8895a2aca09386796d6053463a2d2013070000000000000000000000000000000000060f18232e39434d57616c74818e95a0aaa29890837d87939fa7a49e92857b6e665b50443d32281e130800000000000000000000000000000000000000000915212e3b47535f6a76828f98a2aea59f92877f78726f6d666a696a666d6f7379818d929da7aca2978d8074685d5246392d20130700000000000000000000020e1a25313b46535f69737f8c949fa7a79f948f837c75706d676867676869696e737a818c919ca5aaa1978f82766c6155473d331e150b0000000000000000000714212d3a46535f697784919eaa9e918477695f53463a2d1c110600000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000000000006111a22282d30313939393933322f2a241c140a0000000000000000000c18232e39424d57616b73808d949f978d80746a74818e989d938a7e71695f544b40352c21160b0000000000000006101922292f343738393939352d2c28231d150c05000000000000000000000000000000000613202c3945515d676d78797979796f6a5f53473d32271b0f0100000004101b26303942494d4f535353535353534c4b4640372e23190d0200010c18222d363f454a4b53535353504e49423a30231a0f05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000307090e1b2835414e5b6874818e9b9e9184786b5e5145382b1e120b0c1925303a44505b656f7c87929f9e9184796d605853565e6165686a6b6c6c6b6a6865615e57534e463f372e251c110800000000000713202d3a4653606d798693a0aca194877b6e66727f8c99a3a99b8f8275685e5246392d201304111d2935414c5663707d8a97a1a49a8c8073656f7c8895a2aca09386796d6053463a2d20130700000000000000000000000000000000030c17212834404b555f69717e8a939da7a59f92867b73808d95a0aaa1978f82786c60594f443a2f241910060000000000000000000000000000000000000006121f2b37434e58626f7c86929fa4aca399928b837f7b797777767777797c80858e939da4aea49a92857a6d61564c4135291d1105000000000000000000000009141f2a36424d57606d78828f959fa7a69f959087817d79777574747476787b80858e939ca3aaa29892857b6e615a5044352b210c030000000000000000000815222e3b4855616e7b8896a0ab9a8d817467574d42362a1e0a0000000000000000000000000004111e2a3744515d6a7784909daaa99c8f8376695c504336291d100300000000000000000000000000000000000000000000030a1117242c33393c3d46464646403f3b352e261c120700000000000000050c121d27303b454f59606d788290979f92877c6f7c87939f958e81746c61574d42392e231a110c060000000000020d17222b333b404445464646413a38342e271e170e060000000000000000000000000000000714202d3a4753606d7a84868686877c6f62594f44382c1d12070000000915212c37424c545a5c606060606060605957514940352a1e12060005111d29343f48505658606060605c5a544c42352b21160b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020e1b2835414e5b6874818e9b9e9184786b5e5145382b1e120008131e27333f49535f6a73808d96a0968d80736a5f534c5254585b5d5e5f5f5e5d5b5854524d47433c342d251c130a0000000000000713202d3a4653606d798693a0aca194877b6e6a7784919daba1978a7d7064564c41362a1e11050d19242f3a4653606d7984919eac9e9184786c6f7c8895a2aca09386796d6053463a2d201307000000000000000000000000000000000b151e29333b45515c676e7b86929fa5a89e938b7e716d79839098a3a99f948c7f736b60564c41352922180d03000000000000000000000000000000000000030f1b26323c47535f6a717e8b939aa2aaa39f95918c8886848483838485898c92979ea5aaa39f93887d70685e52443a3024190d010000000000000000000000030e1a26313b44505c666d7a8390959da5a7a099938e898683828181818385888c92979da5a7a09892867d70695e52483e3323190f00000000000000000003101c28343f4a5465727e8b98a8a3998a7d7064574a3d31261a0e0200000000000000000000000004111e2a3744515d6a7784909d9f9f9c8f8376695c504336291d1003000000000000000000000000000000000000000000040c151c2328363e44494a525353534d4b4740382e24190e0200000000000810171d1e252a333e44505c666e7b85929a9990827982909a989183796d605a50453c302a251e1d1710090000000007131e29333d454c50525353534e4645403930292018100800000000000000000000000000000613202c3945515d67707d8a949a8f82766b605448392f24180c0000000d1925313d49545e65696c6c6c6c6c6c6c66635b51463b2f23160a000915212e3a45505a62656c6c6c6c69665e54473d33271c10040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000205070e1b2835414e5b6874818e9b9e9184786b5e5145382b1e1205020b17222d38414e58606d7984919e9f92877c6f655b5046474b4e5152525352514e4c4846423b37312a221c130a010000000000000713202d3a4653606d798693a0aca194877a6e6f7c8995a0ab9e9185796d6053463a3025190d0108131f2b3844505c6673808d9aa7a196897d706f7c8895a2aca09386796d6053463a2d20130700000000000000000000000000000007121c27303b45505a606d79839098a2aba0968e81756c666e7c86929fa6a69f92877c6f685d52453f342a1f150b010000000000000000000000000000000000000a15202b37434e58616c727f8892989fa3a7a09d99999291909090919298999ea2a9a69f98928b7f726c61564c4132281e13080000000000000000000000000009141f28343f4a545e686d7a838e929d9fa7a49f9b9892908e8e8d8e8f9197999ea1a9a29e9590867d706b60574d42362c22110800000000000000000006121f2c3844505c6675828f9ba89f92867a6d6054473a2d2114090000000000000000000000000004111e2a3744515d6a778490939393938f8376695c504336291d10030000000000000000000000000000000000000000060d161e262e343f485055575f6060605a57524a40352a1f13070000000008121a22282d3036393a3f4a545e69707d88939f948e828e949f92867c6f675d51483e3a3936302d28221b12090000000c18242f3b454f575d5f6060605b53514b423a322a221a11070000000000000000000000000004101d2935404b55616c75828f9c94897c6f63554b4035291d100400000f1b2835414d5a65707579797979797979736d63574b3e3225190c000b1724313d4a56626d7179797979767066594f44382c20150a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002090e1114141b2835414e5b6874818e9b9e9184786b5e5145382b1e12050006111b262f3c45515d67707d8a939e999083776c60564c413e41444546464544423f3b3a36302b262018100a01000000000000000713202d3a4653606d798693a0aca094877a6d74818d9aa8a79a8d8073665c504438291e13080003101c28343f4a54626e7b88959fa89b8e81746f7c8895a2aca09386796d6053463a2d2013070000000000000000000000000000050f18232e39424d57616c74808d95a0aaa39991847a6d605f6a727f8b949fa9a39991847a6d605a50463c31271d1207000000000000000000000000000000000000040f1a26313c46505a636d727e868e92999da0a8aba39f9e9d9c9d9e9fa2aaaaa29f9b948f867e726d62594f443a3020160c0200000000000000000000000000030b17232e38424c565e686d79818990959b9fa2aaa39f9d9b9a9a9b9c9ea1a9a49f9c97928c837b706b60594f453b30241a10000000000000000000000713202d3a4653606d7985929fa99c908376675d5145392c2013060000000000000000000000000004111e2a3744515d6a77838686868686868276695c504336291d100300000000000000000000000000000000000000070f18202830383f44515a61646c6c6c6c66635c52473b2f23170a00000005101a242c33393a4146474a4d5357606b73808c949e938e939e938b7f726a5f55534d4b4746413a39342c241b100600000f1c2834404c5761696b6c6c6c68605c544c443c342c2318120b030000000000000000000000010d18242f3943505a626f7c89949b8e8175675d5145392c1f130600000f1c2936424f5c697582868686868686867f7366594c403326190d000b1825323e4b5865717e8686868682766b6054483c32271b0f030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050d14191e2021272835414e5b6874818e9b9e9184786b5e5145382b1e120500000a141d2935404b55616b75818e989f958b7e72685e52463d3037383939383735322e2d2a251f1a150e060000000000000000000713202d3a4653606d798693a0aca093877a6d7985919eab9f95887b6e62544a3f3428170d0200000b17232e3847535f6a7783909dab9f9285796f7b8895a2aca09386796d6053463a2d20130700000000000000000000000000020c17212834404a545f69717e8a929da7a69f92877c6f675d58606c77828f97a1aba1968e81756d62584e43392f23180f050000000000000000000000000000000000000a15202a343e48515b636c717b81878c919597999c9d9e9e9f9f9f9e9d9b9998928e89827b716c625b51473e32281e0e0400000000000000000000000000000006111c26303a444c565e676d747c83898e9298999b9d9e9f9f9f9f9e9d9b999993908b857f786e6960594f473d33291f120800000000000000000000091623303c4956636f7c8998a2a9998c7f7366554b4135291d1104000000000000000000000000020d17222b36424f5b6771777979797979797670665a4e4235291c0f030000000000000000000000000000000000000810192129323a424a505b636c7079797979736e63574b3f3226190c0000000c17222c363e45494c525457575f6165656d78828f9c9e9b9e9b8f82756d6865615e575754524c49453e362c22170c0000111e2b3744505d697378797979746d665e564e463e3528231c150c04000000000000000000000007121d28313e4754606a7683909c9285796d6053473a2d20140700000f1c2936424f5c6975828f93939393938c7f7366594c403326190d000613202d394653606c7883909994897d7063584e43372b1f130600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050e171f252a2d2e342d35414e5b6874818e9b9e9184786b5e5145382b1e12050000020b18242f39434f59616e7b85929f9f92857a6e61594f43392e232c2c2b2a282521201e1a140f0a03000000000000000000000713202d3a4653606d798693a0aca093867a6f7c8997a1aa9d9083766a5f5342382e23170500000006111c2b37434e5865727f8b99a3a2988a7e717b8895a1aca09386796d6053463a2d201307000000000000000000000000000a141e29333b44515c666e7b85929fa4a99f948c7f726a6055505b656e7a85929ea5a89e938b7e716a5f554b40342921170c020000000000000000000000000000000000030e18222d363f49515a61696e747b8084888b8d8f90919292929291908e8c8985817c766e69615a51493f352c20160c00000000000000000000000000000000000a141e28323a444c555c606b6f777d8185898c8e90919292929291908f8d8a86837e79726d665f574f473d352b20170d0000000000000000000004111d2935414c566673808c99aaa197897c6f6256493c2f24180d0100000000000000000000000007131e29333d454c555f676a6c6c6c6c6c6c69665e54493e3226190d01000000000000000000000000000000000007121a222b333b444c545c606d727e868686868073665a4d4033271a0d000005111d28333e485055565e616467696e7175787c808d99a6a8a6998c807c7875716e696764615e565550483e34281d110500121f2c3845525f6b788586868681786d685f584f473f342e271e160e0600000000000000000000010c161f2b37434e5864717e8a99988a7e7164574a3e3124170700000f1c2936424f5c6975828f9c9f9f9f998c7f7366594c403326190d0005121f2b3744505b656f7c87939d9083776a6054473b2e221509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020d17202930363a3b413a38414e5b6874818e9b9e9184786b5e5145382b1e120500000007121d27313e46525e68727f8b959f978e81756b60554b4034281f201f1e1b191514120e09030000000000000000000000000713202d3a4653606d798693a0aca093867974808d9aa9a3988b7e7265584e4330261c1106000000000f1a26313c4754616d7a86929faa9b8f82757b8894a1aca09386796d6053463a2d20130700000000000000000000000006111c26303b454f59606d78839097a2ada1978f82786c60584e49535e68707e8a939da8a59f92867c6f675c51453e33291e140a00000000000000000000000000000000000006101b242e373f4850575e61696e73777b7e80828484858686858583827f7d79756f6b625f5750483f372d231a0e040000000000000000000000000000000000020c162029323a434b515960636b7075797c7f82838485868685858382807d7a76726d67605c544d453d352b23190e05000000000000000000000713202c3945525d687683909da99e9285796c605346392d201307000000000000000000000000000c18242f3b454f575d5f60606060606060605c5a544c42382d21160a00000000000000000000000000000000030b1218242c343d454d565d666d747f87929892857b6e6154473b2e21140800000814212d3945505a6164686d7174777b7e8185888d929ca8b3a89c928c8885817e7b7774716d6864615a5045392d211508000c1926323f4c5965727f8c93938e827a6f6a615951444039302820180f0700000000000000000000040d1b27323d4754606d7a86929a8d8174675a4e412f24180d01000f1c2936424f5c6975828f9ca8aca6998c7f7366594c403326190d00030f1b27333f49535f6a75828f9b95887c6f6255493c31261a0e02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009141f29323b4246474d4745404e5b6874818e9b9e9184786b5e5145382b1e1205000000010b151f2a36414d56606c788390999e93897d70675c51453c31261a0e110f0c0807050200000000000000000000000000000713202d3a4653606d798693a0afa39986797884919eab9f92867a6d6054473c3121150a00000000000a15202d3946525d6875828f9ba99f92867a7b8894a1aca09386796d6053463a2d2013070000000000000000000000050e17232e38424d57616b73808d959fa9a49e92857b6e665b5046414d56616c74818e96a0aba2989083796d605a50453b30261c110600000000000000000000000000000000000009121c25333d45454d52575f62666a6e71737577787879797978777573706d67636059534d453e362d251b110800000000000000000000000000000000000000050e1720333d454c504f54596063676d70727576787879797878777573706d6865605d55504a423c332b2319110700000000000000000000000714212d3a4754606d7a86929fa89b8e8175665b5044382b1f1206000000000000000000000000000f1c2834404c5761696b6c6c6c68605c544c504e49423a31261c1005000000000000000000000000000000050c151d2328363e464f575f686d78818c939993877d70695e52463a2d20140700000a1723303d4955616c71777a7e8184888b8e9297999e9ea1a9a39f9e9997918e8b8784817e7a77716c6155493d3024170a000b1825313e4a56626d75818f969490847c706b625b514a423a322a2119110600000000000000000915202b353f4745515d677683909c9083766a554b4035291d1004000f1c2936424f5c6975828f9ca8b2a6998c7f7366594c403326190d00000b17222d38414e58636f7c89959a8d807367574d42372b1e120600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020e1925303b444d52545a53514b4e5b6874818e9b9e9184786b5e5145382b1e120500000000030d1925303b44505b666f7c87929f9e9184796d60574d42372b20160c02000000000000000000000000000000000000000713202d3a4653606d798693a0ac9f9286797c8996a1a89b8e8175685d5245392c201303000000000005111d2935414c5663707d8a97a1a2988a7d7b8794a1aca09386796d6053463a2d20130700000000000000000000020b172028343f4a545e69707d8a929da7a79d928a7d70695e544a3f3b44505a606d79849199a3aaa0958d80746c61574d42382e23170e0400000000000000000000000000000000000c18242f3a454f575c5f606059575f626466696a6b6b6c6c6c6b6a686663605d55544f47423c332d241b130900000000000000000000000000000000000000000c18242f3a454f575c5f606059555c606366686a6b6c6c6c6c6b6a686664615e5653514b443f38302a211911080000000000000000000000000a1724313d4a5764707d8a99a3a7988b7e7165544a3f33281c0f0300000000000000000000000000111e2b3744505d697378797979746d665e564e463e3528231c150c040000000000000000000000000000060e161e272e344048505960696e7a828e939f948c7f736b60574d42362a1e110500000b1724313e4a5764717e83878a8e9196989b9e9c97919197a1989292979c9e9b9896918e8a87837e7164574b3e3124180b000916222e3a46515b606d7a8491989691867d726d605c544c443c332b2317110a020000000000010e1a26313d4751595e556673808d99928578675d5145392c201306000f1c2936424f5c6975828f9ca8aa9f998c7f7366594c403326190d000006111b262f3c4854606b7783909d918478695f53473a2d2114080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005111e2a36424d565e6167605c554e5b6874818e9b9e9184786b5e5145382b1e1205000000000008141f28333f4a545f6a73808d96a0968c8073695f53473e32281e1308000000000000000000000000000000000000000713202d3a4653606d798693a0ac9f928579808d9aa8a196897d7063564c4135291d11040000000000010d1924303a4653606d7985929eaa9b8e817a8794a0b5a09386796d6053463a2d201307000000000000000000000a141d29323b44505c666e7b85929ea4aaa0958d80746c61574d4238323e45515d676f7c87929fa7a79d928a7e70695e544a3f342820160c02000000000000000000000000000000030f1c2834404c5761686b6c6c66635b55585a5c5d5e5f565e61666a6c6c6a66605d564e463c322a211b12090100000000000000000000000000000000000000030f1c2834404c5761686b6c6c66635b5356595b5d5e5f565e61666a6c6c6a66605d564e463c342e261e180f0800000000000000000000000005121e2b37424d576774818d9aaba095877b6e6154483b2d22170b0000000000000000000000000000121f2c3845525f6b788586868681786d685f584f473f342e271e160e06000000000000000000000000070f18202830394045525a616b6f7b838f949d968f82776c60594f453b30251a0e0200000a1724313d4a5764707d8a939a9a9ea09e9a938f8a8585919e9286858a8f93999ea09e9a9a938a7d7164574a3e3124170b0006121e29353f45525d686f7c86929f9892877f746d665d564d453d3528231c140c030000000004111d2a36424e59636a6c6c727f8b9897867a6d6053473a2d201407000f1c2935424f5c6875828f9b9f9d93938c7f7366594c403326190d000007111b252c38444f596673808c9996887b6e6155483b2e221508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000714202d3a46525e696e746d675f585b6874818e9b9e9184786b5e5145382b1e12050000000000020b17222d38424e58606d7984919e9f92867b6e625a50443a3024190c030000000000000000000000000000000000000713202d3a4653606d798693a0ab9f92857884919eac9e9184786c6053463a2f24190d0100000000000008131f2c3844505c6673808d9aa79e9285798699a3afa09386796d6053463a2d20130700000000000000000006111c262f3b444f59606d78829097a1ada3989083796d605a50453b2f2935404b55606a73808c959faaa49f92857b6e665c50443d32281e130800000000000000000000000000000005111e2b3744505c6873787979736d63574b4d4f50555d60686d7276787977736d685f584e443b3025190e02000000000000000000000000000000000000000005111e2b3744505c6873787979736d6357494c4f50555d60686d7276787977736d685f584e443b3025190c06000000000000000000000000000714212d3a46535f697784919eaa9d918477695e52463a2d1c110600000000000000000000000000000c1926323f4c5965727f8c93938e827a6f6a615951444039302820180f0700000000000000000000071019212a323a434b515b636c717d8591959f9991847a6d655b50473d33291f14090000000713202d3a4653606d7985929f9f9c97928d87827d7883909c9285787d82878c91969b9f9f9285796d6053473a2d20140700010d18232935414c565f6a727e8b939e99938c81786d685f574f473f342e261e150c0300000006121f2c3845525e6a757979797e8a9794877b6e6154483b2e211508000e1b2835414e5b6874818e9b95898686867f7366594c403326190d00010d18232d373f464956636f7c8999978a7d7164574a3e3124170b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000814212e3b4754616e7b80796f6a605b6874818e9b9e9184786b5e5145382b1e120500000000000006111c262f3c45515d67707d8a939e988f82766c61564c4135291e150a0000000000000000000000000000000000000713202d3a4653606d798693a0ab9e92857b8896a1a49a8c8073655b504437281e13080000000000000003101c28343f4a54626f7c8895a0a197897c86929faca09386796d6053463a2d2013070000000000000000050e17222d38424c56606b73808d949fa9a69f92867c6f675d51473e3329242f3a434e58606d78839098a2ada2979082786d60594f443a3025191006000000000000000000000000000005121f2c3845525f6b788586867f7366574d4e535a61676d727a7f83858584807a6f6a5f564d42362a1f1408000000000000000000000000000000000000000005121f2c3845525f6b788586867f7366574d4e535a61676d727a7f83858584807a6f6a5f564d42362a1f1408000000000000000000000000000815222e3b4855616e7b8896a0aa9a8d807467574d42362a1e0a0000000000000000000000000000000b1825313e4a56626d75818f969490847c706b625b514a423a322a211911060000000000000000040f19222b333c444c555c606d737e869297a09f92877c6f685d53493f352b20170d0200000006131f2c3845515c6775818e9a948f8a85807b76717783909d92857971767b80848a8f92998e8175675d5145382c1f13060000070d19242f3a434e58626d75818e95a09f928e827a6e69605951443f3830271e150b0000000613202c3946535f6c798786868a909a95887b6e6255483b2f221508000e1b2734414e5a6774818d9a9083797979736d63574b3e3225190c0006121e29353f49515759606d798692998c7f7366594c403326190d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b87837c726c656874818e9b9e9184786b5e5145382b1e1205000000000000000a141d2935404b55616c75828f989f948a7e71685d52453d30261c110600000000000000000000000000000000000713202d3a4653606d798693a0ab9e91847f8c99a89f93877b6e6153493f3327160c0100000000000000000c17232e3847535f6a7783909da9998c7f85929faba09386796d6053463a2d20130700000000000000020b162028333f4a545e68707d88939fa6a99e938b7f726a5f554b40352c201d28313d44505c666e7b86929fa6a99f948c80736b60564c41352922180d030000000000000000000000000004101d2a3743505d6a7683908f8276695e54585f626c71797f858c909292908c857c6f695e52463b3025190e020000000000000000000000000000000000000004101d2a3743505d6a7683908f8276695e54585f626c71797f858c909292908c857c6f695e52463b3025190e02000000000000000000000003101c28343f4a5465727e8b98a8a398897d7063564a3d30251a0e0000000000000000000000000000000916222e3a46515b606d7a8491989691867d726d605c544c443c332b2317110a020000000000000a16212b343d454d565e676d757f8a9298a19e938b7f726a60564c41382d23190e050000000004101c2834404b5564707d8a8d88837e79736e696a7784919d9886796d696e73787d82868c8a7d7064554b4035291d100400000008131e28313c46515b606d79839198a29d948f847b706b625b504a423930271d120700000613202c3946535f6c79869293979aa295887c6f6255493c2f221609000d1a2733404d5a6673808d99918578666c66635b51463b2f23160a000916222e3a46515b62656c667885919a8d8174675a4e4134271b0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8790867f776e6974818e9b9e9184786b5e5145382b1e120500000000000000020b18242f3a43505a616e7b86929f9e92857a6d60594f42382e23170c03000000000000000000000000000000000713202d3a4653606d798693a0aa9e918482909caa9c8f8276695f5341382d22170400000000000000000006111c2b37434e5865727f8b99a39d908384919eaba09386796d6053463a2d201307000000000000000a141d28323a44505b666e7a85929aa4aba1968f82756d62584e43392f231a161f28343f4a545f69717e8b939ea9a69f93877d70685e52463f342a1f150b01000000000000000000000000020f1b2835424e5b6875818e92877b6e6663646a6f767e848c92989d9f9f9d9791857b6e61564d41362a1e110500000000000000000000000000000000000000020f1b2835424e5b6875818e92877b6e6663646a6f767e848c92989d9f9f9d9791857b6e61564d41362a1e1105000000000000000000000006121f2c3844505c6675828f9ba89f9286796d6053473a2d20140900000000000000000000000000000006121e29353f45525d686f7c86929f9892877f746d665d564d453d3528231c140c0300000000030f1b27323d464e575f686d79818c929fa3a0958e81756d62584e443a2f261b11080000000000000c18232e3a4653606d7984807b76716d66615f6b7884919e93877a6d6061666c70757a7f83796d6053463a2f24180c00000000010c161f2a343f45515d676e7c86929fa59f9691857d726d605c544b42392e23180c00000613202c3946535f6c7986929fa4a6a295887c6f6255493c2f221609000b1825323e4b5865717e8b989286796d605957514940352a1e1206000b1825313e4a57626d7279797983909b8e8275685b4f4235281c0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b8798928c827b7174818e9b9e9184786b5e5145382b1e1205000000000000000007131d28313e46525e69727f8c95a0978e81746b60544a3f34281f1409000000000000000000000000000000000713202d3a4653606d798693a0ab9e918587929fa2988b7e7164574d422f261b1106000000000000000000000f1b26313c4754616d7a86929f9f928785929eaba09386796d6053463a2d20130700000000000006111b262f3a444f59606c78828f97a1aca49991847a6d615b51463c31271d110d17232e38424d57626d75828f97a1ada49991847a6d615b51463c31271d1207000000000000000000000000000c1926333f4c5966727f8c998f8279727071757c838a91969fa2aaa3a3a9a1978e8174685e5246392d20140600000000000000000000000000000000000000000c1926333f4c5966727f8c998f8279727071757c838a91969fa2aaa3a3a9a1978e8174685e5246392d20140600000000000000000000000713202d3a4653606d7985929fa99c8f8276675d5145382c1f1306000000000000000000000000000000010d18232935414c565f6a727e8b939e99938c81786d685f574f473f342e261e150c0300000007131f2c38434e5860696e7a828e939ca4a2989183796d605b51463d32281d140a0000000000000007131f2c3845515c676d78746e6a64605c545f6b7885929e94877b6e61545b6063686e72776d675c5145382c1d12070000000000040d18222935404b555f6a717e8a939da7a09792877f746d665c544b4034281c1004000613202c3946535f6c7986929facafa295887c6f6255493c2f221609000916232f3c4956626f7c899a99897c6f6356494640372e23190d02000c1926323f4c5965727f86868689959c8f8275695c4f4236291c0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000815212e3b4854616e7b879298948f857e74818e9b9e9184786b5e5145382b1e12050000000000000000010c161f2a36424d57606d788390999f93887c6f665c50443b31251a0d040000000000000000000000000000000713202d3a4653606d798693a0ada197919299a39f9285796d6053473b3120140a00000000000000000000000a15202d3946525e6875828f9ba399929297a1ada09386796d6053463a2d2013070000000000040e17222d38414c56606b737f8c949fa9a79f93877d70685e52493f342a1f150b06111c26303c45505a616d7a85919ea4aba1968f82756d62584e43392f24180f060000000000000000000000000a1623303d495663707c8998948f837e7d7e828790949ea1a19e9996979a9f9f92877b6e6154473b2d22170b00000000000000000000000000000000000000000a1623303d495663707c8998948f837e7d7e828790949ea1a19e9996979a9f9f92877b6e6154473b2d22170b0000000000000000000000091623303c4956636f7c8997a2a9988c7f7265554b4035291d100400000000000000000000000000000000070d19242f3a434e58626d75818e95a09f928e827a6e69605951443f3830271e150b0000000915222e3b4854606a6f7b8490949ea5a49f92867c6e675d51493f342b20160b020000000000000004101c2834404b555c666c66625f575351505b657985929f95887b6e62555053565e61666a605c554b4034281c0b01000000000000071018242f39434e58616c74818e95a0a9a299928b80786d665c5145382c1f1306000613202c3946535f6c7986929facafa295887c6f6255493c2f221609000714202d3a4753606d7a8693998c807366594f44382c251c120700000c1926323f4c5965727f8c93939da09c8f8276695c504336291d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613202d394653606c787f86909597928a81818e9b9e9184786b5e5145382b1e1205000000000000000000040d1a25303b44505c666f7c87939f9a9083786d60574d42362a1f160c0100000000000000000000000000000713202d3a4653606d798693a0b3a9a19e9fa3a89a8e8174675d5145392c1f1302000000000000000000000005111d2a36414c5664707d8a97a1a39f9ea1a9b3a09386796d6053463a2d20130700000000020c162027333f49535e686f7d87929fa6aa9f958d80736b60564c41372d22180d03000a151e2a333f46525e68707d8a929da8a89e938b7f726a5f554b40352921170d0300000000000000000000000713202d3a4653606d7985929f95908b898b8f93999fa39f97918c8a8a8e9299998c7f7265544a3f33281c0f03000000000000000000000000000000000000000713202d3a4653606d7985929f95908b898b8f93999fa39f97918c8a8a8e9299998c7f7265544a3f33281c0f0300000000000000000004111d2935414c566673808c99a9a197887c6f6255483c2f24180c00000000000000000000000000000000000008131e28313c46515b606d79839198a29d948f847b706b625b504a423930271d120700000916232f3c4956626f7c85919693939393928a7e716a5f554b40372d22190e040000000000000000000c18232e39434b545b605b54534e464653606c7986939f95897c6f625649464c5254595d53514b43392e23180c000000000000000007121d28313c46505a606d7983909893939393928d82796d6053463a2d201307000613202c3946535f6c7986929facaca295887c6f6255493c2f221609000613202c3945515d677783909d9083776b6054483d30261c110600000c1926323f4c5965727f8c989faaa99c8f8376695c504336291d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006121f2b3844505b666c727c838c9299938e8e939e9e9184786b5e5145382b1e12050000000000000000000009141f28343f4a54606a74808d97a0958c7f72695e53463e31281d130700000000000000000000000000000713202d3a4653606d798693a0acb3adabacaca095897c6f62554b4035291d10040000000000000000000000010d1925303a4653606d7985929eabacabadb3aca09386796d6053463a2d2013070000000008131e28323a44505b656d7a849199a3aea2989083786d60594f443a30251b10060000030c18212a36414c56616b74808d95a0aba69f92867c6f675d51453e33291f1409000000000000000000000006131f2c3845515c6774818d98a09d9896979b9fa49f99928d85807d7d818792998f8276665b5044382b1f12060000000000000000000000000000000000000006131f2c3845515c6774818d98a09d9896979b9fa49f99928d85807d7d818792998f8276665b5044382b1f12060000000000000000000613202c3945525d687683909da99e9185786c605346392d201307000000000000000000000000000000000000010c161f2a343f45515d676e7c86929fa59f9691857d726d605c544b42392e23180c00000d1a2633404d59667380868686868686868680746c61574e43392f251b10070000000000000000000007121d273039424a5053504a47423c4753606d7a869aa496897c706356493d4146474c504645403930271d12070000000000000000010c161f2a343e45515c676e7b8586868686868686867a6e6154473b2e211408000613202c3946535f6c7986929f9f9f9f95887c6f6255493c2f2216090004101d2935404b556673808c9995897d7063584e42382e23170b00000c1926323f4c5965727f8c98a5b2a99c8f8376695c504336291d1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030f1c28333f4a545b606a6e787f8690959b9b9ea59e9184786b5e5145382b1e120500000000000000000000030b17232e38424e58606d7a84919e9f92867b6e615a50433a2f24180d01000000000000000000000000000713202d3a4653606d798693a0acacacacb5ab9d9184776a605443392f24180c0000000000000000000000000008131f2c3844515c6674808d9aa7b1acacacaca09386796d6053463a2d201307000000010d1924303a444e58606c77828f96a1aba59f92857b6e665c50473d32281e130900000000060f1925303a444f59606d79839199a3aea3989183796d605a50453b31261a0e020000000000000000000004101c2834404b55616e7b86929fa4a5a3a4a7a09d948f868079737070747d87939285796c605346392d2013060000000000000000000000000000000000000004101c2834404b55616e7b86929fa4a5a3a4a7a09d948f868079737070747d87939285796c605346392d2013060000000000000000000714212d3a4754606d7a86929fac9b8e8174655b5044372b1f120500000000000000000000000000000000000000040d18222935404b555f6a717e8a939da7a09792877f746d665c544b4034281c1004000c1925323f4b57636d737979797979797979746e645a50453c31281d12090000000000000000000000000b151e272f383f4446443f38373a4754616d7a8794a0978a7d7064574a3d36393b3f443a38342e271e150b00000000000000000000040d18222934404b555f696e78797979797979797976685e5246392d201407000613202c3946535f6c7986929393939393887c6f6255493c2f22160900010d18242f3b4855616e7b88949c8f82756a60544a3f34281c1003000c1926323f4c5965727f8c98a5aca99c8f8376695c504336291d1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b17222d38424a50585f666d727c838c9299a0a79e9184786b5e5145382b1e1205000000000000000000000006111c26303d45515d67717e8a949e988f82756c61554b4035291d1104000000000000000000000000000713202d3a4653606d7986939f9f9f9f9f9fa3998c7f7266584e4331271d12070000000000000000000000000004101c2834404a54626f7c8895a09f9f9f9f9f9f9386796d6053463a2d20130700000004111d2935414c56606a727f8c949ea8a89e938a7e71695f544a3f352b20160c00000000000008131e29323e45515d676f7c87929fa69fa0958e81746c61574d42362a1e120500000000000000000000000c18232e3946525e69727f8b929b9e9f9e9b959089827b736d6763646b74818e98887b6e6255483b2f22150800000000000000000000000000000000000000000c18232e3946525e69727f8b929b9e9f9e9b959089827b736d6763646b74818e98887b6e6255483b2f2215080000000000000000000a1724313d4a5764707d8a99a3a49a8a7e716453493f33271b0f030000000000000000000000000000000000000000071018242f39434e58616c74818e95a0a9a299928b80786d665c5145382c1f1306000a16232f3b47525b63666c6c6c6c6c6c6c6c67645c52483e332a1f160c00000000000000000000000000030c151d262d33383938332d2e3b4854616e7b87949f978a7e7164574b3e312d2e33372d2c28231d150c030000000000000000000000060f18232f39434d575f616c6c6c6c6c6c6c6c6c6c5e564c41362a1e1105000613202c3946535f6c7987868686868686867c6f6255493c2f22160900000714212d3a47535f6975828f9c93877c6f665c5044382b1f1206000c1926323f4c5965727f8c989f9f9f9c8f8376695c504336291d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006111c262f383f444e545c606a6f788087909593939184786b5e5145382b1e12050000000000000000000000000a141e2935414c55616c75828f9893948a7d70675d5145392c201306000000000000000000000000000713202d3a4653606d7986939393939393939392867b6e6154473d3221150b0100000000000000000000000000000c18232e394754606a778390939393939393939386796d6053463a2d2013070000000713202c3945525d686f7c879293939393968e81746c61574d42382e23190e04000000000000020c17202935404b55606a727f8c9493939393938a7e71695f53463a2d211407000000000000000000000007121d2a36424d56626d7380898f9292918f8a837d766e69605d5559626f7c89988a7d7063574a3d3024170a000000000000000000000000000000000000000007121d2a36424d56626d7380898f9292918f8a837d766e69605d5559626f7c89988a7d7063574a3d3024170a0000000000000000000e1b2734414e5a6774818d93939393877a6d6154473a2d22170b0000000000000000000000000000000000000000000007121d28313c46505a606d7983909893939393928d82796d6053463a2d2013070007131e2a35404952575960606060606060605a58524a40362c21180d040000000000000000000000000000030b141c22282b2d2b28222f3b4855626e7b889393938b7e7265584b3f322521262a201f1c18120b030000000000000000000000000007121d27313c454d53555f60606060606060605f524c443b3025190e020006121f2c3845525e6a757979797979797979766a6054473b2e221508000006121e2b37424d57626f7c89939a9083786d6053463a2d201307000c1926323f4c5965727f8c93939393938f8376695c504336291d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a141d262d333c424a50585f666d737c838686868684786b5e5145382b1e1205000000000000000000000000020c19242f3a43505a616e7b8686868686847a6d6053473a2d201407000000000000000000000000000713202d3a4653606d78868686868686868686868275685e5246392d20140300000000000000000000000000000007121c2b37434e5865727f86868686868686868686786d6053463a2d2013070000000714212d3a4754606d7a848686868686868684796d605a50453b30261c11070000000000000000050e18242f39434e58606c788286868686868686857b6e6155483b2e2215080000000000000000000000000e1925303b44515b636e737d82858684827d78706b625f57514b53606d788686867f7265584c3f3225190c0000000000000000000000000000000000000000000e1925303b44515b636e737d82858684827d78706b625f57514b53606d788686867f7265584c3f3225190c000000000000000000111e2b3844515e6b778486868686868377685e5246392d1b110600000000000000000000000000000000000000000000010c161f2a343e45515c676e7b8586868686868686867a6e6154473b2e21140800020d19242e3740474b4d53535353535353534d4c4740382f241a0f0600000000000000000000000000000000020a11171c1f201f1c222f3c4955626f7c86868686867f7265594c3f322619191d1313100c07000000000000000000000000000000010b151f2a333c4246485253535353535353535346413b32291e1408000004111d2a36424e59636a6c6c6c6c6c6c6c6c6260584e43372b1f13060000020e1a26313c4754606a7581868686867f7265584c3f3225190c000c1926323f4c5965727f868686868686868276695c504336291d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020b141c222830383f444e545c606a6f77797979797872685c5043372a1d11040000000000000000000000000008131e28313e46535f696e7979797979786d675d5145392c2013060000000000000000000000000006121f2c3844505c667679797979797979797979757065564d41362a1e1105000000000000000000000000000000000f1b27323c4a57626d727979797979797979797976665c5044382c1f12060000000713202c3945525d686d7879797979797979776d675d51483e33291e150a0000000000000000000007121d27313c44505b666c7679797979797979786e695f53463a2d21140700000000000000000000000009141f29323f49525c636b707578797875706c656059534d4544505c6674797979726d62564a3e3124180b00000000000000000000000000000000000000000009141f29323f49525c636b707578797875706c656059534d4544505c6674797979726d62564a3e3124180b000000000000000000111d2a37434f5c6772777979797979777167564c41362a1e0a000000000000000000000000000000000000000000000000040d18222934404b555f696e78797979797979797976685e5246392d201407000007121c252e353b3f404646464646464646413f3c362f261d120800000000000000000000000000000000000000060b0f12131215222e3b4754606a767979797979726d63574a3e3125180c11070604000000000000000000000000000000000000030d18212a31373a3b4546464646464646463b3936302920170d020000010e1a26313d4751595e5f6060606060606055544e463c32271b0f0300000009151f2b38434e58656f7579797979726d62564a3e3125180b000b1825313e4a57626d72797979797979797670665a4e4235291c0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171e262e343c424a51585f626a6c6c6c6c6b6860564b3f33271b0f0200000000000000000000000000010c161f2a36424d575f616c6c6c6c6c6b605d554b4035291d11040000000000000000000000000003101c28343f4a545c6c6c6c6c6c6c6c6c6c6c6c69655e54443b3025190e02000000000000000000000000000000000a15202e3a46515b62656c6c6c6c6c6c6c6c6c6c6c5c544a3f34281c100300000004111d2935414c565d606b6c6c6c6c6c6c6c6b605d554b40362c21170c0300000000000000000000010b151f28333f4a545b60696c6c6c6c6c6c6c6c615f574d42362a1e1205000000000000000000000000020d17202d37404952596063686b6c6b6864605b534f47423c3f4a545c6a6c6c6c65625b51463a2e221509000000000000000000000000000000000000000000020d17202d37404952596063686b6c6b6864605b534f47423c3f4a545c6a6c6c6c65625b51463a2e2215090000000000000000000f1b27333f4b5660676b6c6c6c6c6c6a675f55443a3025190d00000000000000000000000000000000000000000000000000060f18232f39434d575f616c6c6c6c6c6c6c6c6c6c5e564c41362a1e11050000000a131c242a2f323339393939393939393433302b241d140b0000000000000000000000000000000000000000000003060606131f2b37434e5860626c6c6c6c6c65635b51463a2e2216090400000000000000000000000000000000000000000000060f181f262b2d2e3939393939393939392e2d2a251e170e05000000000915202b353f474e5253535353535353534947433c342b20150a00000000030f1b27323d46535d65686c6c6c6c65625b51463a2e221609000916222e3a46515b62656c6c6c6c6c6c6c69665e54493e3226190d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c141c2328303940444e54555d606060605e5c564e443a2f23170b000000000000000000000000000000040d1a26313b454d53555f606060605e53514b433a2f24180d0100000000000000000000000000000c17232e38424a505f606060606060606060605c5a544c4232291f1408000000000000000000000000000000000004121e29353f49515759606060606060606060605f504a42382e23170c00000000010d1924303a444c52545e606060606060605e53514b433a2f241a0f06000000000000000000000000030d17222d38424a50535d606060606060605f55534d453b31261a0e0200000000000000000000000000050e1b252e3740474f54565c5f5f5e5c57535049413d373138424a50535f6060585651493f34291e120600000000000000000000000000000000000000000000050e1b252e3740474f54565c5f5f5e5c57535049413d373138424a50535f6060585651493f34291e12060000000000000000000b17232e3a444e565c5e60606060605d5b554d4332291e1308000000000000000000000000000000000000000000000000000007121d27313c454d53555f60606060606060605f524c443b3025190e02000000010a12191e2325262d2d2d2d2d2d2d2d2726241f19130b0200000000000000000000000000000000000000000000000000030f1b27323c464e54556060606060595751493f352a1e1206000000000000000000000000000000000000000000000000060e141a1e21222c2d2d2d2d2d2d2d2d21201e19140d050000000000040f19242d353d424546464646464646463c3b37322b22190f0400000000000a16202b34414b53595b60606060585651493f34291e12060006121e29353f49515759606060606060605c5a544c42382d21160a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a11171e272e343c434749515353535351504b443c32281d12070000000000000000000000000000000009141f29333b4246485253535353514745403a31281d130700000000000000000000000000000006111c2630383f4453535353535353535353534f4d4942393020170d020000000000000000000000000000000000010d18232d373f464a4c5353535353535353535353443f3830261c1106000000000008131e28323a4145475153535353535353514745403a31281d1208000000000000000000000000000006111c262f383f44465053535353535353524846423b33291f140900000000000000000000000000000009131c252e353d4448494f5253514f4a46443f382f2b2630383f44465353534c4a463f372d23180d01000000000000000000000000000000000000000000000009131c252e353d4448494f5253514f4a46443f382f2b2630383f44465353534c4a463f372d23180d0100000000000000000006121d28323c444b4f515353535353504f4a433b3120170d020000000000000000000000000000000000000000000000000000010b151f2a333c4246485253535353535353535346413b32291e1408000000000000070d1316191a20202020202020201a1a17130e08010000000000000000000000000000000000000000000000000000000a15202b343c43474953535353534c4a463f372d23180d010000000000000000000000000000000000000000000000000003090e1214151f20202020202020201414110e08020000000000000008121b242b31363839393939393939392f2e2b2720191007000000000000040f19222f3941484d4e535353534c4a463f372d23180d0100010d18232d373f464a4c53535353535353504e49423a31261c1005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c151c232832373b3c444646464645433f3a322a20160c0100000000000000000000000000000000030d17212931363a3b4646464646453a39352f281f160c01000000000000000000000000000000000a151e262e3438464646464646464646464642413d3730271e0e050000000000000000000000000000000000000007111b252d353a3e3f464646464646464646464638342e261e150a000000000000020c1620283035393a4546464646464646443a39352f281f160c000000000000000000000000000000000a141d262d3338394346464646464646453b3a36312921170d03000000000000000000000000000000010a131c232b33383c3d42454645423d3937332d261d1e262e34383a4646463f3e3a342d251b1106000000000000000000000000000000000000000000000000010a131c232b33383c3d42454645423d3937332d261d1e262e34383a4646463f3e3a342d251b110600000000000000000000010c16202a323a3f4344464646464644423e3931291f0e0500000000000000000000000000000000000000000000000000000000030d18212a31373a3b4546464646464646463b3936302920170d020000000000000002070a0c0d13131313131313130e0d0b07030000000000000000000000000000000000000000000000000000000000040e19222b32373b3c46464646463f3e3a352d251c11070000000000000000000000000000000000000000000000000000000002050708121313131313131313080705020000000000000000000009121920262a2c2c2d2d2d2d2d2d2d22221f1b150f07000000000000000007101d272f373d4042464646463f3e3a342d251b110700000007111b252d353a3e3f4646464646464643423e3831281f150a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b121820262b2e2f37393939393837332f2820180f05000000000000000000000000000000000000060f171f262a2d2e3939393939382d2c29241d160d040000000000000000000000000000000000030c151c23282c39393939393939393939393635312c261e150c0000000000000000000000000000000000000000000a131b23292e313239393939393939393939392c28231c150c0300000000000000040e161e24292c2d3839393939393939382d2c29241d160d0400000000000000000000000000000000020b141c22282b2d3639393939393939392e2d2a261f170f060000000000000000000000000000000000010a111921272c2f303538393835312d2b27221b14151c23282c2d39393932312e29231b13090000000000000000000000000000000000000000000000000000010a111921272c2f303538393835312d2b27221b14151c23282c2d39393932312e29231b1309000000000000000000000000040e1820282e33373839393939393736332e271f170d000000000000000000000000000000000000000000000000000000000000060f181f262b2d2e3939393939393939392e2d2a251e170e05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007101920272b2e2f393939393932312e2a231c130a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f151a1d1f20202020202020201615130f0a04000000000000000000000b151d252c3134353939393932312e29231b130900000000000a131b23292e3132393939393939393635322d261f160d0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070c151b1f22222a2d2d2d2d2b2a27231d160f060000000000000000000000000000000000000000060d141a1e21222c2d2d2d2d2b20201d18130c0400000000000000000000000000000000000000030a11171c1f2d2d2d2d2d2d2d2d2d2d2d292825211b140c03000000000000000000000000000000000000000000010a11181e2225262d2d2d2d2d2d2d2d2d2d2d1f1c17110a03000000000000000000040c13191d20212b2d2d2d2d2d2d2d2b20201d18130c04000000000000000000000000000000000000020a11171c1f202a2d2d2d2d2d2d2d2c22211e1a140d060000000000000000000000000000000000000000070f161c202223292c2c2b2924201f1b17110a0a11171c1f202c2d2d2524221e1811090100000000000000000000000000000000000000000000000000000000070f161c202223292c2c2b2924201f1b17110a0a11171c1f202c2d2d2524221e1811090100000000000000000000000000060e161d23272a2b2d2d2d2d2d2a2926221c150d0500000000000000000000000000000000000000000000000000000000000000060e141a1e21222c2d2d2d2d2d2d2d2d21201e19140d0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e151b1f22222d2d2d2d2d2625221e18110a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004090e1112131313131313131309080603000000000000000000000000030b131a202427282d2d2d2d2525221e181109010000000000010a11181e2225262d2d2d2d2d2d2d292926211c150d04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f1315161e202020201e1d1b17120c050000000000000000000000000000000000000000000003090e1214151f202020201e1413110d070100000000000000000000000000000000000000000000060c101220202020202020202020201c1b1915100902000000000000000000000000000000000000000000000000070d12161819202020202020202020202012100c0600000000000000000000000002080d1113141e202020202020201e1413110d0701000000000000000000000000000000000000000000060b0f12131d202020202020201f1514120e090300000000000000000000000000000000000000000000050b101316161c1f201e1c1713120f0b060000060c101213202020191815120d0600000000000000000000000000000000000000000000000000000000000000050b101316161c1f201e1c1713120f0b060000060c101213202020191815120d0600000000000000000000000000000000040c12171b1d1e20202020201d1d1a16110b0300000000000000000000000000000000000000000000000000000000000000000003090e1214151f20202020202020201414110e0802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040a0f1315162020202020191816120d0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001090f14181b1b20202020191816120d07000000000000000000070d12161819202020202020201d1c1916100a0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003060809111313131312110f0b07010000000000000000000000000000000000000000000000000002050708131313131312070604010000000000000000000000000000000000000000000000000000030613131313131313131313130f0f0d09040000000000000000000000000000000000000000000000000000000106090b0c13131313131313131313130603000000000000000000000000000000000104070712131313131313131107060401000000000000000000000000000000000000000000000000000306061013131313131313120807050200000000000000000000000000000000000000000000000000000407090a0f1213120f0a0605030000000000000306071313130c0b090601000000000000000000000000000000000000000000000000000000000000000000000407090a0f1213120f0a0605030000000000000306071313130c0b09060100000000000000000000000000000000000001060b0f1111131313131311100e0a06000000000000000000000000000000000000000000000000000000000000000000000000000205070812131313131313131308070502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000306080913131313130c0c09060100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004080c0e0f131313130c0b09060100000000000000000000000106090b0c13131313131313100f0d0a05000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + m_StreamData: + offset: 0 + size: 0 + path: diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset.meta b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset.meta new file mode 100644 index 0000000..66e69d1 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f586378b4e144a9851e7b34d9b748ee +timeCreated: 1484171803 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt b/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt new file mode 100644 index 0000000..a52cc38 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt @@ -0,0 +1 @@ +)]}〕〉》」』】〙〗〟’”⦆»ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻‐゠–〜?!‼⁇⁈⁉・、%,.:;。!?]):;=}¢°"†‡℃〆%,. \ No newline at end of file diff --git a/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt.meta b/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt.meta new file mode 100644 index 0000000..73ed660 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/LineBreaking Following Characters.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fade42e8bc714b018fac513c043d323b +timeCreated: 1425440388 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt b/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt new file mode 100644 index 0000000..ccbb4ae --- /dev/null +++ b/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt @@ -0,0 +1 @@ +([{〔〈《「『【〘〖〝‘“⦅«$—…‥〳〴〵\[({£¥"々〇$¥₩ # \ No newline at end of file diff --git a/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt.meta b/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt.meta new file mode 100644 index 0000000..cc684b3 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/LineBreaking Leading Characters.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d82c1b31c7e74239bff1220585707d2b +timeCreated: 1425440388 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Sprite Assets.meta b/Assets/TextMesh Pro/Resources/Sprite Assets.meta new file mode 100644 index 0000000..5171f1b --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Sprite Assets.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 512a49d95c0c4332bdd98131869c23c9 +folderAsset: yes +timeCreated: 1441876896 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset b/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset new file mode 100644 index 0000000..98e6d27 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset @@ -0,0 +1,659 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2103686 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TextMeshPro/Sprite + m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3} + m_ShaderKeywords: UNITY_UI_CLIP_RECT + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 2800000, guid: dffef66376be4fa480fb02b19edbe903, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _ColorMask: 15 + - _CullMode: 0 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _UseUIAlphaClip: 0 + m_Colors: + - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} + - _Color: {r: 1, g: 1, b: 1, a: 1} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 84a92b25f83d49b9bc132d206b370281, type: 3} + m_Name: EmojiOne + m_EditorClassIdentifier: + hashCode: -1836805472 + material: {fileID: 2103686} + materialHashCode: 0 + m_Version: 1.1.0 + m_FaceInfo: + m_FamilyName: + m_StyleName: + m_PointSize: 0 + m_Scale: 0 + m_LineHeight: 0 + m_AscentLine: 0 + m_CapLine: 0 + m_MeanLine: 0 + m_Baseline: 0 + m_DescentLine: 0 + m_SuperscriptOffset: 0 + m_SuperscriptSize: 0 + m_SubscriptOffset: 0 + m_SubscriptSize: 0 + m_UnderlineOffset: 0 + m_UnderlineThickness: 0 + m_StrikethroughOffset: 0 + m_StrikethroughThickness: 0 + m_TabWidth: 0 + spriteSheet: {fileID: 2800000, guid: dffef66376be4fa480fb02b19edbe903, type: 3} + m_SpriteCharacterTable: + - m_ElementType: 2 + m_Unicode: 128522 + m_GlyphIndex: 0 + m_Scale: 1 + m_Name: Smiling face with smiling eyes + m_HashCode: -1318250903 + - m_ElementType: 2 + m_Unicode: 128523 + m_GlyphIndex: 1 + m_Scale: 1 + m_Name: 1f60b + m_HashCode: 57188339 + - m_ElementType: 2 + m_Unicode: 128525 + m_GlyphIndex: 2 + m_Scale: 1 + m_Name: 1f60d + m_HashCode: 57188341 + - m_ElementType: 2 + m_Unicode: 128526 + m_GlyphIndex: 3 + m_Scale: 1 + m_Name: 1f60e + m_HashCode: 57188340 + - m_ElementType: 2 + m_Unicode: 128512 + m_GlyphIndex: 4 + m_Scale: 1 + m_Name: Grinning face + m_HashCode: -95541379 + - m_ElementType: 2 + m_Unicode: 128513 + m_GlyphIndex: 5 + m_Scale: 1 + m_Name: 1f601 + m_HashCode: 57188256 + - m_ElementType: 2 + m_Unicode: 128514 + m_GlyphIndex: 6 + m_Scale: 1 + m_Name: Face with tears of joy + m_HashCode: 239522663 + - m_ElementType: 2 + m_Unicode: 128515 + m_GlyphIndex: 7 + m_Scale: 1 + m_Name: 1f603 + m_HashCode: 57188258 + - m_ElementType: 2 + m_Unicode: 128516 + m_GlyphIndex: 8 + m_Scale: 1 + m_Name: 1f604 + m_HashCode: 57188261 + - m_ElementType: 2 + m_Unicode: 128517 + m_GlyphIndex: 9 + m_Scale: 1 + m_Name: 1f605 + m_HashCode: 57188260 + - m_ElementType: 2 + m_Unicode: 128518 + m_GlyphIndex: 10 + m_Scale: 1 + m_Name: 1f606 + m_HashCode: 57188263 + - m_ElementType: 2 + m_Unicode: 128521 + m_GlyphIndex: 11 + m_Scale: 1 + m_Name: 1f609 + m_HashCode: 57188264 + - m_ElementType: 2 + m_Unicode: 0 + m_GlyphIndex: 12 + m_Scale: 1 + m_Name: .notdef + m_HashCode: -600915428 + - m_ElementType: 2 + m_Unicode: 129315 + m_GlyphIndex: 13 + m_Scale: 1 + m_Name: 1f923 + m_HashCode: 57200239 + - m_ElementType: 2 + m_Unicode: 9786 + m_GlyphIndex: 14 + m_Scale: 1 + m_Name: 263a + m_HashCode: 1748406 + - m_ElementType: 2 + m_Unicode: 9785 + m_GlyphIndex: 15 + m_Scale: 1 + m_Name: 2639 + m_HashCode: 1748462 + m_SpriteGlyphTable: + - m_Index: 0 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 1 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 2 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 3 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 384 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 4 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 5 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 6 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 7 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 256 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 8 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 128 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 9 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 128 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 10 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 128 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 11 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 128 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 12 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 0 + m_Y: 0 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 13 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 128 + m_Y: 0 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 14 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 256 + m_Y: 0 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + - m_Index: 15 + m_Metrics: + m_Width: 128 + m_Height: 128 + m_HorizontalBearingX: 0 + m_HorizontalBearingY: 115.6 + m_HorizontalAdvance: 128 + m_GlyphRect: + m_X: 384 + m_Y: 0 + m_Width: 128 + m_Height: 128 + m_Scale: 1 + m_AtlasIndex: 0 + sprite: {fileID: 0} + spriteInfoList: + - id: 0 + x: 0 + y: 384 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: Smiling face with smiling eyes + hashCode: -1318250903 + unicode: 128522 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 1 + x: 128 + y: 384 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f60b + hashCode: 57188339 + unicode: 128523 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 2 + x: 256 + y: 384 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f60d + hashCode: 57188341 + unicode: 128525 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 3 + x: 384 + y: 384 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f60e + hashCode: 57188340 + unicode: 128526 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 4 + x: 0 + y: 256 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: Grinning face + hashCode: -95541379 + unicode: 128512 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 5 + x: 128 + y: 256 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f601 + hashCode: 57188256 + unicode: 128513 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 6 + x: 256 + y: 256 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: Face with tears of joy + hashCode: 239522663 + unicode: 128514 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 7 + x: 384 + y: 256 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f603 + hashCode: 57188258 + unicode: 128515 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 8 + x: 0 + y: 128 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f604 + hashCode: 57188261 + unicode: 128516 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 9 + x: 128 + y: 128 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f605 + hashCode: 57188260 + unicode: 128517 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 10 + x: 256 + y: 128 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f606 + hashCode: 57188263 + unicode: 128518 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 11 + x: 384 + y: 128 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f609 + hashCode: 57188264 + unicode: 128521 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 12 + x: 0 + y: 0 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f618 + hashCode: 57188168 + unicode: 128536 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 13 + x: 128 + y: 0 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 1f923 + hashCode: 57200239 + unicode: 129315 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 14 + x: 256 + y: 0 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 263a + hashCode: 1748406 + unicode: 9786 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + - id: 15 + x: 384 + y: 0 + width: 128 + height: 128 + xOffset: 0 + yOffset: 115.6 + xAdvance: 128 + scale: 1 + name: 2639 + hashCode: 1748462 + unicode: 9785 + pivot: {x: 0.5, y: 0.5} + sprite: {fileID: 0} + fallbackSpriteAssets: [] +--- !u!21 &1369835458 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TextMeshPro/Sprite + m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: [] + m_Floats: [] + m_Colors: [] diff --git a/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset.meta b/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset.meta new file mode 100644 index 0000000..c7ac83f --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Sprite Assets/EmojiOne.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c41005c129ba4d66911b75229fd70b45 +timeCreated: 1480316912 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Style Sheets.meta b/Assets/TextMesh Pro/Resources/Style Sheets.meta new file mode 100644 index 0000000..4958550 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Style Sheets.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4aecb92fff08436c8303b10eab8da368 +folderAsset: yes +timeCreated: 1441876950 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset new file mode 100644 index 0000000..018d42f --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset @@ -0,0 +1,81 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: ab2114bdc8544297b417dfefe9f1e410, type: 3} + m_Name: Default Style Sheet + m_EditorClassIdentifier: + m_StyleList: + - m_Name: Normal + m_HashCode: -1183493901 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: + m_ClosingTagArray: + - m_Name: H1 + m_HashCode: 2425 + m_OpeningDefinition: <#40ff80>* + m_ClosingDefinition: '*' + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d00000032000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000660000006600000038000000300000003e0000002a000000 + m_ClosingTagArray: 2a0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: Quote + m_HashCode: 93368250 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000690000003e0000003c00000073000000690000007a000000650000003d0000003700000035000000250000003e0000003c0000006d000000610000007200000067000000690000006e0000003d0000003100000030000000250000003e000000 + m_ClosingTagArray: 3c0000002f000000690000003e0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f00000077000000690000006400000074000000680000003e0000003c0000002f0000006d000000610000007200000067000000690000006e0000003e000000 + - m_Name: A + m_HashCode: 65 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000003400000030000000610000003000000066000000660000003e0000003c000000750000003e000000 + m_ClosingTagArray: 3c0000002f000000750000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: Link + m_HashCode: 2656128 + m_OpeningDefinition: <#40a0ff> + m_ClosingDefinition: + m_OpeningTagArray: 3c000000750000003e0000003c000000230000003400000030000000610000003000000066000000660000003e0000003c0000006c000000690000006e0000006b0000003d0000002200000049000000440000005f0000003000000031000000220000003e000000 + m_ClosingTagArray: 3c0000002f000000750000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f0000006c000000690000006e0000006b0000003e000000 + - m_Name: Title + m_HashCode: 97690656 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e0000003c000000620000003e0000003c000000610000006c00000069000000670000006e0000003d00000063000000650000006e0000007400000065000000720000003e000000 + m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000610000006c00000069000000670000006e0000003e000000 + - m_Name: H2 + m_HashCode: 2426 + m_OpeningDefinition: <#4080FF> + m_ClosingDefinition: + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000002e00000035000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000380000003000000046000000460000003e000000 + m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: H3 + m_HashCode: 2427 + m_OpeningDefinition: <#FF8040> + m_ClosingDefinition: + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000002e0000003100000037000000650000006d0000003e0000003c000000620000003e0000003c000000230000004600000046000000380000003000000034000000300000003e000000 + m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: C1 + m_HashCode: 2194 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000006600000066000000660000006600000034000000300000003e000000 + m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: C2 + m_HashCode: 2193 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000006600000066000000340000003000000046000000460000003e0000003c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e000000 + m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f00000073000000690000007a000000650000003e000000 + - m_Name: C3 + m_HashCode: 2192 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000003800000030000000410000003000000046000000460000003e0000003c000000620000003e000000 + m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f000000620000003e000000 diff --git a/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset.meta b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset.meta new file mode 100644 index 0000000..95fd96e --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f952c082cb03451daed3ee968ac6c63e +timeCreated: 1432805430 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/TMP Settings.asset b/Assets/TextMesh Pro/Resources/TMP Settings.asset new file mode 100644 index 0000000..1e8d083 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/TMP Settings.asset @@ -0,0 +1,52 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 2705215ac5b84b70bacc50632be6e391, type: 3} + m_Name: TMP Settings + m_EditorClassIdentifier: + assetVersion: 2 + m_TextWrappingMode: 1 + m_enableKerning: 1 + m_ActiveFontFeatures: 00000000 + m_enableExtraPadding: 0 + m_enableTintAllSprites: 0 + m_enableParseEscapeCharacters: 1 + m_EnableRaycastTarget: 1 + m_GetFontFeaturesAtRuntime: 1 + m_missingGlyphCharacter: 0 + m_ClearDynamicDataOnBuild: 1 + m_warningsDisabled: 0 + m_defaultFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_defaultFontAssetPath: Fonts & Materials/ + m_defaultFontSize: 36 + m_defaultAutoSizeMinRatio: 0.5 + m_defaultAutoSizeMaxRatio: 2 + m_defaultTextMeshProTextContainerSize: {x: 20, y: 5} + m_defaultTextMeshProUITextContainerSize: {x: 200, y: 50} + m_autoSizeTextContainer: 0 + m_IsTextObjectScaleStatic: 0 + m_fallbackFontAssets: [] + m_matchMaterialPreset: 1 + m_HideSubTextObjects: 1 + m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, + type: 2} + m_defaultSpriteAssetPath: Sprite Assets/ + m_enableEmojiSupport: 1 + m_MissingCharacterSpriteUnicode: 0 + m_EmojiFallbackTextAssets: [] + m_defaultColorGradientPresetsPath: Color Gradient Presets/ + m_defaultStyleSheet: {fileID: 11400000, guid: f952c082cb03451daed3ee968ac6c63e, + type: 2} + m_StyleSheetsResourcePath: + m_leadingCharacters: {fileID: 4900000, guid: d82c1b31c7e74239bff1220585707d2b, type: 3} + m_followingCharacters: {fileID: 4900000, guid: fade42e8bc714b018fac513c043d323b, + type: 3} + m_UseModernHangulLineBreakingRules: 0 diff --git a/Assets/TextMesh Pro/Resources/TMP Settings.asset.meta b/Assets/TextMesh Pro/Resources/TMP Settings.asset.meta new file mode 100644 index 0000000..32db384 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/TMP Settings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3f5b5dff67a942289a9defa416b206f3 +timeCreated: 1436653997 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders.meta b/Assets/TextMesh Pro/Shaders.meta new file mode 100644 index 0000000..29a90a6 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e9f693669af91aa45ad615fc681ed29f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl b/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl new file mode 100644 index 0000000..b611994 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl @@ -0,0 +1,178 @@ +float2 UnpackUV(float uv) +{ + float2 output; + output.x = floor(uv / 4096.0); + output.y = uv - 4096.0 * output.x; + + return output * 0.001953125; +} + +float4 BlendARGB(float4 overlying, float4 underlying) +{ + overlying.rgb *= overlying.a; + underlying.rgb *= underlying.a; + float3 blended = overlying.rgb + ((1 - overlying.a) * underlying.rgb); + float alpha = underlying.a + (1 - underlying.a) * overlying.a; + return float4(blended / alpha, alpha); +} + +float3 GetSpecular(float3 n, float3 l) +{ + float spec = pow(max(0.0, dot(n, l)), _Reflectivity); + return _SpecularColor.rgb * spec * _SpecularPower; +} + +void GetSurfaceNormal_float(texture2D atlas, float textureWidth, float textureHeight, float2 uv, bool isFront, out float3 nornmal) +{ + float3 delta = float3(1.0 / textureWidth, 1.0 / textureHeight, 0.0); + + // Read "height field" + float4 h = float4( + SAMPLE_TEXTURE2D(atlas, SamplerState_Linear_Clamp, uv - delta.xz).a, + SAMPLE_TEXTURE2D(atlas, SamplerState_Linear_Clamp, uv + delta.xz).a, + SAMPLE_TEXTURE2D(atlas, SamplerState_Linear_Clamp, uv - delta.zy).a, + SAMPLE_TEXTURE2D(atlas, SamplerState_Linear_Clamp, uv + delta.zy).a); + + bool raisedBevel = _BevelType; + + h += _BevelOffset; + + float bevelWidth = max(.01, _BevelWidth); + + // Track outline + h -= .5; + h /= bevelWidth; + h = saturate(h + .5); + + if (raisedBevel) h = 1 - abs(h * 2.0 - 1.0); + h = lerp(h, sin(h * 3.141592 / 2.0), float4(_BevelRoundness, _BevelRoundness, _BevelRoundness, _BevelRoundness)); + h = min(h, 1.0 - float4(_BevelClamp, _BevelClamp, _BevelClamp, _BevelClamp)); + h *= _BevelAmount * bevelWidth * _GradientScale * -2.0; + + float3 va = normalize(float3(-1.0, 0.0, h.y - h.x)); + float3 vb = normalize(float3(0.0, 1.0, h.w - h.z)); + + float3 f = float3(1, 1, 1); + if (isFront) f = float3(1, 1, -1); + nornmal = cross(va, vb) * f; +} + +void EvaluateLight_float(float4 faceColor, float3 n, out float4 color) +{ + n.z = abs(n.z); + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), 1.0)); + + float3 col = max(faceColor.rgb, 0) + GetSpecular(n, light)* faceColor.a; + //faceColor.rgb += col * faceColor.a; + col *= 1 - (dot(n, light) * _Diffuse); + col *= lerp(_Ambient, 1, n.z * n.z); + + //fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + //faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + + color = float4(col, faceColor.a); +} + +// Add custom function to handle time in HDRP + + +// +void GenerateUV_float(float2 inUV, float4 transform, float2 animSpeed, out float2 outUV) +{ + outUV = inUV * transform.xy + transform.zw + (animSpeed * _Time.y); +} + +void ComputeUVOffset_float(float texWidth, float texHeight, float2 offset, float SDR, out float2 uvOffset) +{ + uvOffset = float2(-offset.x * SDR / texWidth, -offset.y * SDR / texHeight); +} + +void ScreenSpaceRatio2_float(float4x4 projection, float4 position, float2 objectScale, float screenWidth, float screenHeight, float fontScale, out float SSR) +{ + float2 pixelSize = position.w; + pixelSize /= (objectScale * mul((float2x2)projection, float2(screenWidth, screenHeight))); + SSR = rsqrt(dot(pixelSize, pixelSize)*2) * fontScale; +} + +// UV : Texture coordinate of the source distance field texture +// TextureSize : Size of the source distance field texture +// Filter : Enable perspective filter (soften) +void ScreenSpaceRatio_float(float2 UV, float TextureSize, bool Filter, out float SSR) +{ + if(Filter) + { + float2 a = float2(ddx(UV.x), ddy(UV.x)); + float2 b = float2(ddx(UV.y), ddy(UV.y)); + float s = lerp(dot(a,a), dot(b,b), 0.5); + SSR = rsqrt(s) / TextureSize; + } + else + { + float s = rsqrt(abs(ddx(UV.x) * ddy(UV.y) - ddy(UV.x) * ddx(UV.y))); + SSR = s / TextureSize; + } +} + +// SSR : Screen Space Ratio +// SD : Signed Distance (encoded : Distance / SDR + .5) +// SDR : Signed Distance Ratio +// +// IsoPerimeter : Dilate / Contract the shape +void ComputeSDF_float(float SSR, float SD, float SDR, float isoPerimeter, float softness, out float outAlpha) +{ + softness *= SSR * SDR; + float d = (SD - 0.5) * SDR; // Signed distance to edge, in Texture space + outAlpha = saturate((d * 2.0 * SSR + 0.5 + isoPerimeter * SDR * SSR + softness * 0.5) / (1.0 + softness)); // Screen pixel coverage (alpha) +} + +void ComputeSDF2_float(float SSR, float SD, float SDR, float2 isoPerimeter, float2 softness, out float2 outAlpha) +{ + softness *= SSR * SDR; + float d = (SD - 0.5f) * SDR; + outAlpha = saturate((d * 2.0f * SSR + 0.5f + isoPerimeter * SDR * SSR + softness * 0.5) / (1.0 + softness)); +} + +void ComputeSDF4_float(float SSR, float SD, float SDR, float4 isoPerimeter, float4 softness, out float4 outAlpha) +{ + softness *= SSR * SDR; + float d = (SD - 0.5f) * SDR; + outAlpha = saturate((d * 2.0f * SSR + 0.5f + isoPerimeter * SDR * SSR + softness * 0.5) / (1.0 + softness)); +} + +void ComputeSDF44_float(float SSR, float4 SD, float SDR, float4 isoPerimeter, float4 softness, bool outline, out float4 outAlpha) +{ + softness *= SSR * SDR; + float4 d = (SD - 0.5f) * SDR; + if(outline) d.w = max(max(d.x, d.y), d.z); + outAlpha = saturate((d * 2.0f * SSR + 0.5f + isoPerimeter * SDR * SSR + softness * 0.5) / (1.0 + softness)); +} + +void Composite_float(float4 overlying, float4 underlying, out float4 outColor) +{ + outColor = BlendARGB(overlying, underlying); +} + +// Face only +void Layer1_float(float alpha, float4 color0, out float4 outColor) +{ + color0.a *= alpha; + outColor = color0; +} + +// Face + 1 Outline +void Layer2_float(float2 alpha, float4 color0, float4 color1, out float4 outColor) +{ + color1.a *= alpha.y; + color0.rgb *= color0.a; color1.rgb *= color1.a; + outColor = lerp(color1, color0, alpha.x); + outColor.rgb /= outColor.a; +} + +// Face + 3 Outline +void Layer4_float(float4 alpha, float4 color0, float4 color1, float4 color2, float4 color3, out float4 outColor) +{ + color3.a *= alpha.w; + color0.rgb *= color0.a; color1.rgb *= color1.a; color2.rgb *= color2.a; color3.rgb *= color3.a; + outColor = lerp(lerp(lerp(color3, color2, alpha.z), color1, alpha.y), color0, alpha.x); + outColor.rgb /= outColor.a; +} diff --git a/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl.meta b/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl.meta new file mode 100644 index 0000000..001b14e --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 96de908384869cd409c75efa351d5edf +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader new file mode 100644 index 0000000..7e0f35c --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader @@ -0,0 +1,145 @@ +Shader "TextMeshPro/Bitmap Custom Atlas" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + _FaceColor ("Text Color", Color) = (1,1,1,1) + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _Padding ("Padding", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader{ + + Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull [_CullMode] + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + + struct appdata_t + { + float4 vertex : POSITION; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + float4 mask : TEXCOORD2; + }; + + uniform sampler2D _MainTex; + uniform sampler2D _FaceTex; + uniform float4 _FaceTex_ST; + uniform fixed4 _FaceColor; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + uniform float _UIMaskSoftnessX; + uniform float _UIMaskSoftnessY; + uniform int _UIVertexColorAlwaysGammaSpace; + + v2f vert (appdata_t v) + { + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + + float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert)); + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + v.color.rgb = UIGammaToLinear(v.color.rgb); + } + fixed4 faceColor = v.color; + faceColor *= _FaceColor; + + v2f OUT; + OUT.vertex = vPosition; + OUT.color = faceColor; + OUT.texcoord0 = v.texcoord0; + OUT.texcoord1 = TRANSFORM_TEX(v.texcoord1, _FaceTex); + float2 pixelSize = vPosition.w; + pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + const float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : SV_Target + { + fixed4 color = tex2D(_MainTex, IN.texcoord0) * tex2D(_FaceTex, IN.texcoord1) * IN.color; + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + + CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta new file mode 100644 index 0000000..0a416c8 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 48bb5f55d8670e349b6e614913f9d910 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader new file mode 100644 index 0000000..b89e267 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader @@ -0,0 +1,155 @@ +Shader "TextMeshPro/Mobile/Bitmap" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _Color ("Text Color", Color) = (1,1,1,1) + _DiffusePower ("Diffuse Power", Range(1.0,4.0)) = 1.0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull [_CullMode] + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma fragmentoption ARB_precision_hint_fastest + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + + struct appdata_t + { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f + { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float4 mask : TEXCOORD2; + }; + + sampler2D _MainTex; + fixed4 _Color; + float _DiffusePower; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + uniform float _UIMaskSoftnessX; + uniform float _UIMaskSoftnessY; + uniform int _UIVertexColorAlwaysGammaSpace; + + v2f vert (appdata_t v) + { + v2f OUT; + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + v.color.rgb = UIGammaToLinear(v.color.rgb); + } + OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert)); + OUT.color = v.color; + OUT.color *= _Color; + OUT.color.rgb *= _DiffusePower; + OUT.texcoord0 = v.texcoord0; + + float2 pixelSize = OUT.vertex.w; + //pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + const float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : COLOR + { + fixed4 color = fixed4(IN.color.rgb, IN.color.a * tex2D(_MainTex, IN.texcoord0).a); + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + +SubShader { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + BindChannels { + Bind "Color", color + Bind "Vertex", vertex + Bind "TexCoord", texcoord0 + } + Pass { + SetTexture [_MainTex] { + constantColor [_Color] combine constant * primary, constant * texture + } + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader.meta new file mode 100644 index 0000000..d5fb125 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1e3b057af24249748ff873be7fafee47 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader b/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader new file mode 100644 index 0000000..caa527f --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader @@ -0,0 +1,145 @@ +Shader "TextMeshPro/Bitmap" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + _FaceColor ("Text Color", Color) = (1,1,1,1) + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader{ + + Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull [_CullMode] + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + + struct appdata_t + { + float4 vertex : POSITION; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + float4 mask : TEXCOORD2; + }; + + uniform sampler2D _MainTex; + uniform sampler2D _FaceTex; + uniform float4 _FaceTex_ST; + uniform fixed4 _FaceColor; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + uniform float _UIMaskSoftnessX; + uniform float _UIMaskSoftnessY; + uniform int _UIVertexColorAlwaysGammaSpace; + + v2f vert (appdata_t v) + { + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + + float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert)); + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + v.color.rgb = UIGammaToLinear(v.color.rgb); + } + fixed4 faceColor = v.color; + faceColor *= _FaceColor; + + v2f OUT; + OUT.vertex = vPosition; + OUT.color = faceColor; + OUT.texcoord0 = v.texcoord0; + OUT.texcoord1 = TRANSFORM_TEX(v.texcoord1, _FaceTex); + float2 pixelSize = vPosition.w; + pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + const float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : SV_Target + { + fixed4 color = tex2D(_MainTex, IN.texcoord0); + color = fixed4 (tex2D(_FaceTex, IN.texcoord1).rgb * IN.color.rgb, IN.color.a * color.a); + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + + CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader.meta new file mode 100644 index 0000000..7eb1870 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 128e987d567d4e2c824d754223b3f3b0 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader new file mode 100644 index 0000000..757a617 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader @@ -0,0 +1,326 @@ +Shader "TextMeshPro/Distance Field Overlay" { + +Properties { + _FaceTex ("Face Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 + _SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularPower ("Specular", Range(0,4)) = 2.0 + _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 + _Diffuse ("Diffuse", Range(0,1)) = 0.5 + _Ambient ("Ambient", Range(1,0)) = 0.5 + + _BumpMap ("Normal map", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0 + _BumpFace ("Bump Face", Range(0,1)) = 0 + + _ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1) + _ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + + + _UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + Tags + { + "Queue"="Overlay" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest Always + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma target 3.0 + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ BEVEL_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + #pragma shader_feature __ GLOW_ON + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + struct vertex_t + { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 position : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t + { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 position : SV_POSITION; + fixed4 color : COLOR; + float2 atlas : TEXCOORD0; // Atlas + float4 param : TEXCOORD1; // alphaClip, scale, bias, weight + float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw) + float3 viewDir : TEXCOORD3; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 texcoord2 : TEXCOORD4; // u,v, scale, bias + fixed4 underlayColor : COLOR1; + #endif + + float4 textures : TEXCOORD5; + }; + + // Used by Unity internally to handle Texture Tiling and Offset. + uniform float4 _FaceTex_ST; + uniform float4 _OutlineTex_ST; + uniform float _UIMaskSoftnessX; + uniform float _UIMaskSoftnessY; + uniform int _UIVertexColorAlwaysGammaSpace; + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input,output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord0.w, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float bias =(.5 - weight) + (.5 / scale); + + float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA); + + #if GLOW_ON + alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); + #endif + + alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float bScale = scale; + bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale); + float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 bOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Support for texture tiling and offset + float2 textureUV = input.texcoord1; + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + output.position = vPosition; + output.color = input.color; + output.atlas = input.texcoord0; + output.param = float4(alphaClip, scale, bias, weight); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias); + output.underlayColor = underlayColor; + #endif + output.textures = float4(faceUV, outlineUV); + + return output; + } + + + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + float c = tex2D(_MainTex, input.atlas).a; + + #ifndef UNDERLAY_ON + clip(c - input.param.x); + #endif + + float scale = input.param.y; + float bias = input.param.z; + float weight = input.param.w; + float sd = (bias - c) * scale; + + float outline = (_OutlineWidth * _ScaleRatioA) * scale; + float softness = (_OutlineSoftness * _ScaleRatioA) * scale; + + half4 faceColor = _FaceColor; + half4 outlineColor = _OutlineColor; + + faceColor.rgb *= input.color.rgb; + + faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y); + outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y); + + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + + #if BEVEL_ON + float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); + float3 n = GetSurfaceNormal(input.atlas, weight, dxy); + + float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + n = normalize(n- bump); + + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0)); + + float3 col = GetSpecular(n, light); + faceColor.rgb += col*faceColor.a; + faceColor.rgb *= 1-(dot(n, light)*_Diffuse); + faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z); + + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + #endif + + #if UNDERLAY_ON + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); + #endif + + #if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + faceColor.rgb += glowColor.rgb * glowColor.a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + faceColor *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor * input.color.a; + } + ENDCG + } +} + +Fallback "TextMeshPro/Mobile/Distance Field" +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader.meta new file mode 100644 index 0000000..56284e9 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dd89cf5b9246416f84610a006f916af7 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader new file mode 100644 index 0000000..27c14bc --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader @@ -0,0 +1,321 @@ +Shader "TextMeshPro/Distance Field SSD" { + +Properties { + _FaceTex ("Face Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 + _SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularPower ("Specular", Range(0,4)) = 2.0 + _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 + _Diffuse ("Diffuse", Range(0,1)) = 0.5 + _Ambient ("Ambient", Range(1,0)) = 0.5 + + _BumpMap ("Normal map", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0 + _BumpFace ("Bump Face", Range(0,1)) = 0 + + _ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1) + _ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + + + _UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue" = "Transparent" + "IgnoreProjector" = "True" + "RenderType" = "Transparent" + } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + Cull[_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest[unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass + { + CGPROGRAM + #pragma target 3.0 + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ BEVEL_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + #pragma shader_feature __ GLOW_ON + #pragma shader_feature __ FORCE_LINEAR + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + struct vertex_t + { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 position : POSITION; + float3 normal : NORMAL; + float4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t + { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 position : SV_POSITION; + float4 color : COLOR; + float2 atlas : TEXCOORD0; + float weight : TEXCOORD1; + float2 mask : TEXCOORD2; // Position in object space(xy) + float3 viewDir : TEXCOORD3; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float2 texcoord2 : TEXCOORD4; + float4 underlayColor : COLOR1; + #endif + + float4 textures : TEXCOORD5; + }; + + // Used by Unity internally to handle Texture Tiling and Offset. + float4 _FaceTex_ST; + float4 _OutlineTex_ST; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + + float4 SRGBToLinear(float4 rgba) + { + return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a); + } + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input,output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord0.w, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + float4 vPosition = UnityObjectToClipPos(vert); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 bOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + + // Support for texture tiling and offset + float2 textureUV = input.texcoord1; + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + float4 color = input.color; + #if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA) + color = SRGBToLinear(input.color); + #endif + + output.position = vPosition; + output.color = color; + output.atlas = input.texcoord0; + output.weight = weight; + output.mask = half2(vert.xy * 2 - clampedRect.xy - clampedRect.zw); + output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord2 = input.texcoord0 + bOffset; + output.underlayColor = underlayColor; + #endif + output.textures = float4(faceUV, outlineUV); + + return output; + } + + + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + float c = tex2D(_MainTex, input.atlas).a; + + float pixelSize = abs(ddx(input.atlas.y)) + abs(ddy(input.atlas.y)); + pixelSize *= _TextureHeight * 0.75; + float scale = 1 / pixelSize * _GradientScale * (_Sharpness + 1); + + float weight = input.weight; + float bias = (.5 - weight) + (.5 / scale); + float sd = (bias - c) * scale; + + float outline = (_OutlineWidth * _ScaleRatioA) * scale; + float softness = (_OutlineSoftness * _ScaleRatioA) * scale; + + half4 faceColor = _FaceColor; + half4 outlineColor = _OutlineColor; + + faceColor.rgb *= input.color.rgb; + + faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y); + outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y); + + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + + #if BEVEL_ON + float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); + float3 n = GetSurfaceNormal(input.atlas, weight, dxy); + + float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + n = normalize(n - bump); + + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0)); + + float3 col = GetSpecular(n, light); + faceColor.rgb += col * faceColor.a; + faceColor.rgb *= 1 - (dot(n, light) * _Diffuse); + faceColor.rgb *= lerp(_Ambient, 1, n.z * n.z); + + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + #endif + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float bScale = scale; + bScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * bScale); + float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); + #endif + + #if UNDERLAY_ON + float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale; + faceColor += input.underlayColor * saturate(d - bBias) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale; + faceColor += input.underlayColor * (1 - saturate(d - bBias)) * saturate(1 - sd) * (1 - faceColor.a); + #endif + + #if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + faceColor.rgb += glowColor.rgb * glowColor.a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + float2 maskZW = 0.25 / (0.25 * maskSoftness + 1 / scale); + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * maskZW); + faceColor *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor * input.color.a; + } + ENDCG + } +} + +Fallback "TextMeshPro/Mobile/Distance Field" +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader.meta new file mode 100644 index 0000000..08cd8ae --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 14eb328de4b8eb245bb7cea29e4ac00b +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph new file mode 100644 index 0000000..4f7157c --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph @@ -0,0 +1,12074 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "386c36a1c4c34ea29deb680fb82cfe8b", + "m_Properties": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "c417006ffa034c44b79da3dd323165ff" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "6b0cd1bfb339459ca967fa23df287ef0" + } + ], + "m_Nodes": [ + { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + }, + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + }, + { + "m_Id": "bc782d8e80154073b48a687a07adf60a" + }, + { + "m_Id": "2786e48f93f54a82aee4303ce7b63c82" + }, + { + "m_Id": "7f7d8028b58d4227a4560891be6e7cda" + }, + { + "m_Id": "f5a8bfcec21a4dac9df63993ec53635e" + }, + { + "m_Id": "be58359e488f42e9b5121357d0fa526b" + } + ], + "m_GroupDatas": [ + { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 5 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 6 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 1 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3749.0 + }, + "m_Blocks": [ + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3480.0 + }, + "m_Blocks": [ + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + }, + { + "m_Id": "bc782d8e80154073b48a687a07adf60a" + }, + { + "m_Id": "2786e48f93f54a82aee4303ce7b63c82" + }, + { + "m_Id": "7f7d8028b58d4227a4560891be6e7cda" + }, + { + "m_Id": "f5a8bfcec21a4dac9df63993ec53635e" + }, + { + "m_Id": "be58359e488f42e9b5121357d0fa526b" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"fileID\":10210,\"guid\":\"0000000000000000e000000000000000\",\"type\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "TextMeshPro/SRP", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "7cf0e63037a74dc2a9f591225c678ff4" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "007c75c776ac4f1babe9cd7ae1fc4f14", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5722.99951171875, + "y": -3827.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1356dc7cbdfa4199a6535d3bbf4cd536" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.BuiltinData", + "m_ObjectId": "00996039d61e400a9e854ce591ac35a0", + "m_Distortion": false, + "m_DistortionMode": 0, + "m_DistortionDepthTest": true, + "m_AddPrecomputedVelocity": false, + "m_TransparentWritesMotionVec": false, + "m_DepthOffset": false, + "m_ConservativeDepthOffset": false, + "m_TransparencyFog": true, + "m_AlphaTestShadow": false, + "m_BackThenFrontRendering": false, + "m_TransparentDepthPrepass": false, + "m_TransparentDepthPostpass": false, + "m_TransparentPerPixelSorting": false, + "m_SupportLodCrossFade": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "013228b0fdf1424097798f0973a9a4fb", + "m_Title": "Face Texture", + "m_Position": { + "x": -4828.0, + "y": -2832.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "02559cbe5ad441a3904ccb75ded2b2c5", + "m_Id": 5, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "03182b3263304258b265266325c21f65", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "045c4f6b050549c7a0efb208e6349779", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "04dc152dd2ba4d519391577eb1156235", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4540.0, + "y": -2749.0, + "width": 151.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "3d04f5ba6e7b40d281f22eb424145acd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "04dfcc9ff13a4bf282ed46faec39d15c", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "05805bc6fcc941fd889922555c6c86d7", + "m_Guid": { + "m_GuidSerialized": "fe84e680-4cee-4ca5-be86-2e293a9ba093" + }, + "m_Name": "Ambient Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_05805bc6fcc941fd889922555c6c86d7", + "m_OverrideReferenceName": "_Ambient", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "0580d4b7e3a049049569f4508643a724", + "m_Guid": { + "m_GuidSerialized": "eefb88c5-7665-45dc-b3c2-7cf98b9990d6" + }, + "m_Name": "Softness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_D64EC33D", + "m_OverrideReferenceName": "_Softness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "068ae649e00b40e198ec5a30ad741fab", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0699eea947fc426cbfeb8744cf120222", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "07946387933e416db576b677f0711e5f", + "m_Guid": { + "m_GuidSerialized": "21d612fb-8153-41f8-9e2f-9de044c19fbf" + }, + "m_Name": "_FaceTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1A08AD4A", + "m_OverrideReferenceName": "_FaceText_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "082e9706dffc4c188270980d4e44ce0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0848ba750e0341198cf0bbd413e0efe4", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "09b1b86c1c074337a4c439d3a308dd2e", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0a67ca5280214bd794dc0ad66b5710a9", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0b57f2d35157477ab2b29a5aac14ae8b", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0ba4932e164847878ddb7b7bcff96985", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0c4dc51f26484c26ad88a3fe4002abcd", + "m_Id": 2, + "m_DisplayName": "Color (1)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "0d6a57754b824f6db9cefa6953bc06a9", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0d7878dd226d4cfb81a991dc312309fc", + "m_Id": 0, + "m_DisplayName": "Underlay Dilate", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "0f7ffb6d2de4447f9736780cbcee8e07", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0fac35636fca4474a6afaefc3c757775", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "105b1ed1aa714e41bbe1ef5472bdb11f", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -4233.0, + "width": 158.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "8a08179f99d649d289b8053d5fa0ad22" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "109f638d1f9b49d4991d6d21a86d4eb7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5098.99951171875, + "y": -3182.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "880bb02c6c6b49b18aa6ebc66dc566a0" + }, + { + "m_Id": "1b9cd8f5f4004e2eaf8afbaab803bc04" + }, + { + "m_Id": "b224a1cf80604103ad085c799995f3c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "10a99c07aad742349d258db16838c129", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1196ae398cc348349ab0c1a23fdab4bd", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1356dc7cbdfa4199a6535d3bbf4cd536", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "14ad19bf20a140dd88d58452d7df688b", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 1.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "150533bad8e2424aaa2c74e253af8592", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4955.0, + "y": -3487.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "72fb5a0d7796446b9e2b929cb32facdc" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "163beb4431c34f538340bc0af0991e6f", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3284.0, + "y": -3516.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c334de01ecd429baa7652fc6002536b" + }, + { + "m_Id": "e2d28f29bbac4983a401574480b5ca28" + }, + { + "m_Id": "6a7af6143e114a538663e71f56731a21" + }, + { + "m_Id": "3e25be96bb3747738c238cf3a741d5df" + }, + { + "m_Id": "4907352322c644ebacdf2ca30f2994fd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "183118ca50814141b7bc3e0cee27fb9b", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "19075add867e4757b9520d18fe8de1d0", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4291.99951171875, + "y": -3197.0, + "width": 124.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c28ee9109014fa086e5de7a3993341d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0580d4b7e3a049049569f4508643a724" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1b9cd8f5f4004e2eaf8afbaab803bc04", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1bdde3efd3b7464b8934c555be0f8a48", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "1be90d4f96a841748b0c95219b12ad27", + "m_Guid": { + "m_GuidSerialized": "4c91c146-43bb-4de8-948a-fbf8b1da10e1" + }, + "m_Name": "Bevel Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_97690701", + "m_OverrideReferenceName": "_BevelOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": -0.5, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "1c4df61c2fea404eb3b87b270d7c59bc", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4311.0, + "y": -3221.0, + "width": 148.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "f864c900600e427ba7793f00c715e971" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1d35fa1fb5004f96a65ace54fbe4f1ad", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1db37082bf844442804487b4944352de", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1df58cfa4dad4c449d01ee1c5ea05f2e", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "1e12726617b24675958e942eb62e4b09", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4772.0, + "y": -4404.0, + "width": 145.00001525878907, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "0848ba750e0341198cf0bbd413e0efe4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1f247658c7ba45fb93c41f51e21acb0d", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1f46181633594ae0a1fb2adb76b42981", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "200245fc8bbe4826b209ab5f7ffe074c", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "204dacb5a95b424facf11cb6f65bd188", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "215a82c127204988b751de7d3a39b955", + "m_Id": 6, + "m_DisplayName": "Outline", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Outline", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "215b30ae27784ec3a13360a9029af283", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "21a7a380e66d42e780e2a2a1baa630d5", + "m_Guid": { + "m_GuidSerialized": "b2d0099f-e605-49f5-9959-e7cacae37aa3" + }, + "m_Name": "Bevel Type", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_21a7a380e66d42e780e2a2a1baa630d5", + "m_OverrideReferenceName": "_BevelType", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e", + "m_Guid": { + "m_GuidSerialized": "cd167d3a-7465-4d5a-86fc-0f22dc0ef908" + }, + "m_Name": "Outline Color 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5550EB71", + "m_OverrideReferenceName": "_OutlineColor1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "232b1aa09e67479abae141d3c76d3c5b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "256d41e89a204d22951450de1c38051d", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "26e48352a08441bfa694dcea54c06e36", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "2786e48f93f54a82aee4303ce7b63c82", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Smoothness", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "9d0c47172bf840a0ac029980ba082af7" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Smoothness" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "281bcee4777040f8a31ee0e10344e98d", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "285f6a9863d54ed2a8150727ad749456", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4177.0, + "y": -2422.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "b42e6dbfbc864097af182cbff5c0c1fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.IsFrontFaceNode", + "m_ObjectId": "2a552a0b828f457c911aa19561e410ae", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Is Front Face", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4282.0, + "y": -3681.3330078125, + "width": 121.99999237060547, + "height": 77.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "2ef1d888dc9d49e59d6a6950897ddc93" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "2ac79705aa9e415dbb74ec215233fd1b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Composite (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3350.0, + "y": -3810.0, + "width": 213.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "a75f7ac601c446469802fe7754c1f279" + }, + { + "m_Id": "8c38a5d8327f456e9783740c05382619" + }, + { + "m_Id": "facc84930f544fd7a0205a6176b18ac0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Composite", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2b01ea3023e34c94af1754e4dcea8f2e", + "m_Id": 0, + "m_DisplayName": "Face Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2bf5f2fdd2984599b7323d10cfb1d240", + "m_Id": 1, + "m_DisplayName": "Filter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Filter", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "2c10b97b92c947ceb307a93759c0228b", + "m_Guid": { + "m_GuidSerialized": "6be0b8ff-a766-4c6b-a6e4-3a72758ac95f" + }, + "m_Name": "Bevel Amount", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B01DD93E", + "m_OverrideReferenceName": "_BevelAmount", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.25, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2c7a9460724b47daad8df1be144de7c6", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "2d0a269511e34bd1ba9056d2c939dff2", + "m_Guid": { + "m_GuidSerialized": "edbe73dc-53ab-4bc1-9d64-ab36e0e05f03" + }, + "m_Name": "_FaceUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_3A8E0F13", + "m_OverrideReferenceName": "_FaceUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "2db15d90c2204143b225ec4ef08d0755", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4387.0, + "y": -2405.0, + "width": 163.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "def8e0b9d8384982bc5b4c32d877e458" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "2e4eb1ef08bb44178c82e53872485e0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2ef1d888dc9d49e59d6a6950897ddc93", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 2, + "m_Value": true, + "m_DefaultValue": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.SystemData", + "m_ObjectId": "305e3be306674fcd8bb02273d27ee5b7", + "m_MaterialNeedsUpdateHash": 280372, + "m_SurfaceType": 1, + "m_RenderingPass": 4, + "m_BlendMode": 0, + "m_ZTest": 4, + "m_ZWrite": false, + "m_TransparentCullMode": 2, + "m_OpaqueCullMode": 2, + "m_SortPriority": 0, + "m_AlphaTest": true, + "m_TransparentDepthPrepass": false, + "m_TransparentDepthPostpass": false, + "m_SupportLodCrossFade": false, + "m_DoubleSidedMode": 0, + "m_DOTSInstancing": false, + "m_CustomVelocity": false, + "m_Tessellation": false, + "m_TessellationMode": 0, + "m_TessellationFactorMinDistance": 20.0, + "m_TessellationFactorMaxDistance": 50.0, + "m_TessellationFactorTriangleSize": 100.0, + "m_TessellationShapeFactor": 0.75, + "m_TessellationBackFaceCullEpsilon": -0.25, + "m_TessellationMaxDisplacement": 0.009999999776482582, + "m_DebugSymbols": false, + "m_Version": 2, + "inspectorFoldoutMask": 9 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "30ca940fe2794c949f2a1d4d2caaa446", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "319916a5921343f7b7eef0e50dc93def", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "d219977210094c0082c517d8dc00c8bb" + }, + { + "m_Id": "f48f04ad45d046a8b88e71731ed506e7" + }, + { + "m_Id": "e6e80c6b0db545cda26b079a9a78fbb3" + }, + { + "m_Id": "c6bdb985bc16435fa72f5a3c81bb633c" + }, + { + "m_Id": "d1a17e42e7a04dc38984e3c01149445b" + }, + { + "m_Id": "fb15d0ba56d54a6192f11e107aeb5fa8" + }, + { + "m_Id": "c35312edaa2344788b1964ee2f63a236" + }, + { + "m_Id": "c88fcbaeea954a5f9c68c339fa8b604d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "34a67e0fef884f9399e674d9eeaf720c", + "m_Id": 6, + "m_DisplayName": "Color3", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color3", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "34a72a5ebb04402384a4fd3748111a37", + "m_Id": 0, + "m_DisplayName": "Alpha Clip Threshold", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AlphaClipThreshold", + "m_StageCapability": 2, + "m_Value": 0.0010000000474974514, + "m_DefaultValue": 0.5, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3535ae87c6dd4769b52b20d9eca61069", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "35cbea6373dd4e4f8d0fea36e8add392", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "36a0c473c4c04c3a930dd38f3920d410", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "36f1b4d96f2941c39e5cd95d9c1d2ce6", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6008.99951171875, + "y": -3341.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "65b3dc13b2b6484283ffe5abfe87a06a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "373f1de8db6c429c9d46c781f741d7a4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3802c81c3be24823aa1d7c9997a33c29", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "3915c1927ffe49f8967304321cfbe497", + "m_Id": 4, + "m_DisplayName": "Atlas", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Atlas", + "m_StageCapability": 3, + "m_BareResource": true, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "39a382d661e2484da71f04c43f48e55f", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "39f2f84f30304d859fb07569e2695f60", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3423.000244140625, + "y": -3516.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "4b2d9ea03bf64fa19dcae1511d2581da" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "3c50439118b2496f9e390021b0964606", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.AlphaClipThreshold", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3028.0, + "y": -3054.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "34a72a5ebb04402384a4fd3748111a37" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.AlphaClipThreshold" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3d04f5ba6e7b40d281f22eb424145acd", + "m_Id": 0, + "m_DisplayName": "Face Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3db1608e927e4102a3c3a88e9fcab39a", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3dccd64e7f324bc1a75c1479d7a67c51", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "3e231021af7b47ba97f2871e7f25d0fe", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2803.000244140625, + "y": -3520.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "6ccaced3889e4503a9414d808ec33981" + }, + { + "m_Id": "7f3d71a6c96847c099da45f95aafbecb" + }, + { + "m_Id": "d8edec16956c4f15b7d51d6ec10753f4" + }, + { + "m_Id": "39a382d661e2484da71f04c43f48e55f" + }, + { + "m_Id": "8764669016f6442f8152593c18a649d7" + }, + { + "m_Id": "26e48352a08441bfa694dcea54c06e36" + }, + { + "m_Id": "3e94a0d106064bdb864c960512ef4026" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3e25be96bb3747738c238cf3a741d5df", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "3e372195f4bd4845852a37839e5b602d", + "m_Guid": { + "m_GuidSerialized": "60abd046-2a1a-48cd-a0af-2f702f7f53ab" + }, + "m_Name": "_MainTex", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_90CBF488", + "m_OverrideReferenceName": "_MainTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":28684132378477856,\"guid\":\"8f586378b4e144a9851e7b34d9b748ee\",\"type\":2}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "3e94a0d106064bdb864c960512ef4026", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "3ec4797e381747829ef4712c85fcf7a1", + "m_Guid": { + "m_GuidSerialized": "020d65cc-50a8-4b8a-a624-90d7b489f549" + }, + "m_Name": "Specular Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_3ec4797e381747829ef4712c85fcf7a1", + "m_OverrideReferenceName": "_SpecularPower", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 1.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 4.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "3fdf4b7bc5d4426492dcc057603ef4a6", + "m_Guid": { + "m_GuidSerialized": "675d2567-3fca-4da6-9462-dfa4924950f1" + }, + "m_Name": "_OutlineUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_D66D89E6", + "m_OverrideReferenceName": "_OutlineUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "400d0b6c95dd4540ad3da3e8cb7e50b2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "41986ac6400d46709d0ef043a67f6b34", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "41b9b79b3859472882bcea393703eec0", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "424dbeeb009344efa29c304c4979e3d6", + "m_Guid": { + "m_GuidSerialized": "314c37de-c6f2-4463-866d-8588f6fc119e" + }, + "m_Name": "Diffuse Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_424dbeeb009344efa29c304c4979e3d6", + "m_OverrideReferenceName": "_Diffuse", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "42a586e4f6ec40eeaba891b7fd133864", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4934.0, + "y": -4442.99951171875, + "width": 133.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "da7a06d393a44089842070d51d2aa0a6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "42cadae0923e4969b50bbc3f78185934", + "m_Title": "Face + 3 Outlines + Underlay", + "m_Position": { + "x": -5468.0, + "y": -3558.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4328cdbf78b94c038fd614c59bfe1cac", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "44317f2e371447e2a8d894f8a021a235", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Layer1 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4004.999755859375, + "y": -4173.0, + "width": 191.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "10a99c07aad742349d258db16838c129" + }, + { + "m_Id": "b85d677872b44421bf5536f42ba0267c" + }, + { + "m_Id": "75aba700d74d4b2687bf3166cf1da3e2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer1", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "44806230fa384c1e95f9c5918a14f056", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4488af8ff6a7421298a7e827f567263b", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4109.0, + "width": 158.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "66f69ef16eac4eb48357bde804cf3c39" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "4590bfa2a0664b65b6f073bae33a071f", + "m_Id": 0, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_ColorMode": 1, + "m_DefaultColor": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "4648b46ad29a4008a80de4f8a5a5b813", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4615.0, + "y": -2422.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "b2baf44eae52473cb6cda7b1debece01" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "46fbf3eeb0ea4470869cba7443249295", + "m_Guid": { + "m_GuidSerialized": "be87c5a3-e361-4b95-89c8-911c39a51c0d" + }, + "m_Name": "Outline Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_A0B54237", + "m_OverrideReferenceName": "_OutlineTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "47d020251e9841a5b1f0fd64396026a1", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "48390d02257d41bf98eace1deaa4c539", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "8036d0e6090b456e9b4ea87227868236" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "484b51c50485473b819c4f05087b32d7", + "m_Title": "Underlay", + "m_Position": { + "x": -5253.0, + "y": -4542.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4907352322c644ebacdf2ca30f2994fd", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "49e7c3ad55ce458797f0e60c950cb965", + "m_Guid": { + "m_GuidSerialized": "31b55db9-0da1-4ec4-af2b-d83747ed5bc4" + }, + "m_Name": "Underlay Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_CE9DEDB3", + "m_OverrideReferenceName": "_UnderlayOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4a66dcbe712a4d40bd8f355b834594b5", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "4abff6ff92fa4a05b203f10580988335", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4323.99951171875, + "y": -3498.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "b015d1b7e4134c59baf6851e7649802c" + }, + { + "m_Id": "d9dc4839ee2847999110bdb234d6041a" + }, + { + "m_Id": "91d6a9a5fbc04ea49075cb51835e7264" + }, + { + "m_Id": "f42ad06b3c6a45d3ab33de904c063412" + }, + { + "m_Id": "ed6c215a65584deeaefad1d2c7743044" + }, + { + "m_Id": "edbee7a8952b46529ac5ad0365775774" + }, + { + "m_Id": "70337a74f6ad4b7bb6befc825219bab1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4b2d9ea03bf64fa19dcae1511d2581da", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4bda5c294e1949138d033640e1d385b4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4c28ee9109014fa086e5de7a3993341d", + "m_Id": 0, + "m_DisplayName": "Softness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4c334de01ecd429baa7652fc6002536b", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4d1cb1a475df49f9a148195a65f5453a", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4d9ce48719d143748f9f8e22da6f9ddc", + "m_Id": 5, + "m_DisplayName": "TextureWidth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureWidth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4e64dac49ddc47c3b5b1e27b17a08304", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "4eb3c00a1ca44e10be833b7ca61ff059", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4f194ff591484e908fc2bcdacbcf2570", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4309.0, + "y": -2773.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "2b01ea3023e34c94af1754e4dcea8f2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "509e6f38505b4b0695b263706a55028f", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "51378bae98a94c309785d14cd5cbb453", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "GetSurfaceNormal (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4067.333251953125, + "y": -3881.99951171875, + "width": 263.9999694824219, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "5b0077c23eae443887872f84227deccc" + }, + { + "m_Id": "3915c1927ffe49f8967304321cfbe497" + }, + { + "m_Id": "4d9ce48719d143748f9f8e22da6f9ddc" + }, + { + "m_Id": "ebd6d75abcb84108bcadbfe7ee5f6244" + }, + { + "m_Id": "ef9738ec7e894772a14e9dce441c16c6" + }, + { + "m_Id": "9eeec1a9713045af8845cea263d5ea48" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GetSurfaceNormal", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "51f76f8a53ad43a4ad028426548ce9ba", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "52798bdb86f6400e86489a7a368e9f8b", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6154.99951171875, + "y": -3169.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1df58cfa4dad4c449d01ee1c5ea05f2e" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "53073e5ea924459fa6681a4943e9f947", + "m_Guid": { + "m_GuidSerialized": "5fdac24e-2d58-4471-80ce-79c3ab9a2564" + }, + "m_Name": "Outline Color 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_DBAB5AEC", + "m_OverrideReferenceName": "_OutlineColor2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.009433984756469727, + "g": 0.02534518577158451, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "54d7a93ffec5490aa4591da23a21b693", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "55ffa45ec3654d5e88089fb40d2b0465", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "56c25395796e4d2fbe5c892d428d1620", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5102.99951171875, + "y": -3427.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "9eb8137a6c2e41bbafdc8b0732dd47a3" + }, + { + "m_Id": "36a0c473c4c04c3a930dd38f3920d410" + }, + { + "m_Id": "068ae649e00b40e198ec5a30ad741fab" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "57abc172afd449e2a4d567f93432507b", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "582d6e289dbe4fdca7cf0307273eaa2f", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "59bd90a849624124bae6464ee3669aa6", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4007.0, + "y": -2395.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "2e4eb1ef08bb44178c82e53872485e0f" + }, + { + "m_Id": "8695190a5e614f2d90081871a8a06fc2" + }, + { + "m_Id": "81bdb47901ef48e5a588c6724b1b0142" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "5b0077c23eae443887872f84227deccc", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5b3ff4ee364f4d7a923b530ad60d8762", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5bd258837c514ff7ab0bf7027e762c18", + "m_Guid": { + "m_GuidSerialized": "2d8f3ee9-1307-4b58-a60d-526e86b07109" + }, + "m_Name": "Bevel Roundness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_AB6A015F", + "m_OverrideReferenceName": "_BevelRoundness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5da82bf481f8489ebd05e997f617f51b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": 4.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5e42524569844befad16fda5a94eb9cb", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5fbe253f3e444f2aa8ac717f9c856619", + "m_Guid": { + "m_GuidSerialized": "0a61c93f-6430-4aa6-af07-79bc3b411ccd" + }, + "m_Name": "Bevel Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B50BBFCC", + "m_OverrideReferenceName": "_BevelWidth", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.5, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61133d79a89048c195f54939b2a1d30a", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61a6ac5f29344d109411f26850ab0a96", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDLitData", + "m_ObjectId": "6238ae56182d404f8563cb88cb801549", + "m_RayTracing": false, + "m_MaterialType": 0, + "m_MaterialTypeMask": 2, + "m_RefractionModel": 0, + "m_SSSTransmission": true, + "m_EnergyConservingSpecular": true, + "m_ClearCoat": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6271438664e74b3fbf723bd6a1f50f8b", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "62bc551cea604e88b7858cc37d96a98a", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "636180f6e0504f2baaa5cc086980cb47", + "m_Guid": { + "m_GuidSerialized": "c1223e37-093d-4d5a-b2b0-cd9cc3e4f88e" + }, + "m_Name": "Outline Offset 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_636180f6e0504f2baaa5cc086980cb47", + "m_OverrideReferenceName": "_OutlineOffset1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "63c7cd57fc3c45a9a97b514fdae32693", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5266.99951171875, + "y": -3387.0, + "width": 156.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "c422a9a9ff824176aad2241f58c44d0b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "641eda269d7b4da9acb65f8d50035ea9", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "65b3dc13b2b6484283ffe5abfe87a06a", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "65c8e64a7535466e933eed08a2f77532", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3499.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "256d41e89a204d22951450de1c38051d" + }, + { + "m_Id": "0a67ca5280214bd794dc0ad66b5710a9" + }, + { + "m_Id": "ebbd94a7102a4457a48ac492de3bff14" + }, + { + "m_Id": "6271438664e74b3fbf723bd6a1f50f8b" + }, + { + "m_Id": "c9b722d107ce4cd6a748c883472b9b0f" + }, + { + "m_Id": "74cf69e61bef44589521f1bf2bf3c59a" + }, + { + "m_Id": "6e532f83d1c44e839bcfc5845d3b01d6" + }, + { + "m_Id": "cb5e9f9567e84f8fa5463efc0e256e19" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "66f69ef16eac4eb48357bde804cf3c39", + "m_Id": 0, + "m_DisplayName": "_UnderlayColor", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "67a519f507384ff1861df5d8d5b486be", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4278.0, + "y": -3939.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c3e6d7c20c184bf39fd8822130e693e7" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDLitSubTarget", + "m_ObjectId": "67bc2306558f4f2fa807637aaebaeab4" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "68ec7c31365549d6a8ce883edfc02de2", + "m_Id": 4, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6a7af6143e114a538663e71f56731a21", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "6b0cd1bfb339459ca967fa23df287ef0", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "c417006ffa034c44b79da3dd323165ff" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "6b2f65c1463f4f7bad16c54a95d2fe75", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5101.0, + "y": -3301.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "1d35fa1fb5004f96a65ace54fbe4f1ad" + }, + { + "m_Id": "fa6de3be9f5b4411b5081b49e645f424" + }, + { + "m_Id": "400d0b6c95dd4540ad3da3e8cb7e50b2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6ccaced3889e4503a9414d808ec33981", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6dfc1177dd0541a7a780fbf911ad1956", + "m_Id": 0, + "m_DisplayName": "_OutlineTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e13f3cd573c467a94379f45d96cb690", + "m_Id": 2, + "m_DisplayName": "SSR", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "6e532f83d1c44e839bcfc5845d3b01d6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6e8946a245e842b38231d4a241bfb3ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3026.0, + "y": -3110.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "ef0b93f78372439696f50711eaf57d90" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "6fbdcc5a972b4fa883dc5f21e525a376", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "70337a74f6ad4b7bb6befc825219bab1", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "703396865b6e4990a0cf1189ea684e5c", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "712da461f71a454db59d349f752d41ee", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "71dd947935b64ce38f0d25406dde447b", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "724e17584e97443e9e285dfa7253c8e3", + "m_Id": 0, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 2, + "m_Value": 0.15000000596046449, + "m_DefaultValue": 1.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "72fb5a0d7796446b9e2b929cb32facdc", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "7444469eb9884253819add9ef96baa25", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4298.0, + "y": -3809.99951171875, + "width": 144.66648864746095, + "height": 129.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "03182b3263304258b265266325c21f65" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "748c31bbcecc4b30bec2e42c0612175b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "74b41464cbed4e9e8e23af5ab9be40cf", + "m_Guid": { + "m_GuidSerialized": "41afbdcb-f3ae-4340-8973-1c1998c992a2" + }, + "m_Name": "Outline Offset 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "74cf69e61bef44589521f1bf2bf3c59a", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "7564379492aa4c5a927ff3501acdc70d", + "m_Id": 0, + "m_DisplayName": "Normal (Tangent Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalTS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 3 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "757174b6f25040fdbb20355a21752222", + "m_Id": 0, + "m_DisplayName": "Outline Offset 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "75aba700d74d4b2687bf3166cf1da3e2", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "75c5657544c648058b20cea090f48dbf", + "m_Id": 0, + "m_DisplayName": "_OutlineUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "767769f736d5478cba5f10a415e28e7f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "773b90134e894e429203c0c83e80b9de", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "77991fa631724e0cb32eed66ff017b23", + "m_Id": 0, + "m_DisplayName": "Metallic", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Metallic", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "77e28f3e930b4c249145630ec961af95", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "79147f6986644769b58d9ed64fe771e1", + "m_Id": 0, + "m_DisplayName": "OutlineMode", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7984fd094e1147bdabb4e26fbd3d31c8", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3113.000244140625, + "y": -3468.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "082e9706dffc4c188270980d4e44ce0f" + }, + { + "m_Id": "f2a351a5375c441b8d9ab7e2c9545a77" + }, + { + "m_Id": "41986ac6400d46709d0ef043a67f6b34" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "7a046f410ce64aa88438b0bfd412c045", + "m_Guid": { + "m_GuidSerialized": "d47271f5-5a84-47bf-a09e-c825d2aeb013" + }, + "m_Name": "Outline Color 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_551702C5", + "m_OverrideReferenceName": "_OutlineColor3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "7a0f504e4175406dbd8134250f4e350b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7a80e8839f0e4a1d9a6c0814f8793ee6", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4961.99951171875, + "y": -3452.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "6fbdcc5a972b4fa883dc5f21e525a376" + }, + { + "m_Id": "0ba4932e164847878ddb7b7bcff96985" + }, + { + "m_Id": "9178663316db43d582f1c4a127d307c6" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7acfafd73b8c4dfab8c55c18a887e087", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "7b8a19bd115e4167a25b59cb3218a817", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "7c27ccb2c2dc4ca59c5438c3358630ca", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDTarget", + "m_ObjectId": "7cf0e63037a74dc2a9f591225c678ff4", + "m_ActiveSubTarget": { + "m_Id": "67bc2306558f4f2fa807637aaebaeab4" + }, + "m_Datas": [ + { + "m_Id": "00996039d61e400a9e854ce591ac35a0" + }, + { + "m_Id": "305e3be306674fcd8bb02273d27ee5b7" + }, + { + "m_Id": "6238ae56182d404f8563cb88cb801549" + }, + { + "m_Id": "a8c49a47cb934f7e8e4d88fce06df6ff" + } + ], + "m_CustomEditorGUI": "TMPro.EditorUtilities.TMP_SDF_HDRPLitShaderGUI", + "m_SupportVFX": false, + "m_SupportLineRendering": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7d7696aa6d184b4fb9c316a9dec37aee", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4959.0, + "y": -3326.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "4d1cb1a475df49f9a148195a65f5453a" + }, + { + "m_Id": "47d020251e9841a5b1f0fd64396026a1" + }, + { + "m_Id": "62bc551cea604e88b7858cc37d96a98a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7d78a616c2754cc28d1f32cf66ade611", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4005.0, + "y": -2797.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "d9bcb754db834583b6518c5ed5152114" + }, + { + "m_Id": "861d4258049a4a3e8164f7297090f88e" + }, + { + "m_Id": "a7c06457d7454693a8bc3dc95257b2c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "7e0fadb2533f496192c1ad3e78642010", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4188.0, + "width": 173.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d48c3871e3064027a10ae9f4babd3be0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f2e6b5f15364ed9835d67d0cf4f8f65", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2586.0, + "y": -3592.0, + "width": 200.0, + "height": 41.0 + } + }, + "m_Slots": [ + { + "m_Id": "85ff8667d72947edada4e9fb4ff60559" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7f3d71a6c96847c099da45f95aafbecb", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f7d8028b58d4227a4560891be6e7cda", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Occlusion", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a00de0d572a84a08a23fe14c2ad5030d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Occlusion" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "8036d0e6090b456e9b4ea87227868236", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "80e665a5eeb64730a51742f698bf0d48", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "8135ca333f8f4ea78163743e6ec1f55c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3140.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d6a6a119394e4082a11bc024a6e42ef8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "81bdb47901ef48e5a588c6724b1b0142", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "81e8ed0534534674a74263e6161a2a1a", + "m_Guid": { + "m_GuidSerialized": "78aab961-c4a8-41f3-b203-1239c3b33b13" + }, + "m_Name": "Underlay Dilate", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_D48690B9", + "m_OverrideReferenceName": "_UnderlayDilate", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "82af2db1018543d7832af96c1cfc981f", + "m_Guid": { + "m_GuidSerialized": "37906c7b-9a3a-454b-a62a-9aa097e64bde" + }, + "m_Name": "Light Angle", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_82af2db1018543d7832af96c1cfc981f", + "m_OverrideReferenceName": "_LightAngle", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 6.28000020980835 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "82d5443fe54d4a3b9420f8745d00a632", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": 8.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "84dc74cdbd8c45e1b189e4fd9a69942d", + "m_Id": 0, + "m_DisplayName": "Outline Offset 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "85a1ad8e741e41759002e8cdc8cd0b96", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "ScreenSpaceRatio (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5800.99951171875, + "y": -3363.0, + "width": 258.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e13f3cd573c467a94379f45d96cb690" + }, + { + "m_Id": "8e6ed600f6504f4083092f5b511e44c4" + }, + { + "m_Id": "93b161cce4504cb79c97b6d8db178de7" + }, + { + "m_Id": "2bf5f2fdd2984599b7323d10cfb1d240" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ScreenSpaceRatio", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "85b5940eb77e4625812ded7215bab8d7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3096.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ada023d617104472b8ab75a81558c0a1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "85ff8667d72947edada4e9fb4ff60559", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "861d4258049a4a3e8164f7297090f88e", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "867a4ae13c0d4a028c71bc1063824c14", + "m_Guid": { + "m_GuidSerialized": "d483c212-0a30-4f6d-b94d-9abbc83a6522" + }, + "m_Name": "Outline Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_C68C9E14", + "m_OverrideReferenceName": "_IsoPerimeter", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 2, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "8695190a5e614f2d90081871a8a06fc2", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8764669016f6442f8152593c18a649d7", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "880bb02c6c6b49b18aa6ebc66dc566a0", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "88253223d2c34ecfab92b0c344048f94", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "ComputeSDF (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4323.0, + "width": 227.99998474121095, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "c52a1744a9a14989b0ae452ad6de6061" + }, + { + "m_Id": "a03db80c558b4f87a330c5ae0a9443a5" + }, + { + "m_Id": "8f1b1d1e8ff24b3284993e52354e54fa" + }, + { + "m_Id": "5da82bf481f8489ebd05e997f617f51b" + }, + { + "m_Id": "82d5443fe54d4a3b9420f8745d00a632" + }, + { + "m_Id": "61133d79a89048c195f54939b2a1d30a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8a08179f99d649d289b8053d5fa0ad22", + "m_Id": 0, + "m_DisplayName": "Underlay Offset", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8b66f4e6bc9d4662b3218ac33a69839f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8c38a5d8327f456e9783740c05382619", + "m_Id": 3, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8cbd81814903479ea1d3151c1f38183e", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "8cf8aae64c1d443f9303126886b40f17", + "m_Guid": { + "m_GuidSerialized": "8d78c9a5-aaef-41fb-af68-2358e401d7ac" + }, + "m_Name": "_UnderlayColor", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_2F5FE804", + "m_OverrideReferenceName": "_UnderlayColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6ed600f6504f4083092f5b511e44c4", + "m_Id": 0, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "8ed907a2cc7949b68a283ae243ea1977", + "m_Guid": { + "m_GuidSerialized": "36803443-a9bc-4f3c-a4f2-7d66a5417ac1" + }, + "m_Name": "Outline Offset 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8f1b1d1e8ff24b3284993e52354e54fa", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9147636b0cfa466a9b37a013d8f693bf", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5421.99951171875, + "y": -3902.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a4f471e3221c4134b291bd9d2ba22db6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "9178663316db43d582f1c4a127d307c6", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "91890fe48ebe4717aea61ecaf3ad4861", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2983.000244140625, + "y": -3468.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "3dccd64e7f324bc1a75c1479d7a67c51" + }, + { + "m_Id": "e444f2c81d1e48329fa2c91005277e8d" + }, + { + "m_Id": "b2c26292b7434733878a9b042f44de89" + }, + { + "m_Id": "964fea1fd4b24f4daf5bef84c4b45118" + }, + { + "m_Id": "deac82280a2b43078e0e40863e2d974c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "91d6a9a5fbc04ea49075cb51835e7264", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "928621a3ca2d41c89a10336bbbc81ddc", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "93b161cce4504cb79c97b6d8db178de7", + "m_Id": 3, + "m_DisplayName": "TextureSize", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureSize", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "945b45993dd84a979755b98c48138f72", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "952d0fa5cd744df0b434cd38e9a90b93", + "m_Guid": { + "m_GuidSerialized": "ce395871-ddeb-47c3-a31d-07855800c197" + }, + "m_Name": "_UnderlaySoftness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_F2B9E3EF", + "m_OverrideReferenceName": "_UnderlaySoftness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "95928bcb6a284b8d88105a84c2e1d3ce", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4793.0, + "y": -2593.0, + "width": 155.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d880558893fb442b9320cf55885d1117" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "964fea1fd4b24f4daf5bef84c4b45118", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "98934a69591249d5b8b92b39045359a3", + "m_Title": "Outline1 Texture", + "m_Position": { + "x": -4672.0, + "y": -2481.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "998db5e5901e45b29040eb2099370071", + "m_Guid": { + "m_GuidSerialized": "6f383614-f2ad-4269-be8f-87b0ecb03cf0" + }, + "m_Name": "Bevel Clamp", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_5BD7E808", + "m_OverrideReferenceName": "_BevelClamp", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "9c228fac287d446296b91a4acf5cec59", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3498.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "582d6e289dbe4fdca7cf0307273eaa2f" + }, + { + "m_Id": "1db37082bf844442804487b4944352de" + }, + { + "m_Id": "8b66f4e6bc9d4662b3218ac33a69839f" + }, + { + "m_Id": "4a66dcbe712a4d40bd8f355b834594b5" + }, + { + "m_Id": "a0285c9c381a49cba194709efa0a7c85" + }, + { + "m_Id": "b2728d0dd3ce40678867c94a7d977916" + }, + { + "m_Id": "e141833aa78b4fd59ecad949beb43a78" + }, + { + "m_Id": "51f76f8a53ad43a4ad028426548ce9ba" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9c26fdddba244d36a854298c00473247", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9d0c47172bf840a0ac029980ba082af7", + "m_Id": 0, + "m_DisplayName": "Smoothness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Smoothness", + "m_StageCapability": 2, + "m_Value": 0.5, + "m_DefaultValue": 0.5, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "9d3c3383d5934a17bf9efbb7fd9e9043", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5443.0, + "y": -3315.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "232b1aa09e67479abae141d3c76d3c5b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e6e50a71d9843b49b62ebe1cf7d3d59", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4486.0, + "y": -3865.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "3535ae87c6dd4769b52b20d9eca61069" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e87ce9607e14015a3790c528ca5dfda", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4637.0, + "y": -2239.0, + "width": 167.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "75c5657544c648058b20cea090f48dbf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "9eb8137a6c2e41bbafdc8b0732dd47a3", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "9eeec1a9713045af8845cea263d5ea48", + "m_Id": 6, + "m_DisplayName": "IsFront", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "IsFront", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "9f0de188085746d5a19073da1de85ddb", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4160.0, + "y": -2739.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "7c27ccb2c2dc4ca59c5438c3358630ca" + }, + { + "m_Id": "373f1de8db6c429c9d46c781f741d7a4" + }, + { + "m_Id": "fd0b096ed5b74f9e9ec51327be200731" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a00de0d572a84a08a23fe14c2ad5030d", + "m_Id": 0, + "m_DisplayName": "Ambient Occlusion", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Occlusion", + "m_StageCapability": 2, + "m_Value": 1.0, + "m_DefaultValue": 1.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a0285c9c381a49cba194709efa0a7c85", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a03db80c558b4f87a330c5ae0a9443a5", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a3f8b6e8ae7f48e2989a029904401502", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "a455bd79094c4413a7b7dd80ca8b9368", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4611.0, + "y": -2691.0, + "width": 222.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "ffb07af0bca546d8b9bc439d34aa68f5" + }, + { + "m_Id": "2c7a9460724b47daad8df1be144de7c6" + }, + { + "m_Id": "55ffa45ec3654d5e88089fb40d2b0465" + }, + { + "m_Id": "e495a9f7a11f4eb89334e83be154ceb9" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateShaderProperty", + "m_ObjectId": "a4ad98d8828c424384229c344ebe2ed0", + "m_Guid": { + "m_GuidSerialized": "f98fc1a2-bb81-4bd1-a207-23d3a90d518e" + }, + "m_Name": "SamplerState", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "SamplerState_a4ad98d8828c424384229c344ebe2ed0", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": false, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_filter": 0, + "m_wrap": 1, + "m_anisotropic": 0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a4f471e3221c4134b291bd9d2ba22db6", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "a535f3bcbeb14622bb177eb6f46e76f4", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4647.0, + "y": -2283.0, + "width": 177.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "6dfc1177dd0541a7a780fbf911ad1956" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "a6bbb32e8d884be9bb36db91fe4b81b1", + "m_Guid": { + "m_GuidSerialized": "6aa76edf-7b80-46ac-add4-406cf1d85493" + }, + "m_Name": "_GradientScale", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_EAE27356", + "m_OverrideReferenceName": "_GradientScale", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 10.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "a6c38edd2e8743a9b057ba8452b9f129", + "m_Guid": { + "m_GuidSerialized": "9fc942ee-4a1d-4ced-a5a6-81893e3ddb63" + }, + "m_Name": "Light Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_a6c38edd2e8743a9b057ba8452b9f129", + "m_OverrideReferenceName": "_SpecularColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "a75f7ac601c446469802fe7754c1f279", + "m_Id": 0, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a7942746b5564dc7bbbae1deb2403022", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "a7c06457d7454693a8bc3dc95257b2c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.LightingData", + "m_ObjectId": "a8c49a47cb934f7e8e4d88fce06df6ff", + "m_NormalDropOffSpace": 0, + "m_BlendPreserveSpecular": true, + "m_ReceiveDecals": true, + "m_ReceiveSSR": true, + "m_ReceiveSSRTransparent": false, + "m_SpecularAA": false, + "m_SpecularOcclusionMode": 0, + "m_OverrideBakedGI": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa2794b8f0e24bf281d22e0fef0647be", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "aa3e347d733e48f7b65d8a8847370eec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "EvaluateLight (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3631.0, + "y": -3810.0, + "width": 230.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "0699eea947fc426cbfeb8744cf120222" + }, + { + "m_Id": "0c4dc51f26484c26ad88a3fe4002abcd" + }, + { + "m_Id": "d5173cc3c6cd4f1998550f3187a3e9c8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "EvaluateLight", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aa87c72ac0e64469acc34f936f00b3d0", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4225.0, + "width": 193.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "0d7878dd226d4cfb81a991dc312309fc" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "abd59150589b436cadf8c9e6f43ccb8e", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "aca823a8188948c782eddaf0f45e1868", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalOS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2542.0, + "y": -3404.000244140625, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "e386b183a18245a796b024022f7f3074" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalOS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "acd0cd5a177f4a97bf23db7219305e3f", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4348.0, + "y": -3905.99951171875, + "width": 185.33299255371095, + "height": 101.33324432373047 + } + }, + "m_Slots": [ + { + "m_Id": "945b45993dd84a979755b98c48138f72" + }, + { + "m_Id": "e51a636b2621440eb94cc802c1cf4bfc" + }, + { + "m_Id": "1bdde3efd3b7464b8934c555be0f8a48" + }, + { + "m_Id": "e364823e158a407fb48dd7b630c79973" + }, + { + "m_Id": "703396865b6e4990a0cf1189ea684e5c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ada023d617104472b8ab75a81558c0a1", + "m_Id": 0, + "m_DisplayName": "Outline Color 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aef5c44f84e04c3185e0b93e95e34204", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5264.99951171875, + "y": -3142.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "84dc74cdbd8c45e1b189e4fd9a69942d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b000f852aa984e9dae25b125a4607f4e", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b015d1b7e4134c59baf6851e7649802c", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "b0b352c4503a43d083a64e57352b29a0", + "m_Guid": { + "m_GuidSerialized": "01cfcc78-60aa-4f71-a1e3-8d8df6dae253" + }, + "m_Name": "Reflectivity Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_b0b352c4503a43d083a64e57352b29a0", + "m_OverrideReferenceName": "_Reflectivity", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 5.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 5.0, + "y": 15.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "b1188549725543d485436c2e921ffbb2", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4146.0, + "y": -2833.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "281bcee4777040f8a31ee0e10344e98d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "b163c9f1666644b0bba62cf0e12df7bc", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4373.0, + "y": -2715.0, + "width": 180.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "cce40479b6284b6fa3174db9f09d0ac9" + }, + { + "m_Id": "80e665a5eeb64730a51742f698bf0d48" + }, + { + "m_Id": "1f46181633594ae0a1fb2adb76b42981" + }, + { + "m_Id": "8cbd81814903479ea1d3151c1f38183e" + }, + { + "m_Id": "cfaf3f3a5a1146e194cddad30c95aada" + }, + { + "m_Id": "b43489e37a5c4df88f15844292a55ec7" + }, + { + "m_Id": "cd7281fb41aa4e61ac0fdf71d4f4bd46" + }, + { + "m_Id": "f01d52cdcb1647aab35782b4af535efd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 1, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "b224a1cf80604103ad085c799995f3c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b2728d0dd3ce40678867c94a7d977916", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b2baf44eae52473cb6cda7b1debece01", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b2c26292b7434733878a9b042f44de89", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "b30617d78dec40a7b8aa7f72dca7f41d", + "m_Id": 0, + "m_DisplayName": "Bent Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BentNormal", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 3 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b42e6dbfbc864097af182cbff5c0c1fb", + "m_Id": 0, + "m_DisplayName": "Outline Color 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b43489e37a5c4df88f15844292a55ec7", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "b4a40cb6acd441acb83cfe0240bf910d", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4750.99951171875, + "y": -4274.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d0b10e52e21941b183f5f635894c76c8" + }, + { + "m_Id": "0d6a57754b824f6db9cefa6953bc06a9" + }, + { + "m_Id": "773b90134e894e429203c0c83e80b9de" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "b4c4676c68bb4752af59e21f896d9470", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "b571db753a1948d5a6f1de4e7d0c7238", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5581.99951171875, + "y": -3867.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "5b3ff4ee364f4d7a923b530ad60d8762" + }, + { + "m_Id": "c183b5bd9bbe45089f93996e73110918" + }, + { + "m_Id": "1196ae398cc348349ab0c1a23fdab4bd" + }, + { + "m_Id": "183118ca50814141b7bc3e0cee27fb9b" + }, + { + "m_Id": "f44e4374a48a4996aa60d23d3ae1e9f9" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b691728a389a417d9b4f2d02541209c2", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b7f9ac55517141868bfb9d2ad6429792", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b85d677872b44421bf5536f42ba0267c", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b911c23b90124d15924551e2730501eb", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "bc782d8e80154073b48a687a07adf60a", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BentNormal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "b30617d78dec40a7b8aa7f72dca7f41d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BentNormal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "bc9afcb18afa4ccc82d2cdc34d3f4641", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -5392.0, + "y": -3867.0, + "width": 125.99999237060547, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "5e42524569844befad16fda5a94eb9cb" + }, + { + "m_Id": "54d7a93ffec5490aa4591da23a21b693" + }, + { + "m_Id": "aa2794b8f0e24bf281d22e0fef0647be" + }, + { + "m_Id": "200245fc8bbe4826b209ab5f7ffe074c" + }, + { + "m_Id": "fc2e62201c5847e798fd939314413fcd" + }, + { + "m_Id": "fe11fa80cc1847a5a37f6757d521cf25" + }, + { + "m_Id": "de0c6f7f7af94defa6c3dbc6433de9d4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "be58359e488f42e9b5121357d0fa526b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Metallic", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "77991fa631724e0cb32eed66ff017b23" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Metallic" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c183b5bd9bbe45089f93996e73110918", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "c234e5216678436195ee1a5914bc79da", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4446.0, + "y": -2347.000244140625, + "width": 222.00001525878907, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "b4c4676c68bb4752af59e21f896d9470" + }, + { + "m_Id": "3db1608e927e4102a3c3a88e9fcab39a" + }, + { + "m_Id": "0f7ffb6d2de4447f9736780cbcee8e07" + }, + { + "m_Id": "d4954b7bbbb0412cbc997bcbe7dfa808" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "c35312edaa2344788b1964ee2f63a236", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "c3e6d7c20c184bf39fd8822130e693e7", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "c417006ffa034c44b79da3dd323165ff", + "m_Guid": { + "m_GuidSerialized": "7a28a011-205c-4fa8-bf4f-8064aa2308b2" + }, + "m_Name": "_ScaleRatioA", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "_ScaleRatioA", + "m_DefaultReferenceName": "_ScaleRatioA", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "c422a9a9ff824176aad2241f58c44d0b", + "m_Id": 0, + "m_DisplayName": "Outline Offset 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "c478c32c45884c57a62f7b2aa8ddc3b0", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c49cfb8bb96846dc87ee00c0c041a372", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c52a1744a9a14989b0ae452ad6de6061", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c6bdb985bc16435fa72f5a3c81bb633c", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c7d4094601ac4bc1aead609c72b1f1c1", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c7ddee91dc5b48dc828309c77fdb0b88", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4266.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a7942746b5564dc7bbbae1deb2403022" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "c88fcbaeea954a5f9c68c339fa8b604d", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c9b722d107ce4cd6a748c883472b9b0f", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c9d7f0dbae7d422985a1cc87c025e76b", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4315.0, + "y": -3165.0, + "width": 144.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "79147f6986644769b58d9ed64fe771e1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "c9ec735d1a1046769e5601b2c97c849a", + "m_Guid": { + "m_GuidSerialized": "281a9526-c332-4471-a44e-ece4a1e95ef6" + }, + "m_Name": "Face Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_75569DEA", + "m_OverrideReferenceName": "_FaceTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ca2a1083dc014f39ab8af0cdf140866b", + "m_Id": 0, + "m_DisplayName": "_FaceTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "cb3c0c3f08654b068bea44c4ffb15f4a", + "m_Guid": { + "m_GuidSerialized": "21009d12-8d94-4273-b0d0-a8ee0608ddcf" + }, + "m_Name": "OutlineMode", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_cb3c0c3f08654b068bea44c4ffb15f4a", + "m_OverrideReferenceName": "_OutlineMode", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cb5e9f9567e84f8fa5463efc0e256e19", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "cb7117ecb1d047a8b2cb00ed552cb181", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Alpha", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3032.66650390625, + "y": -3029.33349609375, + "width": 200.0, + "height": 41.33349609375 + } + }, + "m_Slots": [ + { + "m_Id": "724e17584e97443e9e285dfa7253c8e3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Alpha" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cc88101667c9488f9c5a716e851c1b21", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cce40479b6284b6fa3174db9f09d0ac9", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "cd7281fb41aa4e61ac0fdf71d4f4bd46", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cda5e3b4c1054bf3a65c0b7ec6bc778a", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "cdddee3a537c464697357f11b966f9b8", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4420.0, + "y": -4483.0, + "width": 156.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "41b9b79b3859472882bcea393703eec0" + }, + { + "m_Id": "c7d4094601ac4bc1aead609c72b1f1c1" + }, + { + "m_Id": "767769f736d5478cba5f10a415e28e7f" + }, + { + "m_Id": "b691728a389a417d9b4f2d02541209c2" + }, + { + "m_Id": "045c4f6b050549c7a0efb208e6349779" + }, + { + "m_Id": "509e6f38505b4b0695b263706a55028f" + }, + { + "m_Id": "204dacb5a95b424facf11cb6f65bd188" + }, + { + "m_Id": "35cbea6373dd4e4f8d0fea36e8add392" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "cfaf3f3a5a1146e194cddad30c95aada", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d0a791a544614667962a9a9a9ce0c68a", + "m_Title": "Screen Space Ratio", + "m_Position": { + "x": -6179.99951171875, + "y": -3422.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d0b10e52e21941b183f5f635894c76c8", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d1a17e42e7a04dc38984e3c01149445b", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d219977210094c0082c517d8dc00c8bb", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d258902c6ec74942afdb9ebf8c1d07f8", + "m_Title": "Generate Normal", + "m_Position": { + "x": -4511.33349609375, + "y": -3999.3330078125 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "d30452ac6b244ecca03df4d7b4de9f81", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d48c3871e3064027a10ae9f4babd3be0", + "m_Id": 0, + "m_DisplayName": "_UnderlaySoftness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d4954b7bbbb0412cbc997bcbe7dfa808", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "d4df208fc23b42f2b52364124f1b661c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5268.0, + "y": -3261.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "757174b6f25040fdbb20355a21752222" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "d5173cc3c6cd4f1998550f3187a3e9c8", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d6a6a119394e4082a11bc024a6e42ef8", + "m_Id": 0, + "m_DisplayName": "Outline Color 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d880558893fb442b9320cf55885d1117", + "m_Id": 0, + "m_DisplayName": "_FaceUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d8edec16956c4f15b7d51d6ec10753f4", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d9bcb754db834583b6518c5ed5152114", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d9dc4839ee2847999110bdb234d6041a", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "da7a06d393a44089842070d51d2aa0a6", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "daaf032a109749a88c9b8ff8e1f8b541", + "m_Title": "Offset Scale", + "m_Position": { + "x": -5747.99951171875, + "y": -3961.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "dbcb748279484a4590e53518c49122b8", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4783.0, + "y": -2765.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "7a0f504e4175406dbd8134250f4e350b" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "dc75c4e3a1bc4bb0a128086c2b0679a5", + "m_Guid": { + "m_GuidSerialized": "85cd941f-2fd2-43a3-b0fa-9f728bfb4220" + }, + "m_Name": "Face Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_99AFBB3D", + "m_OverrideReferenceName": "_FaceColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "de0c6f7f7af94defa6c3dbc6433de9d4", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "deac82280a2b43078e0e40863e2d974c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "def8e0b9d8384982bc5b4c32d877e458", + "m_Id": 0, + "m_DisplayName": "Outline Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "dff7a66b353a4023b29c9d937da77960", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4602.0, + "y": -4298.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7b8a19bd115e4167a25b59cb3218a817" + }, + { + "m_Id": "0b57f2d35157477ab2b29a5aac14ae8b" + }, + { + "m_Id": "e9e06fcb161e44ba8cc9f6f60264df78" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "e141833aa78b4fd59ecad949beb43a78", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e2d28f29bbac4983a401574480b5ca28", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e364823e158a407fb48dd7b630c79973", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "e386b183a18245a796b024022f7f3074", + "m_Id": 0, + "m_DisplayName": "Normal (Object Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalOS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e444f2c81d1e48329fa2c91005277e8d", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "e495a9f7a11f4eb89334e83be154ceb9", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e51a636b2621440eb94cc802c1cf4bfc", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "e591df3a1eb94e259b762f2830b407e2", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Emission", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "4590bfa2a0664b65b6f073bae33a071f" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Emission" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e6e80c6b0db545cda26b079a9a78fbb3", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "e818605f8f5a4f01bf61caaa33693581", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "ComputeSDF44 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4144.0, + "y": -3369.0, + "width": 244.0, + "height": 214.0 + } + }, + "m_Slots": [ + { + "m_Id": "641eda269d7b4da9acb65f8d50035ea9" + }, + { + "m_Id": "f6823778a3cf42d5bbe8a83e5f9c9fa3" + }, + { + "m_Id": "9c26fdddba244d36a854298c00473247" + }, + { + "m_Id": "f684c5678e9e4f078157a3ab7ef5057b" + }, + { + "m_Id": "14ad19bf20a140dd88d58452d7df688b" + }, + { + "m_Id": "215a82c127204988b751de7d3a39b955" + }, + { + "m_Id": "c478c32c45884c57a62f7b2aa8ddc3b0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF44", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "e9e06fcb161e44ba8cc9f6f60264df78", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebbd94a7102a4457a48ac492de3bff14", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebd6d75abcb84108bcadbfe7ee5f6244", + "m_Id": 7, + "m_DisplayName": "TextureHeight", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureHeight", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "ec184d6d9fb2494897774c9e7d279e6d", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4803.0, + "y": -2627.0, + "width": 165.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ca2a1083dc014f39ab8af0cdf140866b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "07946387933e416db576b677f0711e5f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "ec1f2e8bc9fd4ae38b133c60ee6c49b8", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4957.99951171875, + "y": -3204.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "748c31bbcecc4b30bec2e42c0612175b" + }, + { + "m_Id": "4bda5c294e1949138d033640e1d385b4" + }, + { + "m_Id": "4e64dac49ddc47c3b5b1e27b17a08304" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "ec79eb447dfd47a9b3380344c6a60f43", + "m_Guid": { + "m_GuidSerialized": "54c77f8b-0534-4b35-a3f0-83ab2ebe6c1f" + }, + "m_Name": "_OutlineTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1774DE83", + "m_OverrideReferenceName": "_OutlineTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "ecf16c34d46f4502ac601f0c38c7576b", + "m_Title": "Vertex Color", + "m_Position": { + "x": -3448.000244140625, + "y": -3579.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ed1d1f1613334c3bb904dd08161cd7e5", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ed6c215a65584deeaefad1d2c7743044", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "edbee7a8952b46529ac5ad0365775774", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "ef0b93f78372439696f50711eaf57d90", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.7353569269180298, + "y": 0.7353569269180298, + "z": 0.7353569269180298 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ef9738ec7e894772a14e9dce441c16c6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "f01d52cdcb1647aab35782b4af535efd", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "f23a8b2b7c85478388ff7a8c8a6de740", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Layer4 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3849.999755859375, + "y": -3286.0, + "width": 193.0, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "0fac35636fca4474a6afaefc3c757775" + }, + { + "m_Id": "cc88101667c9488f9c5a716e851c1b21" + }, + { + "m_Id": "68ec7c31365549d6a8ce883edfc02de2" + }, + { + "m_Id": "02559cbe5ad441a3904ccb75ded2b2c5" + }, + { + "m_Id": "34a67e0fef884f9399e674d9eeaf720c" + }, + { + "m_Id": "3802c81c3be24823aa1d7c9997a33c29" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer4", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "f2903158b3624759bca1fcd843698078", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "f2a351a5375c441b8d9ab7e2c9545a77", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "f383b24f0bc6434dafe44b3e3d338a63", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6012.99951171875, + "y": -3209.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "fb5e1e2a67c14602808358686bb75091" + }, + { + "m_Id": "712da461f71a454db59d349f752d41ee" + }, + { + "m_Id": "b000f852aa984e9dae25b125a4607f4e" + }, + { + "m_Id": "b911c23b90124d15924551e2730501eb" + }, + { + "m_Id": "c49cfb8bb96846dc87ee00c0c041a372" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "f3d31c1f18d8491a8ecf5cbc37e4b7db", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4321.99951171875, + "y": -3246.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ed1d1f1613334c3bb904dd08161cd7e5" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f42ad06b3c6a45d3ab33de904c063412", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f44e4374a48a4996aa60d23d3ae1e9f9", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f48f04ad45d046a8b88e71731ed506e7", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f4ecc442a2d246759f7c2c0412953d28", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a3f8b6e8ae7f48e2989a029904401502" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f5a8bfcec21a4dac9df63993ec53635e", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalTS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "7564379492aa4c5a927ff3501acdc70d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalTS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f6823778a3cf42d5bbe8a83e5f9c9fa3", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f684c5678e9e4f078157a3ab7ef5057b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": { + "x": 3.0, + "y": 2.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "f814deb543c24fbbafbcdb5071d96022", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "abd59150589b436cadf8c9e6f43ccb8e" + }, + { + "m_Id": "7acfafd73b8c4dfab8c55c18a887e087" + }, + { + "m_Id": "928621a3ca2d41c89a10336bbbc81ddc" + }, + { + "m_Id": "b7f9ac55517141868bfb9d2ad6429792" + }, + { + "m_Id": "09b1b86c1c074337a4c439d3a308dd2e" + }, + { + "m_Id": "1f247658c7ba45fb93c41f51e21acb0d" + }, + { + "m_Id": "d30452ac6b244ecca03df4d7b4de9f81" + }, + { + "m_Id": "215b30ae27784ec3a13360a9029af283" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f864c900600e427ba7793f00c715e971", + "m_Id": 0, + "m_DisplayName": "Outline Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fa6de3be9f5b4411b5081b49e645f424", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "faace8101df943d8956faa31728cb004", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5254.99951171875, + "y": -3891.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "77e28f3e930b4c249145630ec961af95" + }, + { + "m_Id": "f2903158b3624759bca1fcd843698078" + }, + { + "m_Id": "30ca940fe2794c949f2a1d4d2caaa446" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "facc84930f544fd7a0205a6176b18ac0", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "fb15d0ba56d54a6192f11e107aeb5fa8", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "fb5e1e2a67c14602808358686bb75091", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "fc2e62201c5847e798fd939314413fcd", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fd0b096ed5b74f9e9ec51327be200731", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "fdb77c3e92ee497b88ca5dc46dc45350", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4208.0, + "y": -2371.0, + "width": 180.0, + "height": 180.0 + } + }, + "m_Slots": [ + { + "m_Id": "4328cdbf78b94c038fd614c59bfe1cac" + }, + { + "m_Id": "04dfcc9ff13a4bf282ed46faec39d15c" + }, + { + "m_Id": "71dd947935b64ce38f0d25406dde447b" + }, + { + "m_Id": "61a6ac5f29344d109411f26850ab0a96" + }, + { + "m_Id": "44806230fa384c1e95f9c5918a14f056" + }, + { + "m_Id": "4eb3c00a1ca44e10be833b7ca61ff059" + }, + { + "m_Id": "57abc172afd449e2a4d567f93432507b" + }, + { + "m_Id": "cda5e3b4c1054bf3a65c0b7ec6bc778a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "fe11fa80cc1847a5a37f6757d521cf25", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ffb07af0bca546d8b9bc439d34aa68f5", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta new file mode 100644 index 0000000..a445e27 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: ca2ed216f98028c4dae6c5224a952b3c +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph new file mode 100644 index 0000000..3118dd0 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph @@ -0,0 +1,11759 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "386c36a1c4c34ea29deb680fb82cfe8b", + "m_Properties": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "ced40c943add479a86f25f7fb5ed59da" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "469965f1c9284b7eb032d415d6295b2c" + } + ], + "m_Nodes": [ + { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + }, + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + } + ], + "m_GroupDatas": [ + { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 5 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 6 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 1 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3749.0 + }, + "m_Blocks": [ + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3480.0 + }, + "m_Blocks": [ + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"fileID\":10210,\"guid\":\"0000000000000000e000000000000000\",\"type\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "TextMeshPro/SRP", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "7cf0e63037a74dc2a9f591225c678ff4" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "007c75c776ac4f1babe9cd7ae1fc4f14", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5722.99951171875, + "y": -3827.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1356dc7cbdfa4199a6535d3bbf4cd536" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.BuiltinData", + "m_ObjectId": "00996039d61e400a9e854ce591ac35a0", + "m_Distortion": false, + "m_DistortionMode": 0, + "m_DistortionDepthTest": true, + "m_AddPrecomputedVelocity": false, + "m_TransparentWritesMotionVec": false, + "m_DepthOffset": false, + "m_ConservativeDepthOffset": false, + "m_TransparencyFog": true, + "m_AlphaTestShadow": false, + "m_BackThenFrontRendering": false, + "m_TransparentDepthPrepass": false, + "m_TransparentDepthPostpass": false, + "m_TransparentPerPixelSorting": false, + "m_SupportLodCrossFade": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "013228b0fdf1424097798f0973a9a4fb", + "m_Title": "Face Texture", + "m_Position": { + "x": -4824.0, + "y": -2949.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "02559cbe5ad441a3904ccb75ded2b2c5", + "m_Id": 5, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "03182b3263304258b265266325c21f65", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "045c4f6b050549c7a0efb208e6349779", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "04dc152dd2ba4d519391577eb1156235", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4534.0, + "y": -2747.0, + "width": 150.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "3d04f5ba6e7b40d281f22eb424145acd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "04dfcc9ff13a4bf282ed46faec39d15c", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "05805bc6fcc941fd889922555c6c86d7", + "m_Guid": { + "m_GuidSerialized": "fe84e680-4cee-4ca5-be86-2e293a9ba093" + }, + "m_Name": "Ambient Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_05805bc6fcc941fd889922555c6c86d7", + "m_OverrideReferenceName": "_Ambient", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "0580d4b7e3a049049569f4508643a724", + "m_Guid": { + "m_GuidSerialized": "eefb88c5-7665-45dc-b3c2-7cf98b9990d6" + }, + "m_Name": "Softness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_D64EC33D", + "m_OverrideReferenceName": "_Softness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "068ae649e00b40e198ec5a30ad741fab", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0699eea947fc426cbfeb8744cf120222", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "07946387933e416db576b677f0711e5f", + "m_Guid": { + "m_GuidSerialized": "21d612fb-8153-41f8-9e2f-9de044c19fbf" + }, + "m_Name": "_FaceTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1A08AD4A", + "m_OverrideReferenceName": "_FaceTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "082e9706dffc4c188270980d4e44ce0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0848ba750e0341198cf0bbd413e0efe4", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "09b1b86c1c074337a4c439d3a308dd2e", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0a67ca5280214bd794dc0ad66b5710a9", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0b57f2d35157477ab2b29a5aac14ae8b", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0ba4932e164847878ddb7b7bcff96985", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0c4dc51f26484c26ad88a3fe4002abcd", + "m_Id": 2, + "m_DisplayName": "Color (1)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "0d6a57754b824f6db9cefa6953bc06a9", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0d7878dd226d4cfb81a991dc312309fc", + "m_Id": 0, + "m_DisplayName": "Underlay Dilate", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "0f7ffb6d2de4447f9736780cbcee8e07", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0fac35636fca4474a6afaefc3c757775", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "105b1ed1aa714e41bbe1ef5472bdb11f", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -4233.0, + "width": 158.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "8a08179f99d649d289b8053d5fa0ad22" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "109f638d1f9b49d4991d6d21a86d4eb7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5098.99951171875, + "y": -3182.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "880bb02c6c6b49b18aa6ebc66dc566a0" + }, + { + "m_Id": "1b9cd8f5f4004e2eaf8afbaab803bc04" + }, + { + "m_Id": "b224a1cf80604103ad085c799995f3c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "10a99c07aad742349d258db16838c129", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1196ae398cc348349ab0c1a23fdab4bd", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1356dc7cbdfa4199a6535d3bbf4cd536", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "14ad19bf20a140dd88d58452d7df688b", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 1.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "150533bad8e2424aaa2c74e253af8592", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4955.0, + "y": -3487.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "72fb5a0d7796446b9e2b929cb32facdc" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "163beb4431c34f538340bc0af0991e6f", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3284.0, + "y": -3516.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c334de01ecd429baa7652fc6002536b" + }, + { + "m_Id": "e2d28f29bbac4983a401574480b5ca28" + }, + { + "m_Id": "6a7af6143e114a538663e71f56731a21" + }, + { + "m_Id": "3e25be96bb3747738c238cf3a741d5df" + }, + { + "m_Id": "4907352322c644ebacdf2ca30f2994fd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "19075add867e4757b9520d18fe8de1d0", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4291.99951171875, + "y": -3197.0, + "width": 124.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c28ee9109014fa086e5de7a3993341d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0580d4b7e3a049049569f4508643a724" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1b9cd8f5f4004e2eaf8afbaab803bc04", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1bdde3efd3b7464b8934c555be0f8a48", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "1be90d4f96a841748b0c95219b12ad27", + "m_Guid": { + "m_GuidSerialized": "4c91c146-43bb-4de8-948a-fbf8b1da10e1" + }, + "m_Name": "Bevel Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_97690701", + "m_OverrideReferenceName": "_BevelOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": -0.5, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "1c4df61c2fea404eb3b87b270d7c59bc", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4311.0, + "y": -3221.0, + "width": 148.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "f864c900600e427ba7793f00c715e971" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1d35fa1fb5004f96a65ace54fbe4f1ad", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1db37082bf844442804487b4944352de", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1df58cfa4dad4c449d01ee1c5ea05f2e", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "1e12726617b24675958e942eb62e4b09", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4772.0, + "y": -4404.0, + "width": 145.00001525878907, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "0848ba750e0341198cf0bbd413e0efe4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1f247658c7ba45fb93c41f51e21acb0d", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1f46181633594ae0a1fb2adb76b42981", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "200245fc8bbe4826b209ab5f7ffe074c", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "204dacb5a95b424facf11cb6f65bd188", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "215a82c127204988b751de7d3a39b955", + "m_Id": 6, + "m_DisplayName": "Outline", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Outline", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "215b30ae27784ec3a13360a9029af283", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "21a7a380e66d42e780e2a2a1baa630d5", + "m_Guid": { + "m_GuidSerialized": "b2d0099f-e605-49f5-9959-e7cacae37aa3" + }, + "m_Name": "Bevel Type", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_21a7a380e66d42e780e2a2a1baa630d5", + "m_OverrideReferenceName": "_BevelType", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e", + "m_Guid": { + "m_GuidSerialized": "cd167d3a-7465-4d5a-86fc-0f22dc0ef908" + }, + "m_Name": "Outline Color 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5550EB71", + "m_OverrideReferenceName": "_OutlineColor1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "232b1aa09e67479abae141d3c76d3c5b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "256d41e89a204d22951450de1c38051d", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "26e48352a08441bfa694dcea54c06e36", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "281bcee4777040f8a31ee0e10344e98d", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "285f6a9863d54ed2a8150727ad749456", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4181.99951171875, + "y": -2415.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "b42e6dbfbc864097af182cbff5c0c1fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDUnlitSubTarget", + "m_ObjectId": "29b1a6d4abc94131be838c0bc77892fc" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.IsFrontFaceNode", + "m_ObjectId": "2a552a0b828f457c911aa19561e410ae", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Is Front Face", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4282.0, + "y": -3681.3330078125, + "width": 121.99999237060547, + "height": 77.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "2ef1d888dc9d49e59d6a6950897ddc93" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "2ac79705aa9e415dbb74ec215233fd1b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Composite (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3350.0, + "y": -3810.0, + "width": 213.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "a75f7ac601c446469802fe7754c1f279" + }, + { + "m_Id": "8c38a5d8327f456e9783740c05382619" + }, + { + "m_Id": "facc84930f544fd7a0205a6176b18ac0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Composite", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2b01ea3023e34c94af1754e4dcea8f2e", + "m_Id": 0, + "m_DisplayName": "Face Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2bf5f2fdd2984599b7323d10cfb1d240", + "m_Id": 1, + "m_DisplayName": "Filter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Filter", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "2c10b97b92c947ceb307a93759c0228b", + "m_Guid": { + "m_GuidSerialized": "6be0b8ff-a766-4c6b-a6e4-3a72758ac95f" + }, + "m_Name": "Bevel Amount", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B01DD93E", + "m_OverrideReferenceName": "_BevelAmount", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.25, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2c7a9460724b47daad8df1be144de7c6", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "2d0a269511e34bd1ba9056d2c939dff2", + "m_Guid": { + "m_GuidSerialized": "edbe73dc-53ab-4bc1-9d64-ab36e0e05f03" + }, + "m_Name": "_FaceUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_3A8E0F13", + "m_OverrideReferenceName": "_FaceUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "2db15d90c2204143b225ec4ef08d0755", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4387.0, + "y": -2405.0, + "width": 163.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "def8e0b9d8384982bc5b4c32d877e458" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "2e4eb1ef08bb44178c82e53872485e0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2ef1d888dc9d49e59d6a6950897ddc93", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 2, + "m_Value": true, + "m_DefaultValue": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.SystemData", + "m_ObjectId": "305e3be306674fcd8bb02273d27ee5b7", + "m_MaterialNeedsUpdateHash": 1, + "m_SurfaceType": 1, + "m_RenderingPass": 4, + "m_BlendMode": 0, + "m_ZTest": 4, + "m_ZWrite": false, + "m_TransparentCullMode": 2, + "m_OpaqueCullMode": 2, + "m_SortPriority": 0, + "m_AlphaTest": true, + "m_TransparentDepthPrepass": false, + "m_TransparentDepthPostpass": false, + "m_SupportLodCrossFade": false, + "m_DoubleSidedMode": 0, + "m_DOTSInstancing": false, + "m_CustomVelocity": false, + "m_Tessellation": false, + "m_TessellationMode": 0, + "m_TessellationFactorMinDistance": 20.0, + "m_TessellationFactorMaxDistance": 50.0, + "m_TessellationFactorTriangleSize": 100.0, + "m_TessellationShapeFactor": 0.75, + "m_TessellationBackFaceCullEpsilon": -0.25, + "m_TessellationMaxDisplacement": 0.009999999776482582, + "m_DebugSymbols": false, + "m_Version": 2, + "inspectorFoldoutMask": 9 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "30ca940fe2794c949f2a1d4d2caaa446", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "319916a5921343f7b7eef0e50dc93def", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "d219977210094c0082c517d8dc00c8bb" + }, + { + "m_Id": "f48f04ad45d046a8b88e71731ed506e7" + }, + { + "m_Id": "e6e80c6b0db545cda26b079a9a78fbb3" + }, + { + "m_Id": "c6bdb985bc16435fa72f5a3c81bb633c" + }, + { + "m_Id": "d1a17e42e7a04dc38984e3c01149445b" + }, + { + "m_Id": "fb15d0ba56d54a6192f11e107aeb5fa8" + }, + { + "m_Id": "c35312edaa2344788b1964ee2f63a236" + }, + { + "m_Id": "c88fcbaeea954a5f9c68c339fa8b604d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "34a67e0fef884f9399e674d9eeaf720c", + "m_Id": 6, + "m_DisplayName": "Color3", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color3", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "34a72a5ebb04402384a4fd3748111a37", + "m_Id": 0, + "m_DisplayName": "Alpha Clip Threshold", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AlphaClipThreshold", + "m_StageCapability": 2, + "m_Value": 0.0010000000474974514, + "m_DefaultValue": 0.5, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3535ae87c6dd4769b52b20d9eca61069", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "35cbea6373dd4e4f8d0fea36e8add392", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "36a0c473c4c04c3a930dd38f3920d410", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "36f1b4d96f2941c39e5cd95d9c1d2ce6", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6008.99951171875, + "y": -3341.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "65b3dc13b2b6484283ffe5abfe87a06a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "373f1de8db6c429c9d46c781f741d7a4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3802c81c3be24823aa1d7c9997a33c29", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "3915c1927ffe49f8967304321cfbe497", + "m_Id": 4, + "m_DisplayName": "Atlas", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Atlas", + "m_StageCapability": 3, + "m_BareResource": true, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "39a382d661e2484da71f04c43f48e55f", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "39f2f84f30304d859fb07569e2695f60", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3423.000244140625, + "y": -3516.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "4b2d9ea03bf64fa19dcae1511d2581da" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "3c50439118b2496f9e390021b0964606", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.AlphaClipThreshold", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3028.0, + "y": -3054.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "34a72a5ebb04402384a4fd3748111a37" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.AlphaClipThreshold" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3d04f5ba6e7b40d281f22eb424145acd", + "m_Id": 0, + "m_DisplayName": "Face Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3db1608e927e4102a3c3a88e9fcab39a", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3dccd64e7f324bc1a75c1479d7a67c51", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "3e231021af7b47ba97f2871e7f25d0fe", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2803.000244140625, + "y": -3520.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "6ccaced3889e4503a9414d808ec33981" + }, + { + "m_Id": "7f3d71a6c96847c099da45f95aafbecb" + }, + { + "m_Id": "d8edec16956c4f15b7d51d6ec10753f4" + }, + { + "m_Id": "39a382d661e2484da71f04c43f48e55f" + }, + { + "m_Id": "8764669016f6442f8152593c18a649d7" + }, + { + "m_Id": "26e48352a08441bfa694dcea54c06e36" + }, + { + "m_Id": "3e94a0d106064bdb864c960512ef4026" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3e25be96bb3747738c238cf3a741d5df", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "3e372195f4bd4845852a37839e5b602d", + "m_Guid": { + "m_GuidSerialized": "60abd046-2a1a-48cd-a0af-2f702f7f53ab" + }, + "m_Name": "_MainTex", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_90CBF488", + "m_OverrideReferenceName": "_MainTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":28684132378477856,\"guid\":\"8f586378b4e144a9851e7b34d9b748ee\",\"type\":2}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "3e94a0d106064bdb864c960512ef4026", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "3ec4797e381747829ef4712c85fcf7a1", + "m_Guid": { + "m_GuidSerialized": "020d65cc-50a8-4b8a-a624-90d7b489f549" + }, + "m_Name": "Specular Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_3ec4797e381747829ef4712c85fcf7a1", + "m_OverrideReferenceName": "_SpecularPower", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 1.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 4.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "3fdf4b7bc5d4426492dcc057603ef4a6", + "m_Guid": { + "m_GuidSerialized": "675d2567-3fca-4da6-9462-dfa4924950f1" + }, + "m_Name": "_OutlineUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_D66D89E6", + "m_OverrideReferenceName": "_OutlineUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "400d0b6c95dd4540ad3da3e8cb7e50b2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "41986ac6400d46709d0ef043a67f6b34", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "41b9b79b3859472882bcea393703eec0", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "424dbeeb009344efa29c304c4979e3d6", + "m_Guid": { + "m_GuidSerialized": "314c37de-c6f2-4463-866d-8588f6fc119e" + }, + "m_Name": "Diffuse Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_424dbeeb009344efa29c304c4979e3d6", + "m_OverrideReferenceName": "_Diffuse", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "42a586e4f6ec40eeaba891b7fd133864", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4934.0, + "y": -4442.99951171875, + "width": 133.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "da7a06d393a44089842070d51d2aa0a6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "42cadae0923e4969b50bbc3f78185934", + "m_Title": "Face + 3 Outlines + Underlay", + "m_Position": { + "x": -5468.0, + "y": -3558.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4328cdbf78b94c038fd614c59bfe1cac", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "44317f2e371447e2a8d894f8a021a235", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Layer1 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4001.0, + "y": -4168.0, + "width": 191.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "10a99c07aad742349d258db16838c129" + }, + { + "m_Id": "b85d677872b44421bf5536f42ba0267c" + }, + { + "m_Id": "75aba700d74d4b2687bf3166cf1da3e2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer1", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "44806230fa384c1e95f9c5918a14f056", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4488af8ff6a7421298a7e827f567263b", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4109.0, + "width": 158.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "66f69ef16eac4eb48357bde804cf3c39" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "4590bfa2a0664b65b6f073bae33a071f", + "m_Id": 0, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_ColorMode": 1, + "m_DefaultColor": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "4648b46ad29a4008a80de4f8a5a5b813", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4613.0, + "y": -2415.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "b2baf44eae52473cb6cda7b1debece01" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "469965f1c9284b7eb032d415d6295b2c", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "ced40c943add479a86f25f7fb5ed59da" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "46fbf3eeb0ea4470869cba7443249295", + "m_Guid": { + "m_GuidSerialized": "be87c5a3-e361-4b95-89c8-911c39a51c0d" + }, + "m_Name": "Outline Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_A0B54237", + "m_OverrideReferenceName": "_OutlineTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "47d020251e9841a5b1f0fd64396026a1", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "48390d02257d41bf98eace1deaa4c539", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "8036d0e6090b456e9b4ea87227868236" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "484b51c50485473b819c4f05087b32d7", + "m_Title": "Underlay", + "m_Position": { + "x": -5253.0, + "y": -4542.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4907352322c644ebacdf2ca30f2994fd", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "49e7c3ad55ce458797f0e60c950cb965", + "m_Guid": { + "m_GuidSerialized": "31b55db9-0da1-4ec4-af2b-d83747ed5bc4" + }, + "m_Name": "Underlay Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_CE9DEDB3", + "m_OverrideReferenceName": "_UnderlayOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4a66dcbe712a4d40bd8f355b834594b5", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "4abff6ff92fa4a05b203f10580988335", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4323.99951171875, + "y": -3498.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "b015d1b7e4134c59baf6851e7649802c" + }, + { + "m_Id": "d9dc4839ee2847999110bdb234d6041a" + }, + { + "m_Id": "91d6a9a5fbc04ea49075cb51835e7264" + }, + { + "m_Id": "f42ad06b3c6a45d3ab33de904c063412" + }, + { + "m_Id": "ed6c215a65584deeaefad1d2c7743044" + }, + { + "m_Id": "edbee7a8952b46529ac5ad0365775774" + }, + { + "m_Id": "70337a74f6ad4b7bb6befc825219bab1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4b2d9ea03bf64fa19dcae1511d2581da", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4bda5c294e1949138d033640e1d385b4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4c28ee9109014fa086e5de7a3993341d", + "m_Id": 0, + "m_DisplayName": "Softness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4c334de01ecd429baa7652fc6002536b", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4d1cb1a475df49f9a148195a65f5453a", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4d9ce48719d143748f9f8e22da6f9ddc", + "m_Id": 5, + "m_DisplayName": "TextureWidth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureWidth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4e64dac49ddc47c3b5b1e27b17a08304", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "4eb3c00a1ca44e10be833b7ca61ff059", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4f194ff591484e908fc2bcdacbcf2570", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4310.0, + "y": -2771.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "2b01ea3023e34c94af1754e4dcea8f2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "509e6f38505b4b0695b263706a55028f", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "51378bae98a94c309785d14cd5cbb453", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "GetSurfaceNormal (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4067.333251953125, + "y": -3881.99951171875, + "width": 263.9999694824219, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "5b0077c23eae443887872f84227deccc" + }, + { + "m_Id": "3915c1927ffe49f8967304321cfbe497" + }, + { + "m_Id": "4d9ce48719d143748f9f8e22da6f9ddc" + }, + { + "m_Id": "ebd6d75abcb84108bcadbfe7ee5f6244" + }, + { + "m_Id": "ef9738ec7e894772a14e9dce441c16c6" + }, + { + "m_Id": "9eeec1a9713045af8845cea263d5ea48" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GetSurfaceNormal", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "51f76f8a53ad43a4ad028426548ce9ba", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "52798bdb86f6400e86489a7a368e9f8b", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6154.99951171875, + "y": -3169.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1df58cfa4dad4c449d01ee1c5ea05f2e" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "53073e5ea924459fa6681a4943e9f947", + "m_Guid": { + "m_GuidSerialized": "5fdac24e-2d58-4471-80ce-79c3ab9a2564" + }, + "m_Name": "Outline Color 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_DBAB5AEC", + "m_OverrideReferenceName": "_OutlineColor2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.009433984756469727, + "g": 0.02534518577158451, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "54d7a93ffec5490aa4591da23a21b693", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "55ffa45ec3654d5e88089fb40d2b0465", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "56c25395796e4d2fbe5c892d428d1620", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5102.99951171875, + "y": -3427.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "9eb8137a6c2e41bbafdc8b0732dd47a3" + }, + { + "m_Id": "36a0c473c4c04c3a930dd38f3920d410" + }, + { + "m_Id": "068ae649e00b40e198ec5a30ad741fab" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "57abc172afd449e2a4d567f93432507b", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "582d6e289dbe4fdca7cf0307273eaa2f", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "59bd90a849624124bae6464ee3669aa6", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4005.999755859375, + "y": -2395.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "2e4eb1ef08bb44178c82e53872485e0f" + }, + { + "m_Id": "8695190a5e614f2d90081871a8a06fc2" + }, + { + "m_Id": "81bdb47901ef48e5a588c6724b1b0142" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "5b0077c23eae443887872f84227deccc", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5b3ff4ee364f4d7a923b530ad60d8762", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5bd258837c514ff7ab0bf7027e762c18", + "m_Guid": { + "m_GuidSerialized": "2d8f3ee9-1307-4b58-a60d-526e86b07109" + }, + "m_Name": "Bevel Roundness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_AB6A015F", + "m_OverrideReferenceName": "_BevelRoundness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5da82bf481f8489ebd05e997f617f51b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": 4.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5e42524569844befad16fda5a94eb9cb", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5fbe253f3e444f2aa8ac717f9c856619", + "m_Guid": { + "m_GuidSerialized": "0a61c93f-6430-4aa6-af07-79bc3b411ccd" + }, + "m_Name": "Bevel Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B50BBFCC", + "m_OverrideReferenceName": "_BevelWidth", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.5, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61133d79a89048c195f54939b2a1d30a", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61a6ac5f29344d109411f26850ab0a96", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6271438664e74b3fbf723bd6a1f50f8b", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "62bc551cea604e88b7858cc37d96a98a", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "636180f6e0504f2baaa5cc086980cb47", + "m_Guid": { + "m_GuidSerialized": "c1223e37-093d-4d5a-b2b0-cd9cc3e4f88e" + }, + "m_Name": "Outline Offset 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_636180f6e0504f2baaa5cc086980cb47", + "m_OverrideReferenceName": "_OutlineOffset1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "63c7cd57fc3c45a9a97b514fdae32693", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5266.99951171875, + "y": -3387.0, + "width": 156.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "c422a9a9ff824176aad2241f58c44d0b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "641eda269d7b4da9acb65f8d50035ea9", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "65b3dc13b2b6484283ffe5abfe87a06a", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "65c8e64a7535466e933eed08a2f77532", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3499.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "256d41e89a204d22951450de1c38051d" + }, + { + "m_Id": "0a67ca5280214bd794dc0ad66b5710a9" + }, + { + "m_Id": "ebbd94a7102a4457a48ac492de3bff14" + }, + { + "m_Id": "6271438664e74b3fbf723bd6a1f50f8b" + }, + { + "m_Id": "c9b722d107ce4cd6a748c883472b9b0f" + }, + { + "m_Id": "74cf69e61bef44589521f1bf2bf3c59a" + }, + { + "m_Id": "6e532f83d1c44e839bcfc5845d3b01d6" + }, + { + "m_Id": "cb5e9f9567e84f8fa5463efc0e256e19" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "66f69ef16eac4eb48357bde804cf3c39", + "m_Id": 0, + "m_DisplayName": "_UnderlayColor", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "67a519f507384ff1861df5d8d5b486be", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4278.0, + "y": -3939.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c3e6d7c20c184bf39fd8822130e693e7" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "68ec7c31365549d6a8ce883edfc02de2", + "m_Id": 4, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6a7af6143e114a538663e71f56731a21", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "6b2f65c1463f4f7bad16c54a95d2fe75", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5101.0, + "y": -3301.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "1d35fa1fb5004f96a65ace54fbe4f1ad" + }, + { + "m_Id": "fa6de3be9f5b4411b5081b49e645f424" + }, + { + "m_Id": "400d0b6c95dd4540ad3da3e8cb7e50b2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6ccaced3889e4503a9414d808ec33981", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6dfc1177dd0541a7a780fbf911ad1956", + "m_Id": 0, + "m_DisplayName": "_OutlineTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e13f3cd573c467a94379f45d96cb690", + "m_Id": 2, + "m_DisplayName": "SSR", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "6e532f83d1c44e839bcfc5845d3b01d6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6e8946a245e842b38231d4a241bfb3ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3026.0, + "y": -3110.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "ef0b93f78372439696f50711eaf57d90" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "6fbdcc5a972b4fa883dc5f21e525a376", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "70337a74f6ad4b7bb6befc825219bab1", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "712da461f71a454db59d349f752d41ee", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "71dd947935b64ce38f0d25406dde447b", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "724e17584e97443e9e285dfa7253c8e3", + "m_Id": 0, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 2, + "m_Value": 0.15000000596046449, + "m_DefaultValue": 1.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "72fb5a0d7796446b9e2b929cb32facdc", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "7444469eb9884253819add9ef96baa25", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4298.0, + "y": -3809.99951171875, + "width": 144.66648864746095, + "height": 129.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "03182b3263304258b265266325c21f65" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "748c31bbcecc4b30bec2e42c0612175b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "74b41464cbed4e9e8e23af5ab9be40cf", + "m_Guid": { + "m_GuidSerialized": "41afbdcb-f3ae-4340-8973-1c1998c992a2" + }, + "m_Name": "Outline Offset 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "74cf69e61bef44589521f1bf2bf3c59a", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "757174b6f25040fdbb20355a21752222", + "m_Id": 0, + "m_DisplayName": "Outline Offset 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "75aba700d74d4b2687bf3166cf1da3e2", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "75c5657544c648058b20cea090f48dbf", + "m_Id": 0, + "m_DisplayName": "_OutlineUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "767769f736d5478cba5f10a415e28e7f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "773b90134e894e429203c0c83e80b9de", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "77e28f3e930b4c249145630ec961af95", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDUnlitData", + "m_ObjectId": "77ebd01f5b3149ad810a5acbffc85921", + "m_EnableShadowMatte": false, + "m_DistortionOnly": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "79147f6986644769b58d9ed64fe771e1", + "m_Id": 0, + "m_DisplayName": "OutlineMode", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7984fd094e1147bdabb4e26fbd3d31c8", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3113.000244140625, + "y": -3468.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "082e9706dffc4c188270980d4e44ce0f" + }, + { + "m_Id": "f2a351a5375c441b8d9ab7e2c9545a77" + }, + { + "m_Id": "41986ac6400d46709d0ef043a67f6b34" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "7a046f410ce64aa88438b0bfd412c045", + "m_Guid": { + "m_GuidSerialized": "d47271f5-5a84-47bf-a09e-c825d2aeb013" + }, + "m_Name": "Outline Color 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_551702C5", + "m_OverrideReferenceName": "_OutlineColor3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "7a0f504e4175406dbd8134250f4e350b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7a80e8839f0e4a1d9a6c0814f8793ee6", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4961.99951171875, + "y": -3452.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "6fbdcc5a972b4fa883dc5f21e525a376" + }, + { + "m_Id": "0ba4932e164847878ddb7b7bcff96985" + }, + { + "m_Id": "9178663316db43d582f1c4a127d307c6" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7acfafd73b8c4dfab8c55c18a887e087", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7b3b88c5975841d6b6d5c3c5515055a0", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "7b8a19bd115e4167a25b59cb3218a817", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "7c27ccb2c2dc4ca59c5438c3358630ca", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDTarget", + "m_ObjectId": "7cf0e63037a74dc2a9f591225c678ff4", + "m_ActiveSubTarget": { + "m_Id": "29b1a6d4abc94131be838c0bc77892fc" + }, + "m_Datas": [ + { + "m_Id": "00996039d61e400a9e854ce591ac35a0" + }, + { + "m_Id": "305e3be306674fcd8bb02273d27ee5b7" + }, + { + "m_Id": "77ebd01f5b3149ad810a5acbffc85921" + } + ], + "m_CustomEditorGUI": "TMPro.EditorUtilities.TMP_SDF_HDRPUnlitShaderGUI", + "m_SupportVFX": false, + "m_SupportLineRendering": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7d7696aa6d184b4fb9c316a9dec37aee", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4959.0, + "y": -3326.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "4d1cb1a475df49f9a148195a65f5453a" + }, + { + "m_Id": "47d020251e9841a5b1f0fd64396026a1" + }, + { + "m_Id": "62bc551cea604e88b7858cc37d96a98a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7d78a616c2754cc28d1f32cf66ade611", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4006.000244140625, + "y": -2795.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "d9bcb754db834583b6518c5ed5152114" + }, + { + "m_Id": "861d4258049a4a3e8164f7297090f88e" + }, + { + "m_Id": "a7c06457d7454693a8bc3dc95257b2c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "7e0fadb2533f496192c1ad3e78642010", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4188.0, + "width": 173.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d48c3871e3064027a10ae9f4babd3be0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f2e6b5f15364ed9835d67d0cf4f8f65", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2586.0, + "y": -3592.0, + "width": 200.0, + "height": 41.0 + } + }, + "m_Slots": [ + { + "m_Id": "85ff8667d72947edada4e9fb4ff60559" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7f3d71a6c96847c099da45f95aafbecb", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "8036d0e6090b456e9b4ea87227868236", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "80e665a5eeb64730a51742f698bf0d48", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "8135ca333f8f4ea78163743e6ec1f55c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3140.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d6a6a119394e4082a11bc024a6e42ef8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "81bdb47901ef48e5a588c6724b1b0142", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "81e8ed0534534674a74263e6161a2a1a", + "m_Guid": { + "m_GuidSerialized": "78aab961-c4a8-41f3-b203-1239c3b33b13" + }, + "m_Name": "Underlay Dilate", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_D48690B9", + "m_OverrideReferenceName": "_UnderlayDilate", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "82af2db1018543d7832af96c1cfc981f", + "m_Guid": { + "m_GuidSerialized": "37906c7b-9a3a-454b-a62a-9aa097e64bde" + }, + "m_Name": "Light Angle", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_82af2db1018543d7832af96c1cfc981f", + "m_OverrideReferenceName": "_LightAngle", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 6.28000020980835 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "82d5443fe54d4a3b9420f8745d00a632", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": 8.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "84dc74cdbd8c45e1b189e4fd9a69942d", + "m_Id": 0, + "m_DisplayName": "Outline Offset 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "85a1ad8e741e41759002e8cdc8cd0b96", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "ScreenSpaceRatio (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5802.0, + "y": -3363.0, + "width": 258.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e13f3cd573c467a94379f45d96cb690" + }, + { + "m_Id": "8e6ed600f6504f4083092f5b511e44c4" + }, + { + "m_Id": "93b161cce4504cb79c97b6d8db178de7" + }, + { + "m_Id": "2bf5f2fdd2984599b7323d10cfb1d240" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ScreenSpaceRatio", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "85b5940eb77e4625812ded7215bab8d7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3096.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ada023d617104472b8ab75a81558c0a1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "85ff8667d72947edada4e9fb4ff60559", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "861d4258049a4a3e8164f7297090f88e", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "867a4ae13c0d4a028c71bc1063824c14", + "m_Guid": { + "m_GuidSerialized": "d483c212-0a30-4f6d-b94d-9abbc83a6522" + }, + "m_Name": "Outline Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_C68C9E14", + "m_OverrideReferenceName": "_IsoPerimeter", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 2, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "8695190a5e614f2d90081871a8a06fc2", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8764669016f6442f8152593c18a649d7", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "880bb02c6c6b49b18aa6ebc66dc566a0", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "88253223d2c34ecfab92b0c344048f94", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "ComputeSDF (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4323.0, + "width": 227.99998474121095, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "c52a1744a9a14989b0ae452ad6de6061" + }, + { + "m_Id": "a03db80c558b4f87a330c5ae0a9443a5" + }, + { + "m_Id": "8f1b1d1e8ff24b3284993e52354e54fa" + }, + { + "m_Id": "5da82bf481f8489ebd05e997f617f51b" + }, + { + "m_Id": "82d5443fe54d4a3b9420f8745d00a632" + }, + { + "m_Id": "61133d79a89048c195f54939b2a1d30a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8a08179f99d649d289b8053d5fa0ad22", + "m_Id": 0, + "m_DisplayName": "Underlay Offset", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8a39319405ad44cb8b7aae71c41dcd01", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8b66f4e6bc9d4662b3218ac33a69839f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8c38a5d8327f456e9783740c05382619", + "m_Id": 3, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8cbd81814903479ea1d3151c1f38183e", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "8cf8aae64c1d443f9303126886b40f17", + "m_Guid": { + "m_GuidSerialized": "8d78c9a5-aaef-41fb-af68-2358e401d7ac" + }, + "m_Name": "_UnderlayColor", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_2F5FE804", + "m_OverrideReferenceName": "_UnderlayColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6ed600f6504f4083092f5b511e44c4", + "m_Id": 0, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "8ed907a2cc7949b68a283ae243ea1977", + "m_Guid": { + "m_GuidSerialized": "36803443-a9bc-4f3c-a4f2-7d66a5417ac1" + }, + "m_Name": "Outline Offset 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8f1b1d1e8ff24b3284993e52354e54fa", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9147636b0cfa466a9b37a013d8f693bf", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5421.99951171875, + "y": -3902.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a4f471e3221c4134b291bd9d2ba22db6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "9178663316db43d582f1c4a127d307c6", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "91890fe48ebe4717aea61ecaf3ad4861", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2983.000244140625, + "y": -3468.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "3dccd64e7f324bc1a75c1479d7a67c51" + }, + { + "m_Id": "e444f2c81d1e48329fa2c91005277e8d" + }, + { + "m_Id": "b2c26292b7434733878a9b042f44de89" + }, + { + "m_Id": "964fea1fd4b24f4daf5bef84c4b45118" + }, + { + "m_Id": "deac82280a2b43078e0e40863e2d974c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "91d6a9a5fbc04ea49075cb51835e7264", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "928621a3ca2d41c89a10336bbbc81ddc", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9327cb5f5e6b46f1bd79f91ef9dca3b7", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "93b161cce4504cb79c97b6d8db178de7", + "m_Id": 3, + "m_DisplayName": "TextureSize", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureSize", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "945b45993dd84a979755b98c48138f72", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "952d0fa5cd744df0b434cd38e9a90b93", + "m_Guid": { + "m_GuidSerialized": "ce395871-ddeb-47c3-a31d-07855800c197" + }, + "m_Name": "_UnderlaySoftness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_F2B9E3EF", + "m_OverrideReferenceName": "_UnderlaySoftness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "95928bcb6a284b8d88105a84c2e1d3ce", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4788.0, + "y": -2591.0, + "width": 155.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d880558893fb442b9320cf55885d1117" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "964fea1fd4b24f4daf5bef84c4b45118", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "98934a69591249d5b8b92b39045359a3", + "m_Title": "Outline1 Texture", + "m_Position": { + "x": -4670.00048828125, + "y": -2474.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "998db5e5901e45b29040eb2099370071", + "m_Guid": { + "m_GuidSerialized": "6f383614-f2ad-4269-be8f-87b0ecb03cf0" + }, + "m_Name": "Bevel Clamp", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_5BD7E808", + "m_OverrideReferenceName": "_BevelClamp", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "9c228fac287d446296b91a4acf5cec59", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3498.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "582d6e289dbe4fdca7cf0307273eaa2f" + }, + { + "m_Id": "1db37082bf844442804487b4944352de" + }, + { + "m_Id": "8b66f4e6bc9d4662b3218ac33a69839f" + }, + { + "m_Id": "4a66dcbe712a4d40bd8f355b834594b5" + }, + { + "m_Id": "a0285c9c381a49cba194709efa0a7c85" + }, + { + "m_Id": "b2728d0dd3ce40678867c94a7d977916" + }, + { + "m_Id": "e141833aa78b4fd59ecad949beb43a78" + }, + { + "m_Id": "51f76f8a53ad43a4ad028426548ce9ba" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9c26fdddba244d36a854298c00473247", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "9d3c3383d5934a17bf9efbb7fd9e9043", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5443.0, + "y": -3315.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "232b1aa09e67479abae141d3c76d3c5b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e6e50a71d9843b49b62ebe1cf7d3d59", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4486.0, + "y": -3865.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "3535ae87c6dd4769b52b20d9eca61069" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e87ce9607e14015a3790c528ca5dfda", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4635.0, + "y": -2239.0, + "width": 167.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "75c5657544c648058b20cea090f48dbf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "9eb8137a6c2e41bbafdc8b0732dd47a3", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "9eeec1a9713045af8845cea263d5ea48", + "m_Id": 6, + "m_DisplayName": "IsFront", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "IsFront", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "9f0de188085746d5a19073da1de85ddb", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4160.0, + "y": -2771.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "7c27ccb2c2dc4ca59c5438c3358630ca" + }, + { + "m_Id": "373f1de8db6c429c9d46c781f741d7a4" + }, + { + "m_Id": "fd0b096ed5b74f9e9ec51327be200731" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9f42c5a9bc2f45baa095a80e7b8b485a", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a0285c9c381a49cba194709efa0a7c85", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a03db80c558b4f87a330c5ae0a9443a5", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a3f8b6e8ae7f48e2989a029904401502", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "a455bd79094c4413a7b7dd80ca8b9368", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4606.99951171875, + "y": -2689.0, + "width": 221.99998474121095, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "dcd51c93d3b64f05a938b3334f343654" + }, + { + "m_Id": "2c7a9460724b47daad8df1be144de7c6" + }, + { + "m_Id": "55ffa45ec3654d5e88089fb40d2b0465" + }, + { + "m_Id": "e495a9f7a11f4eb89334e83be154ceb9" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateShaderProperty", + "m_ObjectId": "a4ad98d8828c424384229c344ebe2ed0", + "m_Guid": { + "m_GuidSerialized": "f98fc1a2-bb81-4bd1-a207-23d3a90d518e" + }, + "m_Name": "SamplerState", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "SamplerState_a4ad98d8828c424384229c344ebe2ed0", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": false, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_filter": 0, + "m_wrap": 1, + "m_anisotropic": 0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a4f471e3221c4134b291bd9d2ba22db6", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "a535f3bcbeb14622bb177eb6f46e76f4", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4645.00048828125, + "y": -2285.0, + "width": 177.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "6dfc1177dd0541a7a780fbf911ad1956" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "a6bbb32e8d884be9bb36db91fe4b81b1", + "m_Guid": { + "m_GuidSerialized": "6aa76edf-7b80-46ac-add4-406cf1d85493" + }, + "m_Name": "_GradientScale", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_EAE27356", + "m_OverrideReferenceName": "_GradientScale", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 10.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "a6c38edd2e8743a9b057ba8452b9f129", + "m_Guid": { + "m_GuidSerialized": "9fc942ee-4a1d-4ced-a5a6-81893e3ddb63" + }, + "m_Name": "Light Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_a6c38edd2e8743a9b057ba8452b9f129", + "m_OverrideReferenceName": "_SpecularColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "a75f7ac601c446469802fe7754c1f279", + "m_Id": 0, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a7942746b5564dc7bbbae1deb2403022", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "a7c06457d7454693a8bc3dc95257b2c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa2794b8f0e24bf281d22e0fef0647be", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "aa3e347d733e48f7b65d8a8847370eec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "EvaluateLight (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3631.0, + "y": -3810.0, + "width": 230.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "0699eea947fc426cbfeb8744cf120222" + }, + { + "m_Id": "0c4dc51f26484c26ad88a3fe4002abcd" + }, + { + "m_Id": "d5173cc3c6cd4f1998550f3187a3e9c8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "EvaluateLight", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aa87c72ac0e64469acc34f936f00b3d0", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4225.0, + "width": 193.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "0d7878dd226d4cfb81a991dc312309fc" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "abd59150589b436cadf8c9e6f43ccb8e", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "aca823a8188948c782eddaf0f45e1868", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalOS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2542.0, + "y": -3404.000244140625, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "e386b183a18245a796b024022f7f3074" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalOS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "acd0cd5a177f4a97bf23db7219305e3f", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4348.0, + "y": -3905.99951171875, + "width": 185.33299255371095, + "height": 101.33324432373047 + } + }, + "m_Slots": [ + { + "m_Id": "945b45993dd84a979755b98c48138f72" + }, + { + "m_Id": "e51a636b2621440eb94cc802c1cf4bfc" + }, + { + "m_Id": "1bdde3efd3b7464b8934c555be0f8a48" + }, + { + "m_Id": "f1fb18f75405424884a776bfd24e79e9" + }, + { + "m_Id": "9f42c5a9bc2f45baa095a80e7b8b485a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ada023d617104472b8ab75a81558c0a1", + "m_Id": 0, + "m_DisplayName": "Outline Color 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aef5c44f84e04c3185e0b93e95e34204", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5264.99951171875, + "y": -3142.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "84dc74cdbd8c45e1b189e4fd9a69942d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b000f852aa984e9dae25b125a4607f4e", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b015d1b7e4134c59baf6851e7649802c", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "b0b352c4503a43d083a64e57352b29a0", + "m_Guid": { + "m_GuidSerialized": "01cfcc78-60aa-4f71-a1e3-8d8df6dae253" + }, + "m_Name": "Reflectivity Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_b0b352c4503a43d083a64e57352b29a0", + "m_OverrideReferenceName": "_Reflectivity", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 5.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 5.0, + "y": 15.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "b1188549725543d485436c2e921ffbb2", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4146.0, + "y": -2869.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "281bcee4777040f8a31ee0e10344e98d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "b163c9f1666644b0bba62cf0e12df7bc", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4367.0, + "y": -2713.0, + "width": 180.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "cce40479b6284b6fa3174db9f09d0ac9" + }, + { + "m_Id": "80e665a5eeb64730a51742f698bf0d48" + }, + { + "m_Id": "1f46181633594ae0a1fb2adb76b42981" + }, + { + "m_Id": "8cbd81814903479ea1d3151c1f38183e" + }, + { + "m_Id": "cfaf3f3a5a1146e194cddad30c95aada" + }, + { + "m_Id": "b43489e37a5c4df88f15844292a55ec7" + }, + { + "m_Id": "cd7281fb41aa4e61ac0fdf71d4f4bd46" + }, + { + "m_Id": "f01d52cdcb1647aab35782b4af535efd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 1, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "b224a1cf80604103ad085c799995f3c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b2728d0dd3ce40678867c94a7d977916", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b2baf44eae52473cb6cda7b1debece01", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b2c26292b7434733878a9b042f44de89", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b42e6dbfbc864097af182cbff5c0c1fb", + "m_Id": 0, + "m_DisplayName": "Outline Color 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b43489e37a5c4df88f15844292a55ec7", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "b4a40cb6acd441acb83cfe0240bf910d", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4750.99951171875, + "y": -4274.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d0b10e52e21941b183f5f635894c76c8" + }, + { + "m_Id": "0d6a57754b824f6db9cefa6953bc06a9" + }, + { + "m_Id": "773b90134e894e429203c0c83e80b9de" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "b571db753a1948d5a6f1de4e7d0c7238", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5581.99951171875, + "y": -3867.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "5b3ff4ee364f4d7a923b530ad60d8762" + }, + { + "m_Id": "c183b5bd9bbe45089f93996e73110918" + }, + { + "m_Id": "1196ae398cc348349ab0c1a23fdab4bd" + }, + { + "m_Id": "9327cb5f5e6b46f1bd79f91ef9dca3b7" + }, + { + "m_Id": "d804b5a6c657409196addf2b39199a4f" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b691728a389a417d9b4f2d02541209c2", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b7f9ac55517141868bfb9d2ad6429792", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b85d677872b44421bf5536f42ba0267c", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "bc9afcb18afa4ccc82d2cdc34d3f4641", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -5392.0, + "y": -3867.0, + "width": 125.99999237060547, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "5e42524569844befad16fda5a94eb9cb" + }, + { + "m_Id": "54d7a93ffec5490aa4591da23a21b693" + }, + { + "m_Id": "aa2794b8f0e24bf281d22e0fef0647be" + }, + { + "m_Id": "200245fc8bbe4826b209ab5f7ffe074c" + }, + { + "m_Id": "fc2e62201c5847e798fd939314413fcd" + }, + { + "m_Id": "fe11fa80cc1847a5a37f6757d521cf25" + }, + { + "m_Id": "de0c6f7f7af94defa6c3dbc6433de9d4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c183b5bd9bbe45089f93996e73110918", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "c234e5216678436195ee1a5914bc79da", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4446.0, + "y": -2347.0, + "width": 222.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "f68d9dee5cbc43cdb355d8fadae602d3" + }, + { + "m_Id": "3db1608e927e4102a3c3a88e9fcab39a" + }, + { + "m_Id": "0f7ffb6d2de4447f9736780cbcee8e07" + }, + { + "m_Id": "d4954b7bbbb0412cbc997bcbe7dfa808" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "c35312edaa2344788b1964ee2f63a236", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "c3e6d7c20c184bf39fd8822130e693e7", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "c422a9a9ff824176aad2241f58c44d0b", + "m_Id": 0, + "m_DisplayName": "Outline Offset 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "c478c32c45884c57a62f7b2aa8ddc3b0", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c52a1744a9a14989b0ae452ad6de6061", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c6bdb985bc16435fa72f5a3c81bb633c", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c7d4094601ac4bc1aead609c72b1f1c1", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c7ddee91dc5b48dc828309c77fdb0b88", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4266.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a7942746b5564dc7bbbae1deb2403022" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "c88fcbaeea954a5f9c68c339fa8b604d", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c9b722d107ce4cd6a748c883472b9b0f", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c9d7f0dbae7d422985a1cc87c025e76b", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4315.0, + "y": -3165.0, + "width": 144.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "79147f6986644769b58d9ed64fe771e1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "c9ec735d1a1046769e5601b2c97c849a", + "m_Guid": { + "m_GuidSerialized": "281a9526-c332-4471-a44e-ece4a1e95ef6" + }, + "m_Name": "Face Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_75569DEA", + "m_OverrideReferenceName": "_FaceTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ca2a1083dc014f39ab8af0cdf140866b", + "m_Id": 0, + "m_DisplayName": "_FaceTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "cb3c0c3f08654b068bea44c4ffb15f4a", + "m_Guid": { + "m_GuidSerialized": "21009d12-8d94-4273-b0d0-a8ee0608ddcf" + }, + "m_Name": "OutlineMode", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_cb3c0c3f08654b068bea44c4ffb15f4a", + "m_OverrideReferenceName": "_OutlineMode", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cb5e9f9567e84f8fa5463efc0e256e19", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "cb7117ecb1d047a8b2cb00ed552cb181", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Alpha", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3032.66650390625, + "y": -3029.33349609375, + "width": 200.0, + "height": 41.33349609375 + } + }, + "m_Slots": [ + { + "m_Id": "724e17584e97443e9e285dfa7253c8e3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Alpha" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cc88101667c9488f9c5a716e851c1b21", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cce40479b6284b6fa3174db9f09d0ac9", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "cd7281fb41aa4e61ac0fdf71d4f4bd46", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cda5e3b4c1054bf3a65c0b7ec6bc778a", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "cdddee3a537c464697357f11b966f9b8", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4420.0, + "y": -4483.0, + "width": 156.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "41b9b79b3859472882bcea393703eec0" + }, + { + "m_Id": "c7d4094601ac4bc1aead609c72b1f1c1" + }, + { + "m_Id": "767769f736d5478cba5f10a415e28e7f" + }, + { + "m_Id": "b691728a389a417d9b4f2d02541209c2" + }, + { + "m_Id": "045c4f6b050549c7a0efb208e6349779" + }, + { + "m_Id": "509e6f38505b4b0695b263706a55028f" + }, + { + "m_Id": "204dacb5a95b424facf11cb6f65bd188" + }, + { + "m_Id": "35cbea6373dd4e4f8d0fea36e8add392" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "ced40c943add479a86f25f7fb5ed59da", + "m_Guid": { + "m_GuidSerialized": "af17e4ab-54fe-4482-a9c5-4e4bc9076517" + }, + "m_Name": "_ScaleRatioA", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "_ScaleRatioA", + "m_DefaultReferenceName": "_ScaleRatioA", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "cfaf3f3a5a1146e194cddad30c95aada", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d0a791a544614667962a9a9a9ce0c68a", + "m_Title": "Screen Space Ratio", + "m_Position": { + "x": -6179.99951171875, + "y": -3422.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d0b10e52e21941b183f5f635894c76c8", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d1a17e42e7a04dc38984e3c01149445b", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d219977210094c0082c517d8dc00c8bb", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d258902c6ec74942afdb9ebf8c1d07f8", + "m_Title": "Generate Normal", + "m_Position": { + "x": -4511.33349609375, + "y": -3999.3330078125 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "d30452ac6b244ecca03df4d7b4de9f81", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d48c3871e3064027a10ae9f4babd3be0", + "m_Id": 0, + "m_DisplayName": "_UnderlaySoftness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d4954b7bbbb0412cbc997bcbe7dfa808", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "d4df208fc23b42f2b52364124f1b661c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5268.0, + "y": -3261.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "757174b6f25040fdbb20355a21752222" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "d5173cc3c6cd4f1998550f3187a3e9c8", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d6a6a119394e4082a11bc024a6e42ef8", + "m_Id": 0, + "m_DisplayName": "Outline Color 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d804b5a6c657409196addf2b39199a4f", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d880558893fb442b9320cf55885d1117", + "m_Id": 0, + "m_DisplayName": "_FaceUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d8edec16956c4f15b7d51d6ec10753f4", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d9bcb754db834583b6518c5ed5152114", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d9dc4839ee2847999110bdb234d6041a", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "da7a06d393a44089842070d51d2aa0a6", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "daaf032a109749a88c9b8ff8e1f8b541", + "m_Title": "Offset Scale", + "m_Position": { + "x": -5747.99951171875, + "y": -3961.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "dbcb748279484a4590e53518c49122b8", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4778.0, + "y": -2771.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "7a0f504e4175406dbd8134250f4e350b" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "dc75c4e3a1bc4bb0a128086c2b0679a5", + "m_Guid": { + "m_GuidSerialized": "85cd941f-2fd2-43a3-b0fa-9f728bfb4220" + }, + "m_Name": "Face Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_99AFBB3D", + "m_OverrideReferenceName": "_FaceColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "dcd51c93d3b64f05a938b3334f343654", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "de0c6f7f7af94defa6c3dbc6433de9d4", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "deac82280a2b43078e0e40863e2d974c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "def8e0b9d8384982bc5b4c32d877e458", + "m_Id": 0, + "m_DisplayName": "Outline Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "dff7a66b353a4023b29c9d937da77960", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4602.0, + "y": -4298.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7b8a19bd115e4167a25b59cb3218a817" + }, + { + "m_Id": "0b57f2d35157477ab2b29a5aac14ae8b" + }, + { + "m_Id": "e9e06fcb161e44ba8cc9f6f60264df78" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "e141833aa78b4fd59ecad949beb43a78", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e2d28f29bbac4983a401574480b5ca28", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "e386b183a18245a796b024022f7f3074", + "m_Id": 0, + "m_DisplayName": "Normal (Object Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalOS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e444f2c81d1e48329fa2c91005277e8d", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "e495a9f7a11f4eb89334e83be154ceb9", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e51a636b2621440eb94cc802c1cf4bfc", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "e591df3a1eb94e259b762f2830b407e2", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Emission", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "4590bfa2a0664b65b6f073bae33a071f" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Emission" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e6e80c6b0db545cda26b079a9a78fbb3", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "e818605f8f5a4f01bf61caaa33693581", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "ComputeSDF44 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4144.0, + "y": -3369.0, + "width": 244.0, + "height": 214.0 + } + }, + "m_Slots": [ + { + "m_Id": "641eda269d7b4da9acb65f8d50035ea9" + }, + { + "m_Id": "f6823778a3cf42d5bbe8a83e5f9c9fa3" + }, + { + "m_Id": "9c26fdddba244d36a854298c00473247" + }, + { + "m_Id": "f684c5678e9e4f078157a3ab7ef5057b" + }, + { + "m_Id": "14ad19bf20a140dd88d58452d7df688b" + }, + { + "m_Id": "215a82c127204988b751de7d3a39b955" + }, + { + "m_Id": "c478c32c45884c57a62f7b2aa8ddc3b0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF44", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "e9e06fcb161e44ba8cc9f6f60264df78", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebbd94a7102a4457a48ac492de3bff14", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebd6d75abcb84108bcadbfe7ee5f6244", + "m_Id": 7, + "m_DisplayName": "TextureHeight", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureHeight", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "ec184d6d9fb2494897774c9e7d279e6d", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4799.0, + "y": -2625.0, + "width": 165.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ca2a1083dc014f39ab8af0cdf140866b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "07946387933e416db576b677f0711e5f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "ec1f2e8bc9fd4ae38b133c60ee6c49b8", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4957.99951171875, + "y": -3204.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "748c31bbcecc4b30bec2e42c0612175b" + }, + { + "m_Id": "4bda5c294e1949138d033640e1d385b4" + }, + { + "m_Id": "4e64dac49ddc47c3b5b1e27b17a08304" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "ec79eb447dfd47a9b3380344c6a60f43", + "m_Guid": { + "m_GuidSerialized": "54c77f8b-0534-4b35-a3f0-83ab2ebe6c1f" + }, + "m_Name": "_OutlineTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1774DE83", + "m_OverrideReferenceName": "_OutlineTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "ecf16c34d46f4502ac601f0c38c7576b", + "m_Title": "Vertex Color", + "m_Position": { + "x": -3448.000244140625, + "y": -3579.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ed1d1f1613334c3bb904dd08161cd7e5", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ed6c215a65584deeaefad1d2c7743044", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "edbee7a8952b46529ac5ad0365775774", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "ef0b93f78372439696f50711eaf57d90", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.7353569269180298, + "y": 0.7353569269180298, + "z": 0.7353569269180298 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ef9738ec7e894772a14e9dce441c16c6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "f01d52cdcb1647aab35782b4af535efd", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f1fb18f75405424884a776bfd24e79e9", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "f23a8b2b7c85478388ff7a8c8a6de740", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Layer4 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3849.999755859375, + "y": -3286.0, + "width": 193.0, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "0fac35636fca4474a6afaefc3c757775" + }, + { + "m_Id": "cc88101667c9488f9c5a716e851c1b21" + }, + { + "m_Id": "68ec7c31365549d6a8ce883edfc02de2" + }, + { + "m_Id": "02559cbe5ad441a3904ccb75ded2b2c5" + }, + { + "m_Id": "34a67e0fef884f9399e674d9eeaf720c" + }, + { + "m_Id": "3802c81c3be24823aa1d7c9997a33c29" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer4", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "f2903158b3624759bca1fcd843698078", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "f2a351a5375c441b8d9ab7e2c9545a77", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "f383b24f0bc6434dafe44b3e3d338a63", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6012.99951171875, + "y": -3209.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "fb5e1e2a67c14602808358686bb75091" + }, + { + "m_Id": "712da461f71a454db59d349f752d41ee" + }, + { + "m_Id": "b000f852aa984e9dae25b125a4607f4e" + }, + { + "m_Id": "7b3b88c5975841d6b6d5c3c5515055a0" + }, + { + "m_Id": "8a39319405ad44cb8b7aae71c41dcd01" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "f3d31c1f18d8491a8ecf5cbc37e4b7db", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4321.99951171875, + "y": -3246.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ed1d1f1613334c3bb904dd08161cd7e5" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f42ad06b3c6a45d3ab33de904c063412", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f48f04ad45d046a8b88e71731ed506e7", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f4ecc442a2d246759f7c2c0412953d28", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a3f8b6e8ae7f48e2989a029904401502" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f6823778a3cf42d5bbe8a83e5f9c9fa3", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f684c5678e9e4f078157a3ab7ef5057b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": { + "x": 3.0, + "y": 2.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "f68d9dee5cbc43cdb355d8fadae602d3", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "f814deb543c24fbbafbcdb5071d96022", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "abd59150589b436cadf8c9e6f43ccb8e" + }, + { + "m_Id": "7acfafd73b8c4dfab8c55c18a887e087" + }, + { + "m_Id": "928621a3ca2d41c89a10336bbbc81ddc" + }, + { + "m_Id": "b7f9ac55517141868bfb9d2ad6429792" + }, + { + "m_Id": "09b1b86c1c074337a4c439d3a308dd2e" + }, + { + "m_Id": "1f247658c7ba45fb93c41f51e21acb0d" + }, + { + "m_Id": "d30452ac6b244ecca03df4d7b4de9f81" + }, + { + "m_Id": "215b30ae27784ec3a13360a9029af283" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f864c900600e427ba7793f00c715e971", + "m_Id": 0, + "m_DisplayName": "Outline Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fa6de3be9f5b4411b5081b49e645f424", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "faace8101df943d8956faa31728cb004", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5254.99951171875, + "y": -3891.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "77e28f3e930b4c249145630ec961af95" + }, + { + "m_Id": "f2903158b3624759bca1fcd843698078" + }, + { + "m_Id": "30ca940fe2794c949f2a1d4d2caaa446" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "facc84930f544fd7a0205a6176b18ac0", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "fb15d0ba56d54a6192f11e107aeb5fa8", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "fb5e1e2a67c14602808358686bb75091", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "fc2e62201c5847e798fd939314413fcd", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fd0b096ed5b74f9e9ec51327be200731", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "fdb77c3e92ee497b88ca5dc46dc45350", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4208.0, + "y": -2371.0, + "width": 180.0, + "height": 180.0 + } + }, + "m_Slots": [ + { + "m_Id": "4328cdbf78b94c038fd614c59bfe1cac" + }, + { + "m_Id": "04dfcc9ff13a4bf282ed46faec39d15c" + }, + { + "m_Id": "71dd947935b64ce38f0d25406dde447b" + }, + { + "m_Id": "61a6ac5f29344d109411f26850ab0a96" + }, + { + "m_Id": "44806230fa384c1e95f9c5918a14f056" + }, + { + "m_Id": "4eb3c00a1ca44e10be833b7ca61ff059" + }, + { + "m_Id": "57abc172afd449e2a4d567f93432507b" + }, + { + "m_Id": "cda5e3b4c1054bf3a65c0b7ec6bc778a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "fe11fa80cc1847a5a37f6757d521cf25", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta new file mode 100644 index 0000000..a2f732a --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: f63d574838ccfb44f84acc05fed0af48 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader new file mode 100644 index 0000000..603df2c --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader @@ -0,0 +1,258 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field - Masking" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + _MaskTex ("Mask Texture", 2D) = "white" {} + _MaskInverse ("Inverse", float) = 0 + _MaskEdgeColor ("Edge Color", Color) = (1,1,1,1) + _MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01 + _MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t + { + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t + { + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + float _MaskWipeControl; + float _MaskEdgeSoftness; + fixed4 _MaskEdgeColor; + bool _MaskInverse; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + + pixel_t VertShader(vertex_t input) + { + float bold = step(input.texcoord0.w, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + + // Structure for pixel shader + pixel_t output = { + vPosition, + faceColor, + outlineColor, + float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y), + half4(scale, bias - outline, bias + outline, bias), + half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)), + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4(input.texcoord0 + layerOffset, input.color.a, 0), + half2(layerScale, layerBias), + #endif + }; + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + //#if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + //#endif + + float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a); + float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl; + a = saturate(t / _MaskEdgeSoftness); + c.rgb = lerp(_MaskEdgeColor.rgb*c.a, c.rgb, a); + c *= a; + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader.meta new file mode 100644 index 0000000..3cbdbbb --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bc1ede39bf3643ee8e493720e4259791 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader new file mode 100644 index 0000000..3edca76 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader @@ -0,0 +1,252 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field Overlay" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Overlay" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest Always + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t + { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t + { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord0.w, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Populate structure for pixel shader + output.vertex = vPosition; + output.faceColor = faceColor; + output.outlineColor = outlineColor; + output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); + output.param = half4(scale, bias - outline, bias + outline, bias); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0); + output.underlayParam = half2(layerScale, layerBias); + #endif + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader.meta new file mode 100644 index 0000000..e6b149e --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a02a7d8c237544f1962732b55a9aebf1 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader new file mode 100644 index 0000000..43b317d --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader @@ -0,0 +1,106 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field SSD" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + _MaskTex ("Mask Texture", 2D) = "white" {} + _MaskInverse ("Inverse", float) = 0 + _MaskEdgeColor ("Edge Color", Color) = (1,1,1,1) + _MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01 + _MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + #include "TMPro_Mobile.cginc" + + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader.meta new file mode 100644 index 0000000..9b84c13 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c8d12adcee749c344b8117cf7c7eb912 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader new file mode 100644 index 0000000..2c8e8da --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader @@ -0,0 +1,389 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field - 2 Pass" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + // Draw Outline and Underlay + Name "Outline" + + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + const float bold = step(input.texcoord0.w, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + const float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + //outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, outline * 2))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Populate structure for pixel shader + output.vertex = vPosition; + output.faceColor = faceColor; + output.outlineColor = outlineColor; + output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); + output.param = half4(scale, bias - outline, bias + outline, bias); + + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0); + output.underlayParam = half2(layerScale, layerBias); + #endif + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = half4(0, 0, 0, 0); + + #if OUTLINE_ON + c = input.outlineColor * saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } + + + // Draw face + Name "Face" + + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half2 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + }; + + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + const float bold = step(input.texcoord0.w, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + float opacity = input.color.a; + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Populate structure for pixel shader + output.vertex = vPosition; + output.faceColor = faceColor; + output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); + output.param = half2(scale, bias); + + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.y); + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } + +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader.meta new file mode 100644 index 0000000..75bd98d --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0178fcb869bafef4690d177d31d17db8 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader new file mode 100644 index 0000000..b899d6e --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader @@ -0,0 +1,250 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma enable_d3d11_debug_symbols + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord0.w, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Populate structure for pixel shader + output.vertex = vPosition; + output.faceColor = faceColor; + output.outlineColor = outlineColor; + output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); + output.param = half4(scale, bias - outline, bias + outline, bias); + + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0); + output.underlayParam = half2(layerScale, layerBias); + #endif + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader.meta new file mode 100644 index 0000000..2ac6e76 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fe393ace9b354375a9cb14cdbbc28be4 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader new file mode 100644 index 0000000..68d0dfa --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader @@ -0,0 +1,139 @@ +// Simplified version of the SDF Surface shader : +// - No support for Bevel, Bump or envmap +// - Diffuse only lighting +// - Fully supports only 1 directional light. Other lights can affect it, but it will be per-vertex/SH. + +Shader "TextMeshPro/Mobile/Distance Field (Surface)" { + +Properties { + _FaceTex ("Fill Texture", 2D) = "white" {} + _FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + // Should not be directly exposed to the user + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _CullMode ("Cull Mode", Float) = 0 + //_MaskCoord ("Mask Coords", vector) = (0,0,0,0) + //_MaskSoftness ("Mask Softness", float) = 0 +} + +SubShader { + + Tags { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + LOD 300 + Cull [_CullMode] + + CGPROGRAM + #pragma surface PixShader Lambert alpha:blend vertex:VertShader noforwardadd nolightmap nodirlightmap + #pragma target 3.0 + #pragma shader_feature __ GLOW_ON + + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + half _FaceShininess; + half _OutlineShininess; + + struct Input + { + fixed4 color : COLOR; + float2 uv_MainTex; + float2 uv2_FaceTex; + float2 uv2_OutlineTex; + float2 param; // Weight, Scale + float3 viewDirEnv; + }; + + #include "TMPro_Surface.cginc" + + ENDCG + + // Pass to render object as a shadow caster + Pass + { + Name "Caster" + Tags { "LightMode" = "ShadowCaster" } + Offset 1, 1 + + Fog {Mode Off} + ZWrite On ZTest LEqual Cull Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #include "UnityCG.cginc" + + struct v2f + { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + float2 uv2 : TEXCOORD3; + float alphaClip : TEXCOORD2; + }; + + uniform float4 _MainTex_ST; + uniform float4 _OutlineTex_ST; + float _OutlineWidth; + float _FaceDilate; + float _ScaleRatioA; + + v2f vert( appdata_base v ) + { + v2f o; + TRANSFER_SHADOW_CASTER(o) + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + o.uv2 = TRANSFORM_TEX(v.texcoord, _OutlineTex); + o.alphaClip = o.alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _FaceDilate * _ScaleRatioA) / 2; + return o; + } + + uniform sampler2D _MainTex; + + float4 frag(v2f i) : COLOR + { + fixed4 texcol = tex2D(_MainTex, i.uv).a; + clip(texcol.a - i.alphaClip); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader.meta new file mode 100644 index 0000000..bff8b7a --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 85187c2149c549c5b33f0cdb02836b17 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader new file mode 100644 index 0000000..281e60d --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader @@ -0,0 +1,159 @@ +Shader "TextMeshPro/Distance Field (Surface)" { + +Properties { + _FaceTex ("Fill Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + _FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _BumpMap ("Normalmap", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0.5 + _BumpFace ("Bump Face", Range(0,1)) = 0.5 + + _ReflectFaceColor ("Face Color", Color) = (0,0,0,1) + _ReflectOutlineColor ("Outline Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + _SpecColor ("Specular Color", Color) = (0,0,0,1) + + _FaceShininess ("Face Shininess", Range(0,1)) = 0 + _OutlineShininess ("Outline Shininess", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + // Should not be directly exposed to the user + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _CullMode ("Cull Mode", Float) = 0 + //_MaskCoord ("Mask Coords", vector) = (0,0,0,0) + //_MaskSoftness ("Mask Softness", float) = 0 +} + +SubShader { + + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + + LOD 300 + Cull [_CullMode] + + CGPROGRAM + #pragma surface PixShader BlinnPhong alpha:blend vertex:VertShader nolightmap nodirlightmap + #pragma target 3.0 + #pragma shader_feature __ GLOW_ON + #pragma glsl + + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + half _FaceShininess; + half _OutlineShininess; + + struct Input + { + fixed4 color : COLOR; + float2 uv_MainTex; + float2 uv2_FaceTex; + float2 uv2_OutlineTex; + float2 param; // Weight, Scale + float3 viewDirEnv; + }; + + + #define BEVEL_ON 1 + #include "TMPro_Surface.cginc" + + ENDCG + + // Pass to render object as a shadow caster + Pass + { + Name "Caster" + Tags { "LightMode" = "ShadowCaster" } + Offset 1, 1 + + Fog {Mode Off} + ZWrite On + ZTest LEqual + Cull Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #include "UnityCG.cginc" + + struct v2f + { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + float2 uv2 : TEXCOORD3; + float alphaClip : TEXCOORD2; + }; + + uniform float4 _MainTex_ST; + uniform float4 _OutlineTex_ST; + float _OutlineWidth; + float _FaceDilate; + float _ScaleRatioA; + + v2f vert( appdata_base v ) + { + v2f o; + TRANSFER_SHADOW_CASTER(o) + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + o.uv2 = TRANSFORM_TEX(v.texcoord, _OutlineTex); + o.alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _FaceDilate * _ScaleRatioA) / 2; + return o; + } + + uniform sampler2D _MainTex; + + float4 frag(v2f i) : COLOR + { + fixed4 texcol = tex2D(_MainTex, i.uv).a; + clip(texcol.a - i.alphaClip); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader.meta new file mode 100644 index 0000000..26e814c --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f7ada0af4f174f0694ca6a487b8f543d +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph new file mode 100644 index 0000000..7922d39 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph @@ -0,0 +1,11932 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "386c36a1c4c34ea29deb680fb82cfe8b", + "m_Properties": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "59a09f50a7ca4cd3a0d248a0f3730b6a" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "7c73ccc923e744b98f19148b971a6090" + } + ], + "m_Nodes": [ + { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + }, + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + { + "m_Id": "86e21b7b6b7a44238607e41b8a9fb9a4" + }, + { + "m_Id": "0c10df95ee1d4b0a8a00558af49ec45f" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + }, + { + "m_Id": "83c51d5b2f7b4eb785248f419181cb87" + }, + { + "m_Id": "ad3e1d26f4404555a8dd29223caaf1ef" + } + ], + "m_GroupDatas": [ + { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 5 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 6 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 1 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3749.0 + }, + "m_Blocks": [ + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3480.0 + }, + "m_Blocks": [ + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "86e21b7b6b7a44238607e41b8a9fb9a4" + }, + { + "m_Id": "0c10df95ee1d4b0a8a00558af49ec45f" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + }, + { + "m_Id": "83c51d5b2f7b4eb785248f419181cb87" + }, + { + "m_Id": "ad3e1d26f4404555a8dd29223caaf1ef" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"fileID\":10210,\"guid\":\"0000000000000000e000000000000000\",\"type\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "TextMeshPro/SRP", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "94300469581b4924ac7dda496811d45d" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "007c75c776ac4f1babe9cd7ae1fc4f14", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5722.99951171875, + "y": -3827.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1356dc7cbdfa4199a6535d3bbf4cd536" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "013228b0fdf1424097798f0973a9a4fb", + "m_Title": "Face Texture", + "m_Position": { + "x": -4813.0, + "y": -2949.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "02559cbe5ad441a3904ccb75ded2b2c5", + "m_Id": 5, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "03182b3263304258b265266325c21f65", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "045c4f6b050549c7a0efb208e6349779", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "04dc152dd2ba4d519391577eb1156235", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4536.00048828125, + "y": -2723.000244140625, + "width": 151.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "3d04f5ba6e7b40d281f22eb424145acd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "04dfcc9ff13a4bf282ed46faec39d15c", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "05805bc6fcc941fd889922555c6c86d7", + "m_Guid": { + "m_GuidSerialized": "fe84e680-4cee-4ca5-be86-2e293a9ba093" + }, + "m_Name": "Ambient Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_05805bc6fcc941fd889922555c6c86d7", + "m_OverrideReferenceName": "_Ambient", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "0580d4b7e3a049049569f4508643a724", + "m_Guid": { + "m_GuidSerialized": "eefb88c5-7665-45dc-b3c2-7cf98b9990d6" + }, + "m_Name": "Softness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_D64EC33D", + "m_OverrideReferenceName": "_Softness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "068ae649e00b40e198ec5a30ad741fab", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0699eea947fc426cbfeb8744cf120222", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "07946387933e416db576b677f0711e5f", + "m_Guid": { + "m_GuidSerialized": "21d612fb-8153-41f8-9e2f-9de044c19fbf" + }, + "m_Name": "_FaceTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1A08AD4A", + "m_OverrideReferenceName": "_FaceTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0801f576ce79452483b42e485405244d", + "m_Id": 0, + "m_DisplayName": "Smoothness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Smoothness", + "m_StageCapability": 2, + "m_Value": 0.5, + "m_DefaultValue": 0.5, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "082e9706dffc4c188270980d4e44ce0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0848ba750e0341198cf0bbd413e0efe4", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "09b1b86c1c074337a4c439d3a308dd2e", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0a67ca5280214bd794dc0ad66b5710a9", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0b57f2d35157477ab2b29a5aac14ae8b", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0ba4932e164847878ddb7b7bcff96985", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "0c10df95ee1d4b0a8a00558af49ec45f", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalTS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a0206f980dc6455f84f5a8442838c726" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalTS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0c4dc51f26484c26ad88a3fe4002abcd", + "m_Id": 2, + "m_DisplayName": "Color (1)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "0d6a57754b824f6db9cefa6953bc06a9", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0d7878dd226d4cfb81a991dc312309fc", + "m_Id": 0, + "m_DisplayName": "Underlay Dilate", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "0f7ffb6d2de4447f9736780cbcee8e07", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0fac35636fca4474a6afaefc3c757775", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "105b1ed1aa714e41bbe1ef5472bdb11f", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -4233.0, + "width": 158.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "8a08179f99d649d289b8053d5fa0ad22" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "109f638d1f9b49d4991d6d21a86d4eb7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5098.99951171875, + "y": -3182.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "880bb02c6c6b49b18aa6ebc66dc566a0" + }, + { + "m_Id": "1b9cd8f5f4004e2eaf8afbaab803bc04" + }, + { + "m_Id": "b224a1cf80604103ad085c799995f3c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "10a99c07aad742349d258db16838c129", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1196ae398cc348349ab0c1a23fdab4bd", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "129f271ebc77450994e18f0a30579bf5", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1356dc7cbdfa4199a6535d3bbf4cd536", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "14ad19bf20a140dd88d58452d7df688b", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 1.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "150533bad8e2424aaa2c74e253af8592", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4955.0, + "y": -3487.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "72fb5a0d7796446b9e2b929cb32facdc" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "163beb4431c34f538340bc0af0991e6f", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3284.0, + "y": -3516.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c334de01ecd429baa7652fc6002536b" + }, + { + "m_Id": "e2d28f29bbac4983a401574480b5ca28" + }, + { + "m_Id": "6a7af6143e114a538663e71f56731a21" + }, + { + "m_Id": "3e25be96bb3747738c238cf3a741d5df" + }, + { + "m_Id": "4907352322c644ebacdf2ca30f2994fd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "19075add867e4757b9520d18fe8de1d0", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4292.0, + "y": -3213.000244140625, + "width": 124.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c28ee9109014fa086e5de7a3993341d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0580d4b7e3a049049569f4508643a724" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1b9cd8f5f4004e2eaf8afbaab803bc04", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1bdde3efd3b7464b8934c555be0f8a48", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "1be90d4f96a841748b0c95219b12ad27", + "m_Guid": { + "m_GuidSerialized": "4c91c146-43bb-4de8-948a-fbf8b1da10e1" + }, + "m_Name": "Bevel Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_97690701", + "m_OverrideReferenceName": "_BevelOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": -0.5, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "1c4df61c2fea404eb3b87b270d7c59bc", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4316.0, + "y": -3247.000244140625, + "width": 148.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "f864c900600e427ba7793f00c715e971" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1d35fa1fb5004f96a65ace54fbe4f1ad", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1db37082bf844442804487b4944352de", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1df58cfa4dad4c449d01ee1c5ea05f2e", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "1e12726617b24675958e942eb62e4b09", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4772.0, + "y": -4404.0, + "width": 145.00001525878907, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "0848ba750e0341198cf0bbd413e0efe4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1f247658c7ba45fb93c41f51e21acb0d", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1f46181633594ae0a1fb2adb76b42981", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "200245fc8bbe4826b209ab5f7ffe074c", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "204dacb5a95b424facf11cb6f65bd188", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "215a82c127204988b751de7d3a39b955", + "m_Id": 6, + "m_DisplayName": "Outline", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Outline", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "215b30ae27784ec3a13360a9029af283", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "21a7a380e66d42e780e2a2a1baa630d5", + "m_Guid": { + "m_GuidSerialized": "b2d0099f-e605-49f5-9959-e7cacae37aa3" + }, + "m_Name": "Bevel Type", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_21a7a380e66d42e780e2a2a1baa630d5", + "m_OverrideReferenceName": "_BevelType", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e", + "m_Guid": { + "m_GuidSerialized": "cd167d3a-7465-4d5a-86fc-0f22dc0ef908" + }, + "m_Name": "Outline Color 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5550EB71", + "m_OverrideReferenceName": "_OutlineColor1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "232b1aa09e67479abae141d3c76d3c5b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "256d41e89a204d22951450de1c38051d", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "26e48352a08441bfa694dcea54c06e36", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "281bcee4777040f8a31ee0e10344e98d", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "285f6a9863d54ed2a8150727ad749456", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4181.99951171875, + "y": -2415.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "b42e6dbfbc864097af182cbff5c0c1fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.IsFrontFaceNode", + "m_ObjectId": "2a552a0b828f457c911aa19561e410ae", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Is Front Face", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4282.0, + "y": -3681.3330078125, + "width": 121.99999237060547, + "height": 77.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "2ef1d888dc9d49e59d6a6950897ddc93" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "2ac79705aa9e415dbb74ec215233fd1b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Composite (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3350.0, + "y": -3810.0, + "width": 213.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "a75f7ac601c446469802fe7754c1f279" + }, + { + "m_Id": "8c38a5d8327f456e9783740c05382619" + }, + { + "m_Id": "facc84930f544fd7a0205a6176b18ac0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Composite", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2b01ea3023e34c94af1754e4dcea8f2e", + "m_Id": 0, + "m_DisplayName": "Face Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2bf5f2fdd2984599b7323d10cfb1d240", + "m_Id": 1, + "m_DisplayName": "Filter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Filter", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "2c10b97b92c947ceb307a93759c0228b", + "m_Guid": { + "m_GuidSerialized": "6be0b8ff-a766-4c6b-a6e4-3a72758ac95f" + }, + "m_Name": "Bevel Amount", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B01DD93E", + "m_OverrideReferenceName": "_BevelAmount", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2c7a9460724b47daad8df1be144de7c6", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "2d0a269511e34bd1ba9056d2c939dff2", + "m_Guid": { + "m_GuidSerialized": "edbe73dc-53ab-4bc1-9d64-ab36e0e05f03" + }, + "m_Name": "_FaceUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_3A8E0F13", + "m_OverrideReferenceName": "_FaceUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "2db15d90c2204143b225ec4ef08d0755", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4387.00048828125, + "y": -2381.0, + "width": 163.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "def8e0b9d8384982bc5b4c32d877e458" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "2e4eb1ef08bb44178c82e53872485e0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2ef1d888dc9d49e59d6a6950897ddc93", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 2, + "m_Value": true, + "m_DefaultValue": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "30ca940fe2794c949f2a1d4d2caaa446", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "319916a5921343f7b7eef0e50dc93def", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "d219977210094c0082c517d8dc00c8bb" + }, + { + "m_Id": "f48f04ad45d046a8b88e71731ed506e7" + }, + { + "m_Id": "e6e80c6b0db545cda26b079a9a78fbb3" + }, + { + "m_Id": "c6bdb985bc16435fa72f5a3c81bb633c" + }, + { + "m_Id": "d1a17e42e7a04dc38984e3c01149445b" + }, + { + "m_Id": "fb15d0ba56d54a6192f11e107aeb5fa8" + }, + { + "m_Id": "c35312edaa2344788b1964ee2f63a236" + }, + { + "m_Id": "c88fcbaeea954a5f9c68c339fa8b604d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "34a67e0fef884f9399e674d9eeaf720c", + "m_Id": 6, + "m_DisplayName": "Color3", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color3", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "34a72a5ebb04402384a4fd3748111a37", + "m_Id": 0, + "m_DisplayName": "Alpha Clip Threshold", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AlphaClipThreshold", + "m_StageCapability": 2, + "m_Value": 0.0010000000474974514, + "m_DefaultValue": 0.5, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3535ae87c6dd4769b52b20d9eca61069", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "35cbea6373dd4e4f8d0fea36e8add392", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "36a0c473c4c04c3a930dd38f3920d410", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "36f1b4d96f2941c39e5cd95d9c1d2ce6", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6008.99951171875, + "y": -3341.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "65b3dc13b2b6484283ffe5abfe87a06a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "373f1de8db6c429c9d46c781f741d7a4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3802c81c3be24823aa1d7c9997a33c29", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "3915c1927ffe49f8967304321cfbe497", + "m_Id": 4, + "m_DisplayName": "Atlas", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Atlas", + "m_StageCapability": 3, + "m_BareResource": true, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "39a382d661e2484da71f04c43f48e55f", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "39f2f84f30304d859fb07569e2695f60", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3423.000244140625, + "y": -3516.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "4b2d9ea03bf64fa19dcae1511d2581da" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "3c50439118b2496f9e390021b0964606", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.AlphaClipThreshold", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3028.0, + "y": -3054.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "34a72a5ebb04402384a4fd3748111a37" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.AlphaClipThreshold" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3d04f5ba6e7b40d281f22eb424145acd", + "m_Id": 0, + "m_DisplayName": "Face Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3db1608e927e4102a3c3a88e9fcab39a", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3dccd64e7f324bc1a75c1479d7a67c51", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "3e231021af7b47ba97f2871e7f25d0fe", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2803.000244140625, + "y": -3520.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "6ccaced3889e4503a9414d808ec33981" + }, + { + "m_Id": "7f3d71a6c96847c099da45f95aafbecb" + }, + { + "m_Id": "d8edec16956c4f15b7d51d6ec10753f4" + }, + { + "m_Id": "39a382d661e2484da71f04c43f48e55f" + }, + { + "m_Id": "8764669016f6442f8152593c18a649d7" + }, + { + "m_Id": "26e48352a08441bfa694dcea54c06e36" + }, + { + "m_Id": "3e94a0d106064bdb864c960512ef4026" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3e25be96bb3747738c238cf3a741d5df", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "3e372195f4bd4845852a37839e5b602d", + "m_Guid": { + "m_GuidSerialized": "60abd046-2a1a-48cd-a0af-2f702f7f53ab" + }, + "m_Name": "_MainTex", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_90CBF488", + "m_OverrideReferenceName": "_MainTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":28684132378477856,\"guid\":\"8f586378b4e144a9851e7b34d9b748ee\",\"type\":2}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "3e94a0d106064bdb864c960512ef4026", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "3ec4797e381747829ef4712c85fcf7a1", + "m_Guid": { + "m_GuidSerialized": "020d65cc-50a8-4b8a-a624-90d7b489f549" + }, + "m_Name": "Specular Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_3ec4797e381747829ef4712c85fcf7a1", + "m_OverrideReferenceName": "_SpecularPower", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 4.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "3fdf4b7bc5d4426492dcc057603ef4a6", + "m_Guid": { + "m_GuidSerialized": "675d2567-3fca-4da6-9462-dfa4924950f1" + }, + "m_Name": "_OutlineUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_D66D89E6", + "m_OverrideReferenceName": "_OutlineUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3ffa095f304e42d2827aa230e2ae3887", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "400d0b6c95dd4540ad3da3e8cb7e50b2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "41986ac6400d46709d0ef043a67f6b34", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "41b9b79b3859472882bcea393703eec0", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "424dbeeb009344efa29c304c4979e3d6", + "m_Guid": { + "m_GuidSerialized": "314c37de-c6f2-4463-866d-8588f6fc119e" + }, + "m_Name": "Diffuse Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_424dbeeb009344efa29c304c4979e3d6", + "m_OverrideReferenceName": "_Diffuse", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "42a586e4f6ec40eeaba891b7fd133864", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4934.0, + "y": -4442.99951171875, + "width": 133.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "da7a06d393a44089842070d51d2aa0a6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "42cadae0923e4969b50bbc3f78185934", + "m_Title": "Face + 3 Outlines + Underlay", + "m_Position": { + "x": -5468.0, + "y": -3558.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4328cdbf78b94c038fd614c59bfe1cac", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "44317f2e371447e2a8d894f8a021a235", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Layer1 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4004.999755859375, + "y": -4173.0, + "width": 191.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "10a99c07aad742349d258db16838c129" + }, + { + "m_Id": "b85d677872b44421bf5536f42ba0267c" + }, + { + "m_Id": "75aba700d74d4b2687bf3166cf1da3e2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer1", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "44806230fa384c1e95f9c5918a14f056", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4488af8ff6a7421298a7e827f567263b", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4109.0, + "width": 158.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "66f69ef16eac4eb48357bde804cf3c39" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "4590bfa2a0664b65b6f073bae33a071f", + "m_Id": 0, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_ColorMode": 1, + "m_DefaultColor": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "4648b46ad29a4008a80de4f8a5a5b813", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4615.00048828125, + "y": -2415.000244140625, + "width": 145.0, + "height": 130.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "b2baf44eae52473cb6cda7b1debece01" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "46fbf3eeb0ea4470869cba7443249295", + "m_Guid": { + "m_GuidSerialized": "be87c5a3-e361-4b95-89c8-911c39a51c0d" + }, + "m_Name": "Outline Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_A0B54237", + "m_OverrideReferenceName": "_OutlineTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "47d020251e9841a5b1f0fd64396026a1", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "48390d02257d41bf98eace1deaa4c539", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "8036d0e6090b456e9b4ea87227868236" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "484b51c50485473b819c4f05087b32d7", + "m_Title": "Underlay", + "m_Position": { + "x": -5253.0, + "y": -4542.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4907352322c644ebacdf2ca30f2994fd", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "49e7c3ad55ce458797f0e60c950cb965", + "m_Guid": { + "m_GuidSerialized": "31b55db9-0da1-4ec4-af2b-d83747ed5bc4" + }, + "m_Name": "Underlay Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_CE9DEDB3", + "m_OverrideReferenceName": "_UnderlayOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4a66dcbe712a4d40bd8f355b834594b5", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "4abff6ff92fa4a05b203f10580988335", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4308.0, + "y": -3498.000244140625, + "width": 140.0, + "height": 166.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "b015d1b7e4134c59baf6851e7649802c" + }, + { + "m_Id": "d9dc4839ee2847999110bdb234d6041a" + }, + { + "m_Id": "91d6a9a5fbc04ea49075cb51835e7264" + }, + { + "m_Id": "f42ad06b3c6a45d3ab33de904c063412" + }, + { + "m_Id": "ed6c215a65584deeaefad1d2c7743044" + }, + { + "m_Id": "edbee7a8952b46529ac5ad0365775774" + }, + { + "m_Id": "70337a74f6ad4b7bb6befc825219bab1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4b2d9ea03bf64fa19dcae1511d2581da", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4bda5c294e1949138d033640e1d385b4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4c28ee9109014fa086e5de7a3993341d", + "m_Id": 0, + "m_DisplayName": "Softness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4c334de01ecd429baa7652fc6002536b", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4d1cb1a475df49f9a148195a65f5453a", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4d9ce48719d143748f9f8e22da6f9ddc", + "m_Id": 5, + "m_DisplayName": "TextureWidth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureWidth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4e64dac49ddc47c3b5b1e27b17a08304", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "4eb3c00a1ca44e10be833b7ca61ff059", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4f194ff591484e908fc2bcdacbcf2570", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4303.00048828125, + "y": -2771.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "2b01ea3023e34c94af1754e4dcea8f2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "509e6f38505b4b0695b263706a55028f", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "51378bae98a94c309785d14cd5cbb453", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "GetSurfaceNormal (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4067.333251953125, + "y": -3881.99951171875, + "width": 263.9999694824219, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "5b0077c23eae443887872f84227deccc" + }, + { + "m_Id": "3915c1927ffe49f8967304321cfbe497" + }, + { + "m_Id": "4d9ce48719d143748f9f8e22da6f9ddc" + }, + { + "m_Id": "ebd6d75abcb84108bcadbfe7ee5f6244" + }, + { + "m_Id": "ef9738ec7e894772a14e9dce441c16c6" + }, + { + "m_Id": "9eeec1a9713045af8845cea263d5ea48" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GetSurfaceNormal", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "51f76f8a53ad43a4ad028426548ce9ba", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "52798bdb86f6400e86489a7a368e9f8b", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6154.99951171875, + "y": -3169.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1df58cfa4dad4c449d01ee1c5ea05f2e" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "53073e5ea924459fa6681a4943e9f947", + "m_Guid": { + "m_GuidSerialized": "5fdac24e-2d58-4471-80ce-79c3ab9a2564" + }, + "m_Name": "Outline Color 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_DBAB5AEC", + "m_OverrideReferenceName": "_OutlineColor2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.009433984756469727, + "g": 0.02534518577158451, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "54d7a93ffec5490aa4591da23a21b693", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "55a3403c16184e63b4e78607a6a20cd8", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "55ffa45ec3654d5e88089fb40d2b0465", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "56c25395796e4d2fbe5c892d428d1620", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5102.99951171875, + "y": -3427.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "9eb8137a6c2e41bbafdc8b0732dd47a3" + }, + { + "m_Id": "36a0c473c4c04c3a930dd38f3920d410" + }, + { + "m_Id": "068ae649e00b40e198ec5a30ad741fab" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "57abc172afd449e2a4d567f93432507b", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "582d6e289dbe4fdca7cf0307273eaa2f", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "59a09f50a7ca4cd3a0d248a0f3730b6a", + "m_Guid": { + "m_GuidSerialized": "3f9e6596-fd53-48cc-96a5-4c4f0cfbb2ba" + }, + "m_Name": "_ScaleRatioA", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "_ScaleRatioA", + "m_DefaultReferenceName": "_ScaleRatioA", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "59bd90a849624124bae6464ee3669aa6", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4008.999755859375, + "y": -2394.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "2e4eb1ef08bb44178c82e53872485e0f" + }, + { + "m_Id": "8695190a5e614f2d90081871a8a06fc2" + }, + { + "m_Id": "81bdb47901ef48e5a588c6724b1b0142" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "5b0077c23eae443887872f84227deccc", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5b3ff4ee364f4d7a923b530ad60d8762", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5bd258837c514ff7ab0bf7027e762c18", + "m_Guid": { + "m_GuidSerialized": "2d8f3ee9-1307-4b58-a60d-526e86b07109" + }, + "m_Name": "Bevel Roundness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_AB6A015F", + "m_OverrideReferenceName": "_BevelRoundness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5da82bf481f8489ebd05e997f617f51b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": 4.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5e42524569844befad16fda5a94eb9cb", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5fbe253f3e444f2aa8ac717f9c856619", + "m_Guid": { + "m_GuidSerialized": "0a61c93f-6430-4aa6-af07-79bc3b411ccd" + }, + "m_Name": "Bevel Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B50BBFCC", + "m_OverrideReferenceName": "_BevelWidth", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.5, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61133d79a89048c195f54939b2a1d30a", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61a6ac5f29344d109411f26850ab0a96", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6271438664e74b3fbf723bd6a1f50f8b", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "62bc551cea604e88b7858cc37d96a98a", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "636180f6e0504f2baaa5cc086980cb47", + "m_Guid": { + "m_GuidSerialized": "c1223e37-093d-4d5a-b2b0-cd9cc3e4f88e" + }, + "m_Name": "Outline Offset 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_636180f6e0504f2baaa5cc086980cb47", + "m_OverrideReferenceName": "_OutlineOffset1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "63c7cd57fc3c45a9a97b514fdae32693", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5266.99951171875, + "y": -3387.0, + "width": 156.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "c422a9a9ff824176aad2241f58c44d0b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "641eda269d7b4da9acb65f8d50035ea9", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "65b3dc13b2b6484283ffe5abfe87a06a", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "65c8e64a7535466e933eed08a2f77532", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3499.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "256d41e89a204d22951450de1c38051d" + }, + { + "m_Id": "0a67ca5280214bd794dc0ad66b5710a9" + }, + { + "m_Id": "ebbd94a7102a4457a48ac492de3bff14" + }, + { + "m_Id": "6271438664e74b3fbf723bd6a1f50f8b" + }, + { + "m_Id": "c9b722d107ce4cd6a748c883472b9b0f" + }, + { + "m_Id": "74cf69e61bef44589521f1bf2bf3c59a" + }, + { + "m_Id": "6e532f83d1c44e839bcfc5845d3b01d6" + }, + { + "m_Id": "cb5e9f9567e84f8fa5463efc0e256e19" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "66f69ef16eac4eb48357bde804cf3c39", + "m_Id": 0, + "m_DisplayName": "_UnderlayColor", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "67a519f507384ff1861df5d8d5b486be", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4278.0, + "y": -3939.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c3e6d7c20c184bf39fd8822130e693e7" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "68ec7c31365549d6a8ce883edfc02de2", + "m_Id": 4, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6a7af6143e114a538663e71f56731a21", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "6b2f65c1463f4f7bad16c54a95d2fe75", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5101.0, + "y": -3301.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "1d35fa1fb5004f96a65ace54fbe4f1ad" + }, + { + "m_Id": "fa6de3be9f5b4411b5081b49e645f424" + }, + { + "m_Id": "400d0b6c95dd4540ad3da3e8cb7e50b2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6ccaced3889e4503a9414d808ec33981", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6dfc1177dd0541a7a780fbf911ad1956", + "m_Id": 0, + "m_DisplayName": "_OutlineTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e13f3cd573c467a94379f45d96cb690", + "m_Id": 2, + "m_DisplayName": "SSR", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "6e532f83d1c44e839bcfc5845d3b01d6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6e8946a245e842b38231d4a241bfb3ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3026.0, + "y": -3110.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "ef0b93f78372439696f50711eaf57d90" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "6fbdcc5a972b4fa883dc5f21e525a376", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "7027aaab25924266a063a05df0aa39b3", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "70337a74f6ad4b7bb6befc825219bab1", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "712da461f71a454db59d349f752d41ee", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "71dd947935b64ce38f0d25406dde447b", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "724e17584e97443e9e285dfa7253c8e3", + "m_Id": 0, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 2, + "m_Value": 0.15000000596046449, + "m_DefaultValue": 1.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "72fb5a0d7796446b9e2b929cb32facdc", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "7444469eb9884253819add9ef96baa25", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4298.0, + "y": -3809.99951171875, + "width": 144.66648864746095, + "height": 129.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "03182b3263304258b265266325c21f65" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "748c31bbcecc4b30bec2e42c0612175b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "74b41464cbed4e9e8e23af5ab9be40cf", + "m_Guid": { + "m_GuidSerialized": "41afbdcb-f3ae-4340-8973-1c1998c992a2" + }, + "m_Name": "Outline Offset 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "74cf69e61bef44589521f1bf2bf3c59a", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "757174b6f25040fdbb20355a21752222", + "m_Id": 0, + "m_DisplayName": "Outline Offset 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "75aba700d74d4b2687bf3166cf1da3e2", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "75c5657544c648058b20cea090f48dbf", + "m_Id": 0, + "m_DisplayName": "_OutlineUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "767769f736d5478cba5f10a415e28e7f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "773b90134e894e429203c0c83e80b9de", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "77e28f3e930b4c249145630ec961af95", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "79147f6986644769b58d9ed64fe771e1", + "m_Id": 0, + "m_DisplayName": "OutlineMode", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7984fd094e1147bdabb4e26fbd3d31c8", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3113.000244140625, + "y": -3468.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "082e9706dffc4c188270980d4e44ce0f" + }, + { + "m_Id": "f2a351a5375c441b8d9ab7e2c9545a77" + }, + { + "m_Id": "41986ac6400d46709d0ef043a67f6b34" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "7a046f410ce64aa88438b0bfd412c045", + "m_Guid": { + "m_GuidSerialized": "d47271f5-5a84-47bf-a09e-c825d2aeb013" + }, + "m_Name": "Outline Color 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_551702C5", + "m_OverrideReferenceName": "_OutlineColor3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "7a0f504e4175406dbd8134250f4e350b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7a80e8839f0e4a1d9a6c0814f8793ee6", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4961.99951171875, + "y": -3452.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "6fbdcc5a972b4fa883dc5f21e525a376" + }, + { + "m_Id": "0ba4932e164847878ddb7b7bcff96985" + }, + { + "m_Id": "9178663316db43d582f1c4a127d307c6" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7acfafd73b8c4dfab8c55c18a887e087", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7b144a976914480baf430c0f6f7f4def", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "7b8a19bd115e4167a25b59cb3218a817", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "7c27ccb2c2dc4ca59c5438c3358630ca", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "7c73ccc923e744b98f19148b971a6090", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "59a09f50a7ca4cd3a0d248a0f3730b6a" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7d7696aa6d184b4fb9c316a9dec37aee", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4959.0, + "y": -3326.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "4d1cb1a475df49f9a148195a65f5453a" + }, + { + "m_Id": "47d020251e9841a5b1f0fd64396026a1" + }, + { + "m_Id": "62bc551cea604e88b7858cc37d96a98a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7d78a616c2754cc28d1f32cf66ade611", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4006.999755859375, + "y": -2796.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d9bcb754db834583b6518c5ed5152114" + }, + { + "m_Id": "861d4258049a4a3e8164f7297090f88e" + }, + { + "m_Id": "a7c06457d7454693a8bc3dc95257b2c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "7e0fadb2533f496192c1ad3e78642010", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4188.0, + "width": 173.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d48c3871e3064027a10ae9f4babd3be0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f2e6b5f15364ed9835d67d0cf4f8f65", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2586.0, + "y": -3592.0, + "width": 200.0, + "height": 41.0 + } + }, + "m_Slots": [ + { + "m_Id": "85ff8667d72947edada4e9fb4ff60559" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7f3d71a6c96847c099da45f95aafbecb", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "8036d0e6090b456e9b4ea87227868236", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "80e665a5eeb64730a51742f698bf0d48", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "8135ca333f8f4ea78163743e6ec1f55c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3140.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d6a6a119394e4082a11bc024a6e42ef8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "81bdb47901ef48e5a588c6724b1b0142", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "81e8ed0534534674a74263e6161a2a1a", + "m_Guid": { + "m_GuidSerialized": "78aab961-c4a8-41f3-b203-1239c3b33b13" + }, + "m_Name": "Underlay Dilate", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_D48690B9", + "m_OverrideReferenceName": "_UnderlayDilate", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "82af2db1018543d7832af96c1cfc981f", + "m_Guid": { + "m_GuidSerialized": "37906c7b-9a3a-454b-a62a-9aa097e64bde" + }, + "m_Name": "Light Angle", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_82af2db1018543d7832af96c1cfc981f", + "m_OverrideReferenceName": "_LightAngle", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 6.28000020980835 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "82d5443fe54d4a3b9420f8745d00a632", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": 8.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "836f639bd89d42f9b3a0470c3094815e", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "83c51d5b2f7b4eb785248f419181cb87", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Occlusion", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "944ebbc49c8a4cddb5834e3beab965a2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Occlusion" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "84dc74cdbd8c45e1b189e4fd9a69942d", + "m_Id": 0, + "m_DisplayName": "Outline Offset 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "85a1ad8e741e41759002e8cdc8cd0b96", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "ScreenSpaceRatio (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5800.99951171875, + "y": -3363.0, + "width": 258.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e13f3cd573c467a94379f45d96cb690" + }, + { + "m_Id": "8e6ed600f6504f4083092f5b511e44c4" + }, + { + "m_Id": "93b161cce4504cb79c97b6d8db178de7" + }, + { + "m_Id": "2bf5f2fdd2984599b7323d10cfb1d240" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ScreenSpaceRatio", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "85b5940eb77e4625812ded7215bab8d7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3096.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ada023d617104472b8ab75a81558c0a1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "85ff8667d72947edada4e9fb4ff60559", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "861d4258049a4a3e8164f7297090f88e", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "867a4ae13c0d4a028c71bc1063824c14", + "m_Guid": { + "m_GuidSerialized": "d483c212-0a30-4f6d-b94d-9abbc83a6522" + }, + "m_Name": "Outline Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_C68C9E14", + "m_OverrideReferenceName": "_IsoPerimeter", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 2, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "8695190a5e614f2d90081871a8a06fc2", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "86e21b7b6b7a44238607e41b8a9fb9a4", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Smoothness", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "0801f576ce79452483b42e485405244d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Smoothness" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8764669016f6442f8152593c18a649d7", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "880bb02c6c6b49b18aa6ebc66dc566a0", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "88253223d2c34ecfab92b0c344048f94", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "ComputeSDF (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4323.0, + "width": 227.99998474121095, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "c52a1744a9a14989b0ae452ad6de6061" + }, + { + "m_Id": "a03db80c558b4f87a330c5ae0a9443a5" + }, + { + "m_Id": "8f1b1d1e8ff24b3284993e52354e54fa" + }, + { + "m_Id": "5da82bf481f8489ebd05e997f617f51b" + }, + { + "m_Id": "82d5443fe54d4a3b9420f8745d00a632" + }, + { + "m_Id": "61133d79a89048c195f54939b2a1d30a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8a08179f99d649d289b8053d5fa0ad22", + "m_Id": 0, + "m_DisplayName": "Underlay Offset", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8b66f4e6bc9d4662b3218ac33a69839f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8c38a5d8327f456e9783740c05382619", + "m_Id": 3, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8cbd81814903479ea1d3151c1f38183e", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "8cf8aae64c1d443f9303126886b40f17", + "m_Guid": { + "m_GuidSerialized": "8d78c9a5-aaef-41fb-af68-2358e401d7ac" + }, + "m_Name": "_UnderlayColor", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_2F5FE804", + "m_OverrideReferenceName": "_UnderlayColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6aee1173864e58be589084897a3f35", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6ed600f6504f4083092f5b511e44c4", + "m_Id": 0, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "8ed907a2cc7949b68a283ae243ea1977", + "m_Guid": { + "m_GuidSerialized": "36803443-a9bc-4f3c-a4f2-7d66a5417ac1" + }, + "m_Name": "Outline Offset 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8f1b1d1e8ff24b3284993e52354e54fa", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9147636b0cfa466a9b37a013d8f693bf", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5421.99951171875, + "y": -3902.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a4f471e3221c4134b291bd9d2ba22db6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "9178663316db43d582f1c4a127d307c6", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "91890fe48ebe4717aea61ecaf3ad4861", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2983.000244140625, + "y": -3468.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "3dccd64e7f324bc1a75c1479d7a67c51" + }, + { + "m_Id": "e444f2c81d1e48329fa2c91005277e8d" + }, + { + "m_Id": "b2c26292b7434733878a9b042f44de89" + }, + { + "m_Id": "964fea1fd4b24f4daf5bef84c4b45118" + }, + { + "m_Id": "deac82280a2b43078e0e40863e2d974c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "91d6a9a5fbc04ea49075cb51835e7264", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "928621a3ca2d41c89a10336bbbc81ddc", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "93b161cce4504cb79c97b6d8db178de7", + "m_Id": 3, + "m_DisplayName": "TextureSize", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureSize", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget", + "m_ObjectId": "94300469581b4924ac7dda496811d45d", + "m_Datas": [], + "m_ActiveSubTarget": { + "m_Id": "a0b9274619da48a59f26fe58997479ee" + }, + "m_AllowMaterialOverride": false, + "m_SurfaceType": 1, + "m_ZTestMode": 4, + "m_ZWriteControl": 0, + "m_AlphaMode": 0, + "m_RenderFace": 0, + "m_AlphaClip": true, + "m_CastShadows": true, + "m_ReceiveShadows": true, + "m_AdditionalMotionVectorMode": 0, + "m_AlembicMotionVectors": false, + "m_SupportsLODCrossFade": false, + "m_CustomEditorGUI": "TMPro.EditorUtilities.TMP_SDFShaderGUI", + "m_SupportVFX": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "944ebbc49c8a4cddb5834e3beab965a2", + "m_Id": 0, + "m_DisplayName": "Ambient Occlusion", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Occlusion", + "m_StageCapability": 2, + "m_Value": 1.0, + "m_DefaultValue": 1.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "945b45993dd84a979755b98c48138f72", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "952d0fa5cd744df0b434cd38e9a90b93", + "m_Guid": { + "m_GuidSerialized": "ce395871-ddeb-47c3-a31d-07855800c197" + }, + "m_Name": "_UnderlaySoftness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_F2B9E3EF", + "m_OverrideReferenceName": "_UnderlaySoftness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "95928bcb6a284b8d88105a84c2e1d3ce", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4778.00048828125, + "y": -2581.000244140625, + "width": 155.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d880558893fb442b9320cf55885d1117" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "964fea1fd4b24f4daf5bef84c4b45118", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "98934a69591249d5b8b92b39045359a3", + "m_Title": "Outline1 Texture", + "m_Position": { + "x": -4670.00048828125, + "y": -2474.000244140625 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "998db5e5901e45b29040eb2099370071", + "m_Guid": { + "m_GuidSerialized": "6f383614-f2ad-4269-be8f-87b0ecb03cf0" + }, + "m_Name": "Bevel Clamp", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_5BD7E808", + "m_OverrideReferenceName": "_BevelClamp", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "9c228fac287d446296b91a4acf5cec59", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3498.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "582d6e289dbe4fdca7cf0307273eaa2f" + }, + { + "m_Id": "1db37082bf844442804487b4944352de" + }, + { + "m_Id": "8b66f4e6bc9d4662b3218ac33a69839f" + }, + { + "m_Id": "4a66dcbe712a4d40bd8f355b834594b5" + }, + { + "m_Id": "a0285c9c381a49cba194709efa0a7c85" + }, + { + "m_Id": "b2728d0dd3ce40678867c94a7d977916" + }, + { + "m_Id": "e141833aa78b4fd59ecad949beb43a78" + }, + { + "m_Id": "51f76f8a53ad43a4ad028426548ce9ba" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9c26fdddba244d36a854298c00473247", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "9d3c3383d5934a17bf9efbb7fd9e9043", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5443.0, + "y": -3315.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "232b1aa09e67479abae141d3c76d3c5b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e6e50a71d9843b49b62ebe1cf7d3d59", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4486.0, + "y": -3865.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "3535ae87c6dd4769b52b20d9eca61069" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e87ce9607e14015a3790c528ca5dfda", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4635.00048828125, + "y": -2239.0, + "width": 167.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "75c5657544c648058b20cea090f48dbf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "9eb8137a6c2e41bbafdc8b0732dd47a3", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "9eeec1a9713045af8845cea263d5ea48", + "m_Id": 6, + "m_DisplayName": "IsFront", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "IsFront", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "9f0de188085746d5a19073da1de85ddb", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4152.0, + "y": -2771.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7c27ccb2c2dc4ca59c5438c3358630ca" + }, + { + "m_Id": "373f1de8db6c429c9d46c781f741d7a4" + }, + { + "m_Id": "fd0b096ed5b74f9e9ec51327be200731" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a0206f980dc6455f84f5a8442838c726", + "m_Id": 0, + "m_DisplayName": "Normal (Tangent Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalTS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 3 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a0285c9c381a49cba194709efa0a7c85", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a03db80c558b4f87a330c5ae0a9443a5", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 2, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalLitSubTarget", + "m_ObjectId": "a0b9274619da48a59f26fe58997479ee", + "m_WorkflowMode": 1, + "m_NormalDropOffSpace": 0, + "m_ClearCoat": false, + "m_BlendModePreserveSpecular": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a3f8b6e8ae7f48e2989a029904401502", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "a455bd79094c4413a7b7dd80ca8b9368", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4606.99951171875, + "y": -2689.0, + "width": 221.99998474121095, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "7027aaab25924266a063a05df0aa39b3" + }, + { + "m_Id": "2c7a9460724b47daad8df1be144de7c6" + }, + { + "m_Id": "55ffa45ec3654d5e88089fb40d2b0465" + }, + { + "m_Id": "e495a9f7a11f4eb89334e83be154ceb9" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateShaderProperty", + "m_ObjectId": "a4ad98d8828c424384229c344ebe2ed0", + "m_Guid": { + "m_GuidSerialized": "f98fc1a2-bb81-4bd1-a207-23d3a90d518e" + }, + "m_Name": "SamplerState", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "SamplerState_a4ad98d8828c424384229c344ebe2ed0", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": false, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_filter": 0, + "m_wrap": 1, + "m_anisotropic": 0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a4f471e3221c4134b291bd9d2ba22db6", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "a535f3bcbeb14622bb177eb6f46e76f4", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4628.00048828125, + "y": -2283.0, + "width": 157.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "6dfc1177dd0541a7a780fbf911ad1956" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "a6bbb32e8d884be9bb36db91fe4b81b1", + "m_Guid": { + "m_GuidSerialized": "6aa76edf-7b80-46ac-add4-406cf1d85493" + }, + "m_Name": "_GradientScale", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_EAE27356", + "m_OverrideReferenceName": "_GradientScale", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 10.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "a6c38edd2e8743a9b057ba8452b9f129", + "m_Guid": { + "m_GuidSerialized": "9fc942ee-4a1d-4ced-a5a6-81893e3ddb63" + }, + "m_Name": "Light Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_a6c38edd2e8743a9b057ba8452b9f129", + "m_OverrideReferenceName": "_SpecularColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "a75f7ac601c446469802fe7754c1f279", + "m_Id": 0, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a7942746b5564dc7bbbae1deb2403022", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "a7c06457d7454693a8bc3dc95257b2c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa2794b8f0e24bf281d22e0fef0647be", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "aa3e347d733e48f7b65d8a8847370eec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "EvaluateLight (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3631.0, + "y": -3810.0, + "width": 230.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "0699eea947fc426cbfeb8744cf120222" + }, + { + "m_Id": "0c4dc51f26484c26ad88a3fe4002abcd" + }, + { + "m_Id": "d5173cc3c6cd4f1998550f3187a3e9c8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "EvaluateLight", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aa87c72ac0e64469acc34f936f00b3d0", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4225.0, + "width": 193.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "0d7878dd226d4cfb81a991dc312309fc" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "abd59150589b436cadf8c9e6f43ccb8e", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "aca823a8188948c782eddaf0f45e1868", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalOS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2542.0, + "y": -3404.000244140625, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "e386b183a18245a796b024022f7f3074" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalOS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "acd0cd5a177f4a97bf23db7219305e3f", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4348.0, + "y": -3905.99951171875, + "width": 185.33299255371095, + "height": 101.33324432373047 + } + }, + "m_Slots": [ + { + "m_Id": "945b45993dd84a979755b98c48138f72" + }, + { + "m_Id": "e51a636b2621440eb94cc802c1cf4bfc" + }, + { + "m_Id": "1bdde3efd3b7464b8934c555be0f8a48" + }, + { + "m_Id": "129f271ebc77450994e18f0a30579bf5" + }, + { + "m_Id": "3ffa095f304e42d2827aa230e2ae3887" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "ad3e1d26f4404555a8dd29223caaf1ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Metallic", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "b46afdad84944599b00e887d2ce29cc3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Metallic" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ada023d617104472b8ab75a81558c0a1", + "m_Id": 0, + "m_DisplayName": "Outline Color 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aef5c44f84e04c3185e0b93e95e34204", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5264.99951171875, + "y": -3142.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "84dc74cdbd8c45e1b189e4fd9a69942d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b000f852aa984e9dae25b125a4607f4e", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b015d1b7e4134c59baf6851e7649802c", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "b0b352c4503a43d083a64e57352b29a0", + "m_Guid": { + "m_GuidSerialized": "01cfcc78-60aa-4f71-a1e3-8d8df6dae253" + }, + "m_Name": "Reflectivity Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_b0b352c4503a43d083a64e57352b29a0", + "m_OverrideReferenceName": "_Reflectivity", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 5.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 5.0, + "y": 15.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "b1188549725543d485436c2e921ffbb2", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4142.0, + "y": -2890.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "281bcee4777040f8a31ee0e10344e98d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "b163c9f1666644b0bba62cf0e12df7bc", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4367.0, + "y": -2713.0, + "width": 180.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "cce40479b6284b6fa3174db9f09d0ac9" + }, + { + "m_Id": "80e665a5eeb64730a51742f698bf0d48" + }, + { + "m_Id": "1f46181633594ae0a1fb2adb76b42981" + }, + { + "m_Id": "8cbd81814903479ea1d3151c1f38183e" + }, + { + "m_Id": "cfaf3f3a5a1146e194cddad30c95aada" + }, + { + "m_Id": "b43489e37a5c4df88f15844292a55ec7" + }, + { + "m_Id": "cd7281fb41aa4e61ac0fdf71d4f4bd46" + }, + { + "m_Id": "f01d52cdcb1647aab35782b4af535efd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 1, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "b224a1cf80604103ad085c799995f3c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b2728d0dd3ce40678867c94a7d977916", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b2baf44eae52473cb6cda7b1debece01", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b2c26292b7434733878a9b042f44de89", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b42e6dbfbc864097af182cbff5c0c1fb", + "m_Id": 0, + "m_DisplayName": "Outline Color 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b43489e37a5c4df88f15844292a55ec7", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b467be738d0e454995e380cbf526efe3", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b46afdad84944599b00e887d2ce29cc3", + "m_Id": 0, + "m_DisplayName": "Metallic", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Metallic", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "b4a40cb6acd441acb83cfe0240bf910d", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4750.99951171875, + "y": -4274.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d0b10e52e21941b183f5f635894c76c8" + }, + { + "m_Id": "0d6a57754b824f6db9cefa6953bc06a9" + }, + { + "m_Id": "773b90134e894e429203c0c83e80b9de" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "b571db753a1948d5a6f1de4e7d0c7238", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5581.99951171875, + "y": -3867.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "5b3ff4ee364f4d7a923b530ad60d8762" + }, + { + "m_Id": "c183b5bd9bbe45089f93996e73110918" + }, + { + "m_Id": "1196ae398cc348349ab0c1a23fdab4bd" + }, + { + "m_Id": "7b144a976914480baf430c0f6f7f4def" + }, + { + "m_Id": "836f639bd89d42f9b3a0470c3094815e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b691728a389a417d9b4f2d02541209c2", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b7f9ac55517141868bfb9d2ad6429792", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b85d677872b44421bf5536f42ba0267c", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "bc9afcb18afa4ccc82d2cdc34d3f4641", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -5392.0, + "y": -3867.0, + "width": 125.99999237060547, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "5e42524569844befad16fda5a94eb9cb" + }, + { + "m_Id": "54d7a93ffec5490aa4591da23a21b693" + }, + { + "m_Id": "aa2794b8f0e24bf281d22e0fef0647be" + }, + { + "m_Id": "200245fc8bbe4826b209ab5f7ffe074c" + }, + { + "m_Id": "fc2e62201c5847e798fd939314413fcd" + }, + { + "m_Id": "fe11fa80cc1847a5a37f6757d521cf25" + }, + { + "m_Id": "de0c6f7f7af94defa6c3dbc6433de9d4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c183b5bd9bbe45089f93996e73110918", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "c234e5216678436195ee1a5914bc79da", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4446.0, + "y": -2347.0, + "width": 221.99998474121095, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "8e6aee1173864e58be589084897a3f35" + }, + { + "m_Id": "3db1608e927e4102a3c3a88e9fcab39a" + }, + { + "m_Id": "0f7ffb6d2de4447f9736780cbcee8e07" + }, + { + "m_Id": "d4954b7bbbb0412cbc997bcbe7dfa808" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "c35312edaa2344788b1964ee2f63a236", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "c3e6d7c20c184bf39fd8822130e693e7", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "c422a9a9ff824176aad2241f58c44d0b", + "m_Id": 0, + "m_DisplayName": "Outline Offset 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "c478c32c45884c57a62f7b2aa8ddc3b0", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c52a1744a9a14989b0ae452ad6de6061", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c6bdb985bc16435fa72f5a3c81bb633c", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c7d4094601ac4bc1aead609c72b1f1c1", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c7ddee91dc5b48dc828309c77fdb0b88", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4266.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a7942746b5564dc7bbbae1deb2403022" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "c88fcbaeea954a5f9c68c339fa8b604d", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c9b722d107ce4cd6a748c883472b9b0f", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c9d7f0dbae7d422985a1cc87c025e76b", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4312.0, + "y": -3179.000244140625, + "width": 144.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "79147f6986644769b58d9ed64fe771e1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "c9ec735d1a1046769e5601b2c97c849a", + "m_Guid": { + "m_GuidSerialized": "281a9526-c332-4471-a44e-ece4a1e95ef6" + }, + "m_Name": "Face Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_75569DEA", + "m_OverrideReferenceName": "_FaceTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ca2a1083dc014f39ab8af0cdf140866b", + "m_Id": 0, + "m_DisplayName": "_FaceTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "cb3c0c3f08654b068bea44c4ffb15f4a", + "m_Guid": { + "m_GuidSerialized": "21009d12-8d94-4273-b0d0-a8ee0608ddcf" + }, + "m_Name": "OutlineMode", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_cb3c0c3f08654b068bea44c4ffb15f4a", + "m_OverrideReferenceName": "_OutlineMode", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cb5e9f9567e84f8fa5463efc0e256e19", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "cb7117ecb1d047a8b2cb00ed552cb181", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Alpha", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3032.66650390625, + "y": -3029.33349609375, + "width": 200.0, + "height": 41.33349609375 + } + }, + "m_Slots": [ + { + "m_Id": "724e17584e97443e9e285dfa7253c8e3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Alpha" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cc88101667c9488f9c5a716e851c1b21", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cce40479b6284b6fa3174db9f09d0ac9", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "cd7281fb41aa4e61ac0fdf71d4f4bd46", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cda5e3b4c1054bf3a65c0b7ec6bc778a", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "cdddee3a537c464697357f11b966f9b8", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4420.0, + "y": -4483.0, + "width": 156.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "41b9b79b3859472882bcea393703eec0" + }, + { + "m_Id": "c7d4094601ac4bc1aead609c72b1f1c1" + }, + { + "m_Id": "767769f736d5478cba5f10a415e28e7f" + }, + { + "m_Id": "b691728a389a417d9b4f2d02541209c2" + }, + { + "m_Id": "045c4f6b050549c7a0efb208e6349779" + }, + { + "m_Id": "509e6f38505b4b0695b263706a55028f" + }, + { + "m_Id": "204dacb5a95b424facf11cb6f65bd188" + }, + { + "m_Id": "35cbea6373dd4e4f8d0fea36e8add392" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "cfaf3f3a5a1146e194cddad30c95aada", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d0a791a544614667962a9a9a9ce0c68a", + "m_Title": "Screen Space Ratio", + "m_Position": { + "x": -6179.99951171875, + "y": -3422.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d0b10e52e21941b183f5f635894c76c8", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d1a17e42e7a04dc38984e3c01149445b", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d219977210094c0082c517d8dc00c8bb", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d258902c6ec74942afdb9ebf8c1d07f8", + "m_Title": "Generate Normal", + "m_Position": { + "x": -4511.33349609375, + "y": -3999.3330078125 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "d30452ac6b244ecca03df4d7b4de9f81", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d48c3871e3064027a10ae9f4babd3be0", + "m_Id": 0, + "m_DisplayName": "_UnderlaySoftness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d4954b7bbbb0412cbc997bcbe7dfa808", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "d4df208fc23b42f2b52364124f1b661c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5268.0, + "y": -3261.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "757174b6f25040fdbb20355a21752222" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "d5173cc3c6cd4f1998550f3187a3e9c8", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d6a6a119394e4082a11bc024a6e42ef8", + "m_Id": 0, + "m_DisplayName": "Outline Color 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d880558893fb442b9320cf55885d1117", + "m_Id": 0, + "m_DisplayName": "_FaceUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d8edec16956c4f15b7d51d6ec10753f4", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d9bcb754db834583b6518c5ed5152114", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d9dc4839ee2847999110bdb234d6041a", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "da7a06d393a44089842070d51d2aa0a6", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "daaf032a109749a88c9b8ff8e1f8b541", + "m_Title": "Offset Scale", + "m_Position": { + "x": -5747.99951171875, + "y": -3961.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "dbcb748279484a4590e53518c49122b8", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4776.00048828125, + "y": -2757.000244140625, + "width": 145.0, + "height": 130.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "7a0f504e4175406dbd8134250f4e350b" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "dc75c4e3a1bc4bb0a128086c2b0679a5", + "m_Guid": { + "m_GuidSerialized": "85cd941f-2fd2-43a3-b0fa-9f728bfb4220" + }, + "m_Name": "Face Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_99AFBB3D", + "m_OverrideReferenceName": "_FaceColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "de0c6f7f7af94defa6c3dbc6433de9d4", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "deac82280a2b43078e0e40863e2d974c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "def8e0b9d8384982bc5b4c32d877e458", + "m_Id": 0, + "m_DisplayName": "Outline Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "dff7a66b353a4023b29c9d937da77960", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4602.0, + "y": -4298.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7b8a19bd115e4167a25b59cb3218a817" + }, + { + "m_Id": "0b57f2d35157477ab2b29a5aac14ae8b" + }, + { + "m_Id": "e9e06fcb161e44ba8cc9f6f60264df78" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "e141833aa78b4fd59ecad949beb43a78", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e2d28f29bbac4983a401574480b5ca28", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "e386b183a18245a796b024022f7f3074", + "m_Id": 0, + "m_DisplayName": "Normal (Object Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalOS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e444f2c81d1e48329fa2c91005277e8d", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "e495a9f7a11f4eb89334e83be154ceb9", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e51a636b2621440eb94cc802c1cf4bfc", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "e591df3a1eb94e259b762f2830b407e2", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Emission", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "4590bfa2a0664b65b6f073bae33a071f" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Emission" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e6e80c6b0db545cda26b079a9a78fbb3", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "e818605f8f5a4f01bf61caaa33693581", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "ComputeSDF44 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4144.0, + "y": -3369.0, + "width": 244.0, + "height": 214.0 + } + }, + "m_Slots": [ + { + "m_Id": "641eda269d7b4da9acb65f8d50035ea9" + }, + { + "m_Id": "f6823778a3cf42d5bbe8a83e5f9c9fa3" + }, + { + "m_Id": "9c26fdddba244d36a854298c00473247" + }, + { + "m_Id": "f684c5678e9e4f078157a3ab7ef5057b" + }, + { + "m_Id": "14ad19bf20a140dd88d58452d7df688b" + }, + { + "m_Id": "215a82c127204988b751de7d3a39b955" + }, + { + "m_Id": "c478c32c45884c57a62f7b2aa8ddc3b0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF44", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "e9e06fcb161e44ba8cc9f6f60264df78", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebbd94a7102a4457a48ac492de3bff14", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebd6d75abcb84108bcadbfe7ee5f6244", + "m_Id": 7, + "m_DisplayName": "TextureHeight", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureHeight", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "ec184d6d9fb2494897774c9e7d279e6d", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4778.00048828125, + "y": -2626.0, + "width": 145.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ca2a1083dc014f39ab8af0cdf140866b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "07946387933e416db576b677f0711e5f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "ec1f2e8bc9fd4ae38b133c60ee6c49b8", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4957.99951171875, + "y": -3204.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "748c31bbcecc4b30bec2e42c0612175b" + }, + { + "m_Id": "4bda5c294e1949138d033640e1d385b4" + }, + { + "m_Id": "4e64dac49ddc47c3b5b1e27b17a08304" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "ec79eb447dfd47a9b3380344c6a60f43", + "m_Guid": { + "m_GuidSerialized": "54c77f8b-0534-4b35-a3f0-83ab2ebe6c1f" + }, + "m_Name": "_OutlineTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1774DE83", + "m_OverrideReferenceName": "_OutlineTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "ecf16c34d46f4502ac601f0c38c7576b", + "m_Title": "Vertex Color", + "m_Position": { + "x": -3448.000244140625, + "y": -3579.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ed1d1f1613334c3bb904dd08161cd7e5", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ed6c215a65584deeaefad1d2c7743044", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "edbee7a8952b46529ac5ad0365775774", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "ef0b93f78372439696f50711eaf57d90", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.7353569269180298, + "y": 0.7353569269180298, + "z": 0.7353569269180298 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ef9738ec7e894772a14e9dce441c16c6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "f01d52cdcb1647aab35782b4af535efd", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "f23a8b2b7c85478388ff7a8c8a6de740", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Layer4 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3849.999755859375, + "y": -3286.0, + "width": 193.0, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "0fac35636fca4474a6afaefc3c757775" + }, + { + "m_Id": "cc88101667c9488f9c5a716e851c1b21" + }, + { + "m_Id": "68ec7c31365549d6a8ce883edfc02de2" + }, + { + "m_Id": "02559cbe5ad441a3904ccb75ded2b2c5" + }, + { + "m_Id": "34a67e0fef884f9399e674d9eeaf720c" + }, + { + "m_Id": "3802c81c3be24823aa1d7c9997a33c29" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer4", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "f2903158b3624759bca1fcd843698078", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "f2a351a5375c441b8d9ab7e2c9545a77", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "f383b24f0bc6434dafe44b3e3d338a63", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6012.99951171875, + "y": -3209.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "fb5e1e2a67c14602808358686bb75091" + }, + { + "m_Id": "712da461f71a454db59d349f752d41ee" + }, + { + "m_Id": "b000f852aa984e9dae25b125a4607f4e" + }, + { + "m_Id": "55a3403c16184e63b4e78607a6a20cd8" + }, + { + "m_Id": "b467be738d0e454995e380cbf526efe3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "f3d31c1f18d8491a8ecf5cbc37e4b7db", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4321.0, + "y": -3281.000244140625, + "width": 153.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ed1d1f1613334c3bb904dd08161cd7e5" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f42ad06b3c6a45d3ab33de904c063412", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f48f04ad45d046a8b88e71731ed506e7", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f4ecc442a2d246759f7c2c0412953d28", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a3f8b6e8ae7f48e2989a029904401502" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f6823778a3cf42d5bbe8a83e5f9c9fa3", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f684c5678e9e4f078157a3ab7ef5057b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": { + "x": 3.0, + "y": 2.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "f814deb543c24fbbafbcdb5071d96022", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "abd59150589b436cadf8c9e6f43ccb8e" + }, + { + "m_Id": "7acfafd73b8c4dfab8c55c18a887e087" + }, + { + "m_Id": "928621a3ca2d41c89a10336bbbc81ddc" + }, + { + "m_Id": "b7f9ac55517141868bfb9d2ad6429792" + }, + { + "m_Id": "09b1b86c1c074337a4c439d3a308dd2e" + }, + { + "m_Id": "1f247658c7ba45fb93c41f51e21acb0d" + }, + { + "m_Id": "d30452ac6b244ecca03df4d7b4de9f81" + }, + { + "m_Id": "215b30ae27784ec3a13360a9029af283" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f864c900600e427ba7793f00c715e971", + "m_Id": 0, + "m_DisplayName": "Outline Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fa6de3be9f5b4411b5081b49e645f424", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "faace8101df943d8956faa31728cb004", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5254.99951171875, + "y": -3891.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "77e28f3e930b4c249145630ec961af95" + }, + { + "m_Id": "f2903158b3624759bca1fcd843698078" + }, + { + "m_Id": "30ca940fe2794c949f2a1d4d2caaa446" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "facc84930f544fd7a0205a6176b18ac0", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "fb15d0ba56d54a6192f11e107aeb5fa8", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "fb5e1e2a67c14602808358686bb75091", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "fc2e62201c5847e798fd939314413fcd", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fd0b096ed5b74f9e9ec51327be200731", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "fdb77c3e92ee497b88ca5dc46dc45350", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4208.0, + "y": -2371.0, + "width": 180.0, + "height": 180.0 + } + }, + "m_Slots": [ + { + "m_Id": "4328cdbf78b94c038fd614c59bfe1cac" + }, + { + "m_Id": "04dfcc9ff13a4bf282ed46faec39d15c" + }, + { + "m_Id": "71dd947935b64ce38f0d25406dde447b" + }, + { + "m_Id": "61a6ac5f29344d109411f26850ab0a96" + }, + { + "m_Id": "44806230fa384c1e95f9c5918a14f056" + }, + { + "m_Id": "4eb3c00a1ca44e10be833b7ca61ff059" + }, + { + "m_Id": "57abc172afd449e2a4d567f93432507b" + }, + { + "m_Id": "cda5e3b4c1054bf3a65c0b7ec6bc778a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "fe11fa80cc1847a5a37f6757d521cf25", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph.meta new file mode 100644 index 0000000..54c945e --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a3d800b099a06e0478fb790c5e79057a +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph new file mode 100644 index 0000000..d7d31de --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph @@ -0,0 +1,11629 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "386c36a1c4c34ea29deb680fb82cfe8b", + "m_Properties": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "4a0041116f73406db7a62ae80ff54ef4" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "bafc3d388c1e444e820897b9a3d6029a" + } + ], + "m_Nodes": [ + { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + }, + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + } + ], + "m_GroupDatas": [ + { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 5 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 6 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 1 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": -2624.000244140625, + "y": -3709.000244140625 + }, + "m_Blocks": [ + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": -2624.000244140625, + "y": -3424.000244140625 + }, + "m_Blocks": [ + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"fileID\":10210,\"guid\":\"0000000000000000e000000000000000\",\"type\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "TextMeshPro/SRP", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "94300469581b4924ac7dda496811d45d" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "007c75c776ac4f1babe9cd7ae1fc4f14", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5868.0, + "y": -3787.000244140625, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1356dc7cbdfa4199a6535d3bbf4cd536" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "013228b0fdf1424097798f0973a9a4fb", + "m_Title": "Face Texture", + "m_Position": { + "x": -4779.494140625, + "y": -2948.97265625 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "02559cbe5ad441a3904ccb75ded2b2c5", + "m_Id": 5, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "03182b3263304258b265266325c21f65", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "045c4f6b050549c7a0efb208e6349779", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "04dc152dd2ba4d519391577eb1156235", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4500.0, + "y": -2747.0, + "width": 151.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "3d04f5ba6e7b40d281f22eb424145acd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "04dfcc9ff13a4bf282ed46faec39d15c", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "05805bc6fcc941fd889922555c6c86d7", + "m_Guid": { + "m_GuidSerialized": "fe84e680-4cee-4ca5-be86-2e293a9ba093" + }, + "m_Name": "Ambient Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_05805bc6fcc941fd889922555c6c86d7", + "m_OverrideReferenceName": "_Ambient", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "0580d4b7e3a049049569f4508643a724", + "m_Guid": { + "m_GuidSerialized": "eefb88c5-7665-45dc-b3c2-7cf98b9990d6" + }, + "m_Name": "Softness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_D64EC33D", + "m_OverrideReferenceName": "_Softness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "068ae649e00b40e198ec5a30ad741fab", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0699eea947fc426cbfeb8744cf120222", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "07946387933e416db576b677f0711e5f", + "m_Guid": { + "m_GuidSerialized": "21d612fb-8153-41f8-9e2f-9de044c19fbf" + }, + "m_Name": "_FaceTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1A08AD4A", + "m_OverrideReferenceName": "_FaceTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "082e9706dffc4c188270980d4e44ce0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0848ba750e0341198cf0bbd413e0efe4", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "09b1b86c1c074337a4c439d3a308dd2e", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0a67ca5280214bd794dc0ad66b5710a9", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0b57f2d35157477ab2b29a5aac14ae8b", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0ba4932e164847878ddb7b7bcff96985", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0c4dc51f26484c26ad88a3fe4002abcd", + "m_Id": 2, + "m_DisplayName": "Color (1)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "0d6a57754b824f6db9cefa6953bc06a9", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0d7878dd226d4cfb81a991dc312309fc", + "m_Id": 0, + "m_DisplayName": "Underlay Dilate", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 2, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalUnlitSubTarget", + "m_ObjectId": "0eeb5490760e492f8c9691086fa00929" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "0f7ffb6d2de4447f9736780cbcee8e07", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0fac35636fca4474a6afaefc3c757775", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "105b1ed1aa714e41bbe1ef5472bdb11f", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -4233.0, + "width": 158.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "8a08179f99d649d289b8053d5fa0ad22" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "109f638d1f9b49d4991d6d21a86d4eb7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5068.0, + "y": -3182.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "880bb02c6c6b49b18aa6ebc66dc566a0" + }, + { + "m_Id": "1b9cd8f5f4004e2eaf8afbaab803bc04" + }, + { + "m_Id": "b224a1cf80604103ad085c799995f3c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "10a99c07aad742349d258db16838c129", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1196ae398cc348349ab0c1a23fdab4bd", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1356dc7cbdfa4199a6535d3bbf4cd536", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "14ad19bf20a140dd88d58452d7df688b", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 1.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "150533bad8e2424aaa2c74e253af8592", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -3486.666259765625, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "72fb5a0d7796446b9e2b929cb32facdc" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "163beb4431c34f538340bc0af0991e6f", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3415.000244140625, + "y": -3462.0, + "width": 120.00000762939453, + "height": 149.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "4c334de01ecd429baa7652fc6002536b" + }, + { + "m_Id": "e2d28f29bbac4983a401574480b5ca28" + }, + { + "m_Id": "6a7af6143e114a538663e71f56731a21" + }, + { + "m_Id": "3e25be96bb3747738c238cf3a741d5df" + }, + { + "m_Id": "4907352322c644ebacdf2ca30f2994fd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "19075add867e4757b9520d18fe8de1d0", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4261.33349609375, + "y": -3197.33349609375, + "width": 124.66650390625, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c28ee9109014fa086e5de7a3993341d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0580d4b7e3a049049569f4508643a724" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1b9cd8f5f4004e2eaf8afbaab803bc04", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1bdde3efd3b7464b8934c555be0f8a48", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "1be90d4f96a841748b0c95219b12ad27", + "m_Guid": { + "m_GuidSerialized": "4c91c146-43bb-4de8-948a-fbf8b1da10e1" + }, + "m_Name": "Bevel Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_97690701", + "m_OverrideReferenceName": "_BevelOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": -0.5, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "1c4df61c2fea404eb3b87b270d7c59bc", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4280.0, + "y": -3221.33349609375, + "width": 145.3330078125, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "f864c900600e427ba7793f00c715e971" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1d35fa1fb5004f96a65ace54fbe4f1ad", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1d7d96a5770b4f8ebb162bdbde020bca", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1db37082bf844442804487b4944352de", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1df58cfa4dad4c449d01ee1c5ea05f2e", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "1e12726617b24675958e942eb62e4b09", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4772.0, + "y": -4404.0, + "width": 145.00001525878907, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "0848ba750e0341198cf0bbd413e0efe4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1f247658c7ba45fb93c41f51e21acb0d", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1f46181633594ae0a1fb2adb76b42981", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "200245fc8bbe4826b209ab5f7ffe074c", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "204dacb5a95b424facf11cb6f65bd188", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "215a82c127204988b751de7d3a39b955", + "m_Id": 6, + "m_DisplayName": "Outline", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Outline", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "215b30ae27784ec3a13360a9029af283", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "21a7a380e66d42e780e2a2a1baa630d5", + "m_Guid": { + "m_GuidSerialized": "b2d0099f-e605-49f5-9959-e7cacae37aa3" + }, + "m_Name": "Bevel Type", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_21a7a380e66d42e780e2a2a1baa630d5", + "m_OverrideReferenceName": "_BevelType", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e", + "m_Guid": { + "m_GuidSerialized": "cd167d3a-7465-4d5a-86fc-0f22dc0ef908" + }, + "m_Name": "Outline Color 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5550EB71", + "m_OverrideReferenceName": "_OutlineColor1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "232b1aa09e67479abae141d3c76d3c5b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "256d41e89a204d22951450de1c38051d", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "26e48352a08441bfa694dcea54c06e36", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "281bcee4777040f8a31ee0e10344e98d", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "285f6a9863d54ed2a8150727ad749456", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4145.0, + "y": -2406.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "b42e6dbfbc864097af182cbff5c0c1fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.IsFrontFaceNode", + "m_ObjectId": "2a552a0b828f457c911aa19561e410ae", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Is Front Face", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4282.0, + "y": -3681.3330078125, + "width": 121.99999237060547, + "height": 77.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "2ef1d888dc9d49e59d6a6950897ddc93" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "2ac79705aa9e415dbb74ec215233fd1b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Composite (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3277.3330078125, + "y": -3841.33349609375, + "width": 218.666748046875, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "a75f7ac601c446469802fe7754c1f279" + }, + { + "m_Id": "8c38a5d8327f456e9783740c05382619" + }, + { + "m_Id": "facc84930f544fd7a0205a6176b18ac0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Composite", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2b01ea3023e34c94af1754e4dcea8f2e", + "m_Id": 0, + "m_DisplayName": "Face Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2bf5f2fdd2984599b7323d10cfb1d240", + "m_Id": 1, + "m_DisplayName": "Filter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Filter", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "2c10b97b92c947ceb307a93759c0228b", + "m_Guid": { + "m_GuidSerialized": "6be0b8ff-a766-4c6b-a6e4-3a72758ac95f" + }, + "m_Name": "Bevel Amount", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B01DD93E", + "m_OverrideReferenceName": "_BevelAmount", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2c7a9460724b47daad8df1be144de7c6", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "2d0a269511e34bd1ba9056d2c939dff2", + "m_Guid": { + "m_GuidSerialized": "edbe73dc-53ab-4bc1-9d64-ab36e0e05f03" + }, + "m_Name": "_FaceUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_3A8E0F13", + "m_OverrideReferenceName": "_FaceUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "2db15d90c2204143b225ec4ef08d0755", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4350.0, + "y": -2396.0, + "width": 163.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "def8e0b9d8384982bc5b4c32d877e458" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "2e4eb1ef08bb44178c82e53872485e0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2ef1d888dc9d49e59d6a6950897ddc93", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 2, + "m_Value": true, + "m_DefaultValue": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "30ca940fe2794c949f2a1d4d2caaa446", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "319916a5921343f7b7eef0e50dc93def", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4760.0, + "y": -3245.000244140625, + "width": 184.0, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "d219977210094c0082c517d8dc00c8bb" + }, + { + "m_Id": "f48f04ad45d046a8b88e71731ed506e7" + }, + { + "m_Id": "e6e80c6b0db545cda26b079a9a78fbb3" + }, + { + "m_Id": "c6bdb985bc16435fa72f5a3c81bb633c" + }, + { + "m_Id": "d1a17e42e7a04dc38984e3c01149445b" + }, + { + "m_Id": "fb15d0ba56d54a6192f11e107aeb5fa8" + }, + { + "m_Id": "c35312edaa2344788b1964ee2f63a236" + }, + { + "m_Id": "c88fcbaeea954a5f9c68c339fa8b604d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "34a67e0fef884f9399e674d9eeaf720c", + "m_Id": 6, + "m_DisplayName": "Color3", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color3", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "34a72a5ebb04402384a4fd3748111a37", + "m_Id": 0, + "m_DisplayName": "Alpha Clip Threshold", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AlphaClipThreshold", + "m_StageCapability": 2, + "m_Value": 0.0010000000474974514, + "m_DefaultValue": 0.5, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3535ae87c6dd4769b52b20d9eca61069", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "35cbea6373dd4e4f8d0fea36e8add392", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "36a0c473c4c04c3a930dd38f3920d410", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "36f1b4d96f2941c39e5cd95d9c1d2ce6", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6314.6669921875, + "y": -3285.3330078125, + "width": 144.6669921875, + "height": 129.33348083496095 + } + }, + "m_Slots": [ + { + "m_Id": "65b3dc13b2b6484283ffe5abfe87a06a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "373f1de8db6c429c9d46c781f741d7a4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3802c81c3be24823aa1d7c9997a33c29", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "3915c1927ffe49f8967304321cfbe497", + "m_Id": 4, + "m_DisplayName": "Atlas", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Atlas", + "m_StageCapability": 3, + "m_BareResource": true, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "39a382d661e2484da71f04c43f48e55f", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "39f2f84f30304d859fb07569e2695f60", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3554.000244140625, + "y": -3462.0, + "width": 116.00000762939453, + "height": 94.00000762939453 + } + }, + "m_Slots": [ + { + "m_Id": "4b2d9ea03bf64fa19dcae1511d2581da" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "3c50439118b2496f9e390021b0964606", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.AlphaClipThreshold", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3028.0, + "y": -3054.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "34a72a5ebb04402384a4fd3748111a37" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.AlphaClipThreshold" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3d04f5ba6e7b40d281f22eb424145acd", + "m_Id": 0, + "m_DisplayName": "Face Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3db1608e927e4102a3c3a88e9fcab39a", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3dccd64e7f324bc1a75c1479d7a67c51", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "3e231021af7b47ba97f2871e7f25d0fe", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2934.000244140625, + "y": -3466.0, + "width": 141.33349609375, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "6ccaced3889e4503a9414d808ec33981" + }, + { + "m_Id": "7f3d71a6c96847c099da45f95aafbecb" + }, + { + "m_Id": "d8edec16956c4f15b7d51d6ec10753f4" + }, + { + "m_Id": "39a382d661e2484da71f04c43f48e55f" + }, + { + "m_Id": "8764669016f6442f8152593c18a649d7" + }, + { + "m_Id": "26e48352a08441bfa694dcea54c06e36" + }, + { + "m_Id": "3e94a0d106064bdb864c960512ef4026" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3e25be96bb3747738c238cf3a741d5df", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "3e372195f4bd4845852a37839e5b602d", + "m_Guid": { + "m_GuidSerialized": "60abd046-2a1a-48cd-a0af-2f702f7f53ab" + }, + "m_Name": "_MainTex", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_90CBF488", + "m_OverrideReferenceName": "_MainTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":28684132378477856,\"guid\":\"8f586378b4e144a9851e7b34d9b748ee\",\"type\":2}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "3e94a0d106064bdb864c960512ef4026", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "3ec4797e381747829ef4712c85fcf7a1", + "m_Guid": { + "m_GuidSerialized": "020d65cc-50a8-4b8a-a624-90d7b489f549" + }, + "m_Name": "Specular Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_3ec4797e381747829ef4712c85fcf7a1", + "m_OverrideReferenceName": "_SpecularPower", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 4.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "3fdf4b7bc5d4426492dcc057603ef4a6", + "m_Guid": { + "m_GuidSerialized": "675d2567-3fca-4da6-9462-dfa4924950f1" + }, + "m_Name": "_OutlineUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_D66D89E6", + "m_OverrideReferenceName": "_OutlineUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "400d0b6c95dd4540ad3da3e8cb7e50b2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "41986ac6400d46709d0ef043a67f6b34", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "41b9b79b3859472882bcea393703eec0", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "424dbeeb009344efa29c304c4979e3d6", + "m_Guid": { + "m_GuidSerialized": "314c37de-c6f2-4463-866d-8588f6fc119e" + }, + "m_Name": "Diffuse Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_424dbeeb009344efa29c304c4979e3d6", + "m_OverrideReferenceName": "_Diffuse", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "42a586e4f6ec40eeaba891b7fd133864", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4934.0, + "y": -4442.99951171875, + "width": 133.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "da7a06d393a44089842070d51d2aa0a6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "42cadae0923e4969b50bbc3f78185934", + "m_Title": "Face + 3 Outlines + Underlay", + "m_Position": { + "x": -5437.0, + "y": -3558.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4328cdbf78b94c038fd614c59bfe1cac", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "44317f2e371447e2a8d894f8a021a235", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Layer1 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4004.999755859375, + "y": -4173.0, + "width": 191.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "10a99c07aad742349d258db16838c129" + }, + { + "m_Id": "b85d677872b44421bf5536f42ba0267c" + }, + { + "m_Id": "75aba700d74d4b2687bf3166cf1da3e2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer1", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "44806230fa384c1e95f9c5918a14f056", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4488af8ff6a7421298a7e827f567263b", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4109.0, + "width": 158.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "66f69ef16eac4eb48357bde804cf3c39" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "4648b46ad29a4008a80de4f8a5a5b813", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4576.0, + "y": -2437.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "b2baf44eae52473cb6cda7b1debece01" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "46fbf3eeb0ea4470869cba7443249295", + "m_Guid": { + "m_GuidSerialized": "be87c5a3-e361-4b95-89c8-911c39a51c0d" + }, + "m_Name": "Outline Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_A0B54237", + "m_OverrideReferenceName": "_OutlineTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "47d020251e9841a5b1f0fd64396026a1", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "48390d02257d41bf98eace1deaa4c539", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "8036d0e6090b456e9b4ea87227868236" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "484b51c50485473b819c4f05087b32d7", + "m_Title": "Underlay", + "m_Position": { + "x": -5253.0, + "y": -4542.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4907352322c644ebacdf2ca30f2994fd", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "49dabfd48a78475882e664526b483ce1", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "49e7c3ad55ce458797f0e60c950cb965", + "m_Guid": { + "m_GuidSerialized": "31b55db9-0da1-4ec4-af2b-d83747ed5bc4" + }, + "m_Name": "Underlay Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_CE9DEDB3", + "m_OverrideReferenceName": "_UnderlayOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "4a0041116f73406db7a62ae80ff54ef4", + "m_Guid": { + "m_GuidSerialized": "a2d96028-f92f-4076-8376-42249ca40935" + }, + "m_Name": "_ScaleRatioA", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "_ScaleRatioA", + "m_DefaultReferenceName": "_ScaleRatioA", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4a66dcbe712a4d40bd8f355b834594b5", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "4abff6ff92fa4a05b203f10580988335", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4293.3330078125, + "y": -3497.99951171875, + "width": 140.66648864746095, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "b015d1b7e4134c59baf6851e7649802c" + }, + { + "m_Id": "d9dc4839ee2847999110bdb234d6041a" + }, + { + "m_Id": "91d6a9a5fbc04ea49075cb51835e7264" + }, + { + "m_Id": "f42ad06b3c6a45d3ab33de904c063412" + }, + { + "m_Id": "ed6c215a65584deeaefad1d2c7743044" + }, + { + "m_Id": "edbee7a8952b46529ac5ad0365775774" + }, + { + "m_Id": "70337a74f6ad4b7bb6befc825219bab1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4b2d9ea03bf64fa19dcae1511d2581da", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4bda5c294e1949138d033640e1d385b4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4c28ee9109014fa086e5de7a3993341d", + "m_Id": 0, + "m_DisplayName": "Softness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4c334de01ecd429baa7652fc6002536b", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4d1cb1a475df49f9a148195a65f5453a", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4d9ce48719d143748f9f8e22da6f9ddc", + "m_Id": 5, + "m_DisplayName": "TextureWidth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureWidth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4e64dac49ddc47c3b5b1e27b17a08304", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "4e90ca54c0cc46a18ea600be7c80413a", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "4eb3c00a1ca44e10be833b7ca61ff059", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4f194ff591484e908fc2bcdacbcf2570", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4255.0, + "y": -2771.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "2b01ea3023e34c94af1754e4dcea8f2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "509e6f38505b4b0695b263706a55028f", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "51378bae98a94c309785d14cd5cbb453", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "GetSurfaceNormal (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4067.333251953125, + "y": -3881.99951171875, + "width": 263.9999694824219, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "5b0077c23eae443887872f84227deccc" + }, + { + "m_Id": "3915c1927ffe49f8967304321cfbe497" + }, + { + "m_Id": "4d9ce48719d143748f9f8e22da6f9ddc" + }, + { + "m_Id": "ebd6d75abcb84108bcadbfe7ee5f6244" + }, + { + "m_Id": "ef9738ec7e894772a14e9dce441c16c6" + }, + { + "m_Id": "9eeec1a9713045af8845cea263d5ea48" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GetSurfaceNormal", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "51f76f8a53ad43a4ad028426548ce9ba", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "52798bdb86f6400e86489a7a368e9f8b", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6460.6669921875, + "y": -3113.333251953125, + "width": 135.33349609375, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "1df58cfa4dad4c449d01ee1c5ea05f2e" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "53073e5ea924459fa6681a4943e9f947", + "m_Guid": { + "m_GuidSerialized": "5fdac24e-2d58-4471-80ce-79c3ab9a2564" + }, + "m_Name": "Outline Color 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_DBAB5AEC", + "m_OverrideReferenceName": "_OutlineColor2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.009433984756469727, + "g": 0.02534518577158451, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "54d7a93ffec5490aa4591da23a21b693", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "55ffa45ec3654d5e88089fb40d2b0465", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "56c25395796e4d2fbe5c892d428d1620", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5071.99951171875, + "y": -3427.0, + "width": 129.99998474121095, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "9eb8137a6c2e41bbafdc8b0732dd47a3" + }, + { + "m_Id": "36a0c473c4c04c3a930dd38f3920d410" + }, + { + "m_Id": "068ae649e00b40e198ec5a30ad741fab" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "57abc172afd449e2a4d567f93432507b", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "582d6e289dbe4fdca7cf0307273eaa2f", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "59bd90a849624124bae6464ee3669aa6", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3972.0, + "y": -2385.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "2e4eb1ef08bb44178c82e53872485e0f" + }, + { + "m_Id": "8695190a5e614f2d90081871a8a06fc2" + }, + { + "m_Id": "81bdb47901ef48e5a588c6724b1b0142" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "59cea37675824d99995b370f09cef20a", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "5b0077c23eae443887872f84227deccc", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5b3ff4ee364f4d7a923b530ad60d8762", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5bd258837c514ff7ab0bf7027e762c18", + "m_Guid": { + "m_GuidSerialized": "2d8f3ee9-1307-4b58-a60d-526e86b07109" + }, + "m_Name": "Bevel Roundness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_AB6A015F", + "m_OverrideReferenceName": "_BevelRoundness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5da82bf481f8489ebd05e997f617f51b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": 4.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5e42524569844befad16fda5a94eb9cb", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5fbe253f3e444f2aa8ac717f9c856619", + "m_Guid": { + "m_GuidSerialized": "0a61c93f-6430-4aa6-af07-79bc3b411ccd" + }, + "m_Name": "Bevel Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B50BBFCC", + "m_OverrideReferenceName": "_BevelWidth", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61133d79a89048c195f54939b2a1d30a", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61a6ac5f29344d109411f26850ab0a96", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6271438664e74b3fbf723bd6a1f50f8b", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "62bc551cea604e88b7858cc37d96a98a", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "636180f6e0504f2baaa5cc086980cb47", + "m_Guid": { + "m_GuidSerialized": "c1223e37-093d-4d5a-b2b0-cd9cc3e4f88e" + }, + "m_Name": "Outline Offset 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_636180f6e0504f2baaa5cc086980cb47", + "m_OverrideReferenceName": "_OutlineOffset1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "63c7cd57fc3c45a9a97b514fdae32693", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5235.99951171875, + "y": -3386.999755859375, + "width": 141.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c422a9a9ff824176aad2241f58c44d0b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "641eda269d7b4da9acb65f8d50035ea9", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "65b3dc13b2b6484283ffe5abfe87a06a", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "65c8e64a7535466e933eed08a2f77532", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4759.99951171875, + "y": -3498.666259765625, + "width": 186.0, + "height": 251.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "256d41e89a204d22951450de1c38051d" + }, + { + "m_Id": "0a67ca5280214bd794dc0ad66b5710a9" + }, + { + "m_Id": "ebbd94a7102a4457a48ac492de3bff14" + }, + { + "m_Id": "6271438664e74b3fbf723bd6a1f50f8b" + }, + { + "m_Id": "c9b722d107ce4cd6a748c883472b9b0f" + }, + { + "m_Id": "74cf69e61bef44589521f1bf2bf3c59a" + }, + { + "m_Id": "6e532f83d1c44e839bcfc5845d3b01d6" + }, + { + "m_Id": "cb5e9f9567e84f8fa5463efc0e256e19" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "66f69ef16eac4eb48357bde804cf3c39", + "m_Id": 0, + "m_DisplayName": "_UnderlayColor", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "67a519f507384ff1861df5d8d5b486be", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4278.0, + "y": -3939.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c3e6d7c20c184bf39fd8822130e693e7" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "68ec7c31365549d6a8ce883edfc02de2", + "m_Id": 4, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6a7af6143e114a538663e71f56731a21", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "6b2f65c1463f4f7bad16c54a95d2fe75", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5070.0, + "y": -3301.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "1d35fa1fb5004f96a65ace54fbe4f1ad" + }, + { + "m_Id": "fa6de3be9f5b4411b5081b49e645f424" + }, + { + "m_Id": "400d0b6c95dd4540ad3da3e8cb7e50b2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6ccaced3889e4503a9414d808ec33981", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6dfc1177dd0541a7a780fbf911ad1956", + "m_Id": 0, + "m_DisplayName": "_OutlineTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e13f3cd573c467a94379f45d96cb690", + "m_Id": 2, + "m_DisplayName": "SSR", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "6e532f83d1c44e839bcfc5845d3b01d6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6e8946a245e842b38231d4a241bfb3ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3026.0, + "y": -3110.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "ef0b93f78372439696f50711eaf57d90" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "6fbdcc5a972b4fa883dc5f21e525a376", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "70337a74f6ad4b7bb6befc825219bab1", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "712da461f71a454db59d349f752d41ee", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "71dd947935b64ce38f0d25406dde447b", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "724e17584e97443e9e285dfa7253c8e3", + "m_Id": 0, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 2, + "m_Value": 0.15000000596046449, + "m_DefaultValue": 1.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "72fb5a0d7796446b9e2b929cb32facdc", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "7444469eb9884253819add9ef96baa25", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4298.0, + "y": -3809.99951171875, + "width": 144.66648864746095, + "height": 129.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "03182b3263304258b265266325c21f65" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "748c31bbcecc4b30bec2e42c0612175b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "74b41464cbed4e9e8e23af5ab9be40cf", + "m_Guid": { + "m_GuidSerialized": "41afbdcb-f3ae-4340-8973-1c1998c992a2" + }, + "m_Name": "Outline Offset 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "74cf69e61bef44589521f1bf2bf3c59a", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "757174b6f25040fdbb20355a21752222", + "m_Id": 0, + "m_DisplayName": "Outline Offset 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "75aba700d74d4b2687bf3166cf1da3e2", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "75c5657544c648058b20cea090f48dbf", + "m_Id": 0, + "m_DisplayName": "_OutlineUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "767769f736d5478cba5f10a415e28e7f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "773b90134e894e429203c0c83e80b9de", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "77e28f3e930b4c249145630ec961af95", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "79147f6986644769b58d9ed64fe771e1", + "m_Id": 0, + "m_DisplayName": "OutlineMode", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7984fd094e1147bdabb4e26fbd3d31c8", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3244.000244140625, + "y": -3414.0, + "width": 130.0, + "height": 118.00000762939453 + } + }, + "m_Slots": [ + { + "m_Id": "082e9706dffc4c188270980d4e44ce0f" + }, + { + "m_Id": "f2a351a5375c441b8d9ab7e2c9545a77" + }, + { + "m_Id": "41986ac6400d46709d0ef043a67f6b34" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "7a046f410ce64aa88438b0bfd412c045", + "m_Guid": { + "m_GuidSerialized": "d47271f5-5a84-47bf-a09e-c825d2aeb013" + }, + "m_Name": "Outline Color 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_551702C5", + "m_OverrideReferenceName": "_OutlineColor3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "7a0f504e4175406dbd8134250f4e350b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7a80e8839f0e4a1d9a6c0814f8793ee6", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4931.0, + "y": -3452.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "6fbdcc5a972b4fa883dc5f21e525a376" + }, + { + "m_Id": "0ba4932e164847878ddb7b7bcff96985" + }, + { + "m_Id": "9178663316db43d582f1c4a127d307c6" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7acfafd73b8c4dfab8c55c18a887e087", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "7b8a19bd115e4167a25b59cb3218a817", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "7c27ccb2c2dc4ca59c5438c3358630ca", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7d7696aa6d184b4fb9c316a9dec37aee", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4928.0, + "y": -3326.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "4d1cb1a475df49f9a148195a65f5453a" + }, + { + "m_Id": "47d020251e9841a5b1f0fd64396026a1" + }, + { + "m_Id": "62bc551cea604e88b7858cc37d96a98a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7d78a616c2754cc28d1f32cf66ade611", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3973.0, + "y": -2796.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "d9bcb754db834583b6518c5ed5152114" + }, + { + "m_Id": "861d4258049a4a3e8164f7297090f88e" + }, + { + "m_Id": "a7c06457d7454693a8bc3dc95257b2c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "7e0fadb2533f496192c1ad3e78642010", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4188.0, + "width": 173.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d48c3871e3064027a10ae9f4babd3be0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f2e6b5f15364ed9835d67d0cf4f8f65", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2586.0, + "y": -3592.0, + "width": 200.0, + "height": 41.0 + } + }, + "m_Slots": [ + { + "m_Id": "85ff8667d72947edada4e9fb4ff60559" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7f3d71a6c96847c099da45f95aafbecb", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "8036d0e6090b456e9b4ea87227868236", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "80e665a5eeb64730a51742f698bf0d48", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "8135ca333f8f4ea78163743e6ec1f55c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4050.666259765625, + "y": -3139.99951171875, + "width": 121.99999237060547, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "d6a6a119394e4082a11bc024a6e42ef8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "81bdb47901ef48e5a588c6724b1b0142", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "81e8ed0534534674a74263e6161a2a1a", + "m_Guid": { + "m_GuidSerialized": "78aab961-c4a8-41f3-b203-1239c3b33b13" + }, + "m_Name": "Underlay Dilate", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_D48690B9", + "m_OverrideReferenceName": "_UnderlayDilate", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "82af2db1018543d7832af96c1cfc981f", + "m_Guid": { + "m_GuidSerialized": "37906c7b-9a3a-454b-a62a-9aa097e64bde" + }, + "m_Name": "Light Angle", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_82af2db1018543d7832af96c1cfc981f", + "m_OverrideReferenceName": "_LightAngle", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 6.28000020980835 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "82d5443fe54d4a3b9420f8745d00a632", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": 8.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "849275cac05e4ca8bd0b38ab7ae43bf8", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "84dc74cdbd8c45e1b189e4fd9a69942d", + "m_Id": 0, + "m_DisplayName": "Outline Offset 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "85a1ad8e741e41759002e8cdc8cd0b96", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "ScreenSpaceRatio (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6112.0, + "y": -3308.0, + "width": 258.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e13f3cd573c467a94379f45d96cb690" + }, + { + "m_Id": "8e6ed600f6504f4083092f5b511e44c4" + }, + { + "m_Id": "93b161cce4504cb79c97b6d8db178de7" + }, + { + "m_Id": "2bf5f2fdd2984599b7323d10cfb1d240" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ScreenSpaceRatio", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "85b5940eb77e4625812ded7215bab8d7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4050.666259765625, + "y": -3095.99951171875, + "width": 121.99999237060547, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "ada023d617104472b8ab75a81558c0a1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "85ff8667d72947edada4e9fb4ff60559", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "861d4258049a4a3e8164f7297090f88e", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "867a4ae13c0d4a028c71bc1063824c14", + "m_Guid": { + "m_GuidSerialized": "d483c212-0a30-4f6d-b94d-9abbc83a6522" + }, + "m_Name": "Outline Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_C68C9E14", + "m_OverrideReferenceName": "_IsoPerimeter", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 2, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "8695190a5e614f2d90081871a8a06fc2", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8764669016f6442f8152593c18a649d7", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "880bb02c6c6b49b18aa6ebc66dc566a0", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "88253223d2c34ecfab92b0c344048f94", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "ComputeSDF (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4323.0, + "width": 227.99998474121095, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "c52a1744a9a14989b0ae452ad6de6061" + }, + { + "m_Id": "a03db80c558b4f87a330c5ae0a9443a5" + }, + { + "m_Id": "8f1b1d1e8ff24b3284993e52354e54fa" + }, + { + "m_Id": "5da82bf481f8489ebd05e997f617f51b" + }, + { + "m_Id": "82d5443fe54d4a3b9420f8745d00a632" + }, + { + "m_Id": "61133d79a89048c195f54939b2a1d30a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8902cb30b1684db8b996562e0140cb18", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8a08179f99d649d289b8053d5fa0ad22", + "m_Id": 0, + "m_DisplayName": "Underlay Offset", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8a5d204e1abd4f6894607d1a497f6e69", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8b66f4e6bc9d4662b3218ac33a69839f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8c38a5d8327f456e9783740c05382619", + "m_Id": 3, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8cbd81814903479ea1d3151c1f38183e", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "8cf8aae64c1d443f9303126886b40f17", + "m_Guid": { + "m_GuidSerialized": "8d78c9a5-aaef-41fb-af68-2358e401d7ac" + }, + "m_Name": "_UnderlayColor", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_2F5FE804", + "m_OverrideReferenceName": "_UnderlayColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6ed600f6504f4083092f5b511e44c4", + "m_Id": 0, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "8ed907a2cc7949b68a283ae243ea1977", + "m_Guid": { + "m_GuidSerialized": "36803443-a9bc-4f3c-a4f2-7d66a5417ac1" + }, + "m_Name": "Outline Offset 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8f1b1d1e8ff24b3284993e52354e54fa", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9147636b0cfa466a9b37a013d8f693bf", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5567.0, + "y": -3862.000244140625, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a4f471e3221c4134b291bd9d2ba22db6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "9178663316db43d582f1c4a127d307c6", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "91890fe48ebe4717aea61ecaf3ad4861", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3114.000244140625, + "y": -3414.0, + "width": 120.00000762939453, + "height": 149.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "3dccd64e7f324bc1a75c1479d7a67c51" + }, + { + "m_Id": "e444f2c81d1e48329fa2c91005277e8d" + }, + { + "m_Id": "b2c26292b7434733878a9b042f44de89" + }, + { + "m_Id": "964fea1fd4b24f4daf5bef84c4b45118" + }, + { + "m_Id": "deac82280a2b43078e0e40863e2d974c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "91d6a9a5fbc04ea49075cb51835e7264", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "928621a3ca2d41c89a10336bbbc81ddc", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "93b161cce4504cb79c97b6d8db178de7", + "m_Id": 3, + "m_DisplayName": "TextureSize", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureSize", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget", + "m_ObjectId": "94300469581b4924ac7dda496811d45d", + "m_Datas": [], + "m_ActiveSubTarget": { + "m_Id": "0eeb5490760e492f8c9691086fa00929" + }, + "m_AllowMaterialOverride": false, + "m_SurfaceType": 1, + "m_ZTestMode": 4, + "m_ZWriteControl": 0, + "m_AlphaMode": 0, + "m_RenderFace": 0, + "m_AlphaClip": true, + "m_CastShadows": true, + "m_ReceiveShadows": true, + "m_AdditionalMotionVectorMode": 0, + "m_AlembicMotionVectors": false, + "m_SupportsLODCrossFade": false, + "m_CustomEditorGUI": "TMPro.EditorUtilities.TMP_SDFShaderGUI", + "m_SupportVFX": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "945b45993dd84a979755b98c48138f72", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "952d0fa5cd744df0b434cd38e9a90b93", + "m_Guid": { + "m_GuidSerialized": "ce395871-ddeb-47c3-a31d-07855800c197" + }, + "m_Name": "_UnderlaySoftness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_F2B9E3EF", + "m_OverrideReferenceName": "_UnderlaySoftness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "95928bcb6a284b8d88105a84c2e1d3ce", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4744.0, + "y": -2591.0, + "width": 155.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d880558893fb442b9320cf55885d1117" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "964fea1fd4b24f4daf5bef84c4b45118", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "98934a69591249d5b8b92b39045359a3", + "m_Title": "Outline1 Texture", + "m_Position": { + "x": -4746.0, + "y": -2497.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "998db5e5901e45b29040eb2099370071", + "m_Guid": { + "m_GuidSerialized": "6f383614-f2ad-4269-be8f-87b0ecb03cf0" + }, + "m_Name": "Bevel Clamp", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_5BD7E808", + "m_OverrideReferenceName": "_BevelClamp", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "9c228fac287d446296b91a4acf5cec59", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4569.0, + "y": -3498.000244140625, + "width": 184.0, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "582d6e289dbe4fdca7cf0307273eaa2f" + }, + { + "m_Id": "1db37082bf844442804487b4944352de" + }, + { + "m_Id": "8b66f4e6bc9d4662b3218ac33a69839f" + }, + { + "m_Id": "4a66dcbe712a4d40bd8f355b834594b5" + }, + { + "m_Id": "a0285c9c381a49cba194709efa0a7c85" + }, + { + "m_Id": "b2728d0dd3ce40678867c94a7d977916" + }, + { + "m_Id": "e141833aa78b4fd59ecad949beb43a78" + }, + { + "m_Id": "51f76f8a53ad43a4ad028426548ce9ba" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9c26fdddba244d36a854298c00473247", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "9d3c3383d5934a17bf9efbb7fd9e9043", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5412.0, + "y": -3315.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "232b1aa09e67479abae141d3c76d3c5b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e6e50a71d9843b49b62ebe1cf7d3d59", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4486.0, + "y": -3865.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "3535ae87c6dd4769b52b20d9eca61069" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e87ce9607e14015a3790c528ca5dfda", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4598.0, + "y": -2251.0, + "width": 167.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "75c5657544c648058b20cea090f48dbf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "9eb8137a6c2e41bbafdc8b0732dd47a3", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "9eeec1a9713045af8845cea263d5ea48", + "m_Id": 6, + "m_DisplayName": "IsFront", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "IsFront", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "9f0de188085746d5a19073da1de85ddb", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4118.0, + "y": -2771.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "7c27ccb2c2dc4ca59c5438c3358630ca" + }, + { + "m_Id": "373f1de8db6c429c9d46c781f741d7a4" + }, + { + "m_Id": "fd0b096ed5b74f9e9ec51327be200731" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a0285c9c381a49cba194709efa0a7c85", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a03db80c558b4f87a330c5ae0a9443a5", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a161b772c7564eee804e3d58f6cb9944", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a3f8b6e8ae7f48e2989a029904401502", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "a455bd79094c4413a7b7dd80ca8b9368", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4573.0, + "y": -2689.0, + "width": 222.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "4e90ca54c0cc46a18ea600be7c80413a" + }, + { + "m_Id": "2c7a9460724b47daad8df1be144de7c6" + }, + { + "m_Id": "55ffa45ec3654d5e88089fb40d2b0465" + }, + { + "m_Id": "e495a9f7a11f4eb89334e83be154ceb9" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateShaderProperty", + "m_ObjectId": "a4ad98d8828c424384229c344ebe2ed0", + "m_Guid": { + "m_GuidSerialized": "f98fc1a2-bb81-4bd1-a207-23d3a90d518e" + }, + "m_Name": "SamplerState", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "SamplerState_a4ad98d8828c424384229c344ebe2ed0", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": false, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_filter": 0, + "m_wrap": 1, + "m_anisotropic": 0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a4f471e3221c4134b291bd9d2ba22db6", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "a535f3bcbeb14622bb177eb6f46e76f4", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4608.0, + "y": -2293.0, + "width": 177.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "6dfc1177dd0541a7a780fbf911ad1956" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "a6bbb32e8d884be9bb36db91fe4b81b1", + "m_Guid": { + "m_GuidSerialized": "6aa76edf-7b80-46ac-add4-406cf1d85493" + }, + "m_Name": "_GradientScale", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_EAE27356", + "m_OverrideReferenceName": "_GradientScale", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 10.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "a6c38edd2e8743a9b057ba8452b9f129", + "m_Guid": { + "m_GuidSerialized": "9fc942ee-4a1d-4ced-a5a6-81893e3ddb63" + }, + "m_Name": "Light Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_a6c38edd2e8743a9b057ba8452b9f129", + "m_OverrideReferenceName": "_SpecularColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "a75f7ac601c446469802fe7754c1f279", + "m_Id": 0, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a7942746b5564dc7bbbae1deb2403022", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "a7c06457d7454693a8bc3dc95257b2c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa2794b8f0e24bf281d22e0fef0647be", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "aa3e347d733e48f7b65d8a8847370eec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "EvaluateLight (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3633.000244140625, + "y": -3805.000244140625, + "width": 179.00001525878907, + "height": 118.00000762939453 + } + }, + "m_Slots": [ + { + "m_Id": "0699eea947fc426cbfeb8744cf120222" + }, + { + "m_Id": "0c4dc51f26484c26ad88a3fe4002abcd" + }, + { + "m_Id": "d5173cc3c6cd4f1998550f3187a3e9c8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "EvaluateLight", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aa87c72ac0e64469acc34f936f00b3d0", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4225.0, + "width": 193.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "0d7878dd226d4cfb81a991dc312309fc" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "abd59150589b436cadf8c9e6f43ccb8e", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "aca823a8188948c782eddaf0f45e1868", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalOS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2542.0, + "y": -3404.000244140625, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "e386b183a18245a796b024022f7f3074" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalOS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "acd0cd5a177f4a97bf23db7219305e3f", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4348.0, + "y": -3905.99951171875, + "width": 185.33299255371095, + "height": 101.33324432373047 + } + }, + "m_Slots": [ + { + "m_Id": "945b45993dd84a979755b98c48138f72" + }, + { + "m_Id": "e51a636b2621440eb94cc802c1cf4bfc" + }, + { + "m_Id": "1bdde3efd3b7464b8934c555be0f8a48" + }, + { + "m_Id": "8a5d204e1abd4f6894607d1a497f6e69" + }, + { + "m_Id": "a161b772c7564eee804e3d58f6cb9944" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ada023d617104472b8ab75a81558c0a1", + "m_Id": 0, + "m_DisplayName": "Outline Color 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aef5c44f84e04c3185e0b93e95e34204", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5233.99951171875, + "y": -3141.999755859375, + "width": 143.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "84dc74cdbd8c45e1b189e4fd9a69942d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b000f852aa984e9dae25b125a4607f4e", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b015d1b7e4134c59baf6851e7649802c", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "b0b352c4503a43d083a64e57352b29a0", + "m_Guid": { + "m_GuidSerialized": "01cfcc78-60aa-4f71-a1e3-8d8df6dae253" + }, + "m_Name": "Reflectivity Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_b0b352c4503a43d083a64e57352b29a0", + "m_OverrideReferenceName": "_Reflectivity", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 5.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 5.0, + "y": 15.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "b1188549725543d485436c2e921ffbb2", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4108.0, + "y": -2890.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "281bcee4777040f8a31ee0e10344e98d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "b163c9f1666644b0bba62cf0e12df7bc", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4333.0, + "y": -2713.0, + "width": 180.0, + "height": 180.0 + } + }, + "m_Slots": [ + { + "m_Id": "cce40479b6284b6fa3174db9f09d0ac9" + }, + { + "m_Id": "80e665a5eeb64730a51742f698bf0d48" + }, + { + "m_Id": "1f46181633594ae0a1fb2adb76b42981" + }, + { + "m_Id": "8cbd81814903479ea1d3151c1f38183e" + }, + { + "m_Id": "cfaf3f3a5a1146e194cddad30c95aada" + }, + { + "m_Id": "b43489e37a5c4df88f15844292a55ec7" + }, + { + "m_Id": "cd7281fb41aa4e61ac0fdf71d4f4bd46" + }, + { + "m_Id": "f01d52cdcb1647aab35782b4af535efd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 1, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "b224a1cf80604103ad085c799995f3c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b2728d0dd3ce40678867c94a7d977916", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b2baf44eae52473cb6cda7b1debece01", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b2c26292b7434733878a9b042f44de89", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b42e6dbfbc864097af182cbff5c0c1fb", + "m_Id": 0, + "m_DisplayName": "Outline Color 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b43489e37a5c4df88f15844292a55ec7", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "b4a40cb6acd441acb83cfe0240bf910d", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4750.99951171875, + "y": -4274.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d0b10e52e21941b183f5f635894c76c8" + }, + { + "m_Id": "0d6a57754b824f6db9cefa6953bc06a9" + }, + { + "m_Id": "773b90134e894e429203c0c83e80b9de" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "b571db753a1948d5a6f1de4e7d0c7238", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5727.0, + "y": -3827.000244140625, + "width": 184.0, + "height": 101.0 + } + }, + "m_Slots": [ + { + "m_Id": "5b3ff4ee364f4d7a923b530ad60d8762" + }, + { + "m_Id": "c183b5bd9bbe45089f93996e73110918" + }, + { + "m_Id": "1196ae398cc348349ab0c1a23fdab4bd" + }, + { + "m_Id": "1d7d96a5770b4f8ebb162bdbde020bca" + }, + { + "m_Id": "49dabfd48a78475882e664526b483ce1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b691728a389a417d9b4f2d02541209c2", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b7f9ac55517141868bfb9d2ad6429792", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b85d677872b44421bf5536f42ba0267c", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "bafc3d388c1e444e820897b9a3d6029a", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "4a0041116f73406db7a62ae80ff54ef4" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "bc9afcb18afa4ccc82d2cdc34d3f4641", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -5537.0, + "y": -3827.000244140625, + "width": 126.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "5e42524569844befad16fda5a94eb9cb" + }, + { + "m_Id": "54d7a93ffec5490aa4591da23a21b693" + }, + { + "m_Id": "aa2794b8f0e24bf281d22e0fef0647be" + }, + { + "m_Id": "200245fc8bbe4826b209ab5f7ffe074c" + }, + { + "m_Id": "fc2e62201c5847e798fd939314413fcd" + }, + { + "m_Id": "fe11fa80cc1847a5a37f6757d521cf25" + }, + { + "m_Id": "de0c6f7f7af94defa6c3dbc6433de9d4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c183b5bd9bbe45089f93996e73110918", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "c234e5216678436195ee1a5914bc79da", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4409.0, + "y": -2338.0, + "width": 222.0, + "height": 142.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "8902cb30b1684db8b996562e0140cb18" + }, + { + "m_Id": "3db1608e927e4102a3c3a88e9fcab39a" + }, + { + "m_Id": "0f7ffb6d2de4447f9736780cbcee8e07" + }, + { + "m_Id": "d4954b7bbbb0412cbc997bcbe7dfa808" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "c35312edaa2344788b1964ee2f63a236", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "c3e6d7c20c184bf39fd8822130e693e7", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "c422a9a9ff824176aad2241f58c44d0b", + "m_Id": 0, + "m_DisplayName": "Outline Offset 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "c478c32c45884c57a62f7b2aa8ddc3b0", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c52a1744a9a14989b0ae452ad6de6061", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c6bdb985bc16435fa72f5a3c81bb633c", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c7d4094601ac4bc1aead609c72b1f1c1", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c7ddee91dc5b48dc828309c77fdb0b88", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4266.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a7942746b5564dc7bbbae1deb2403022" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "c88fcbaeea954a5f9c68c339fa8b604d", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c9b722d107ce4cd6a748c883472b9b0f", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c9d7f0dbae7d422985a1cc87c025e76b", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4284.0, + "y": -3165.0, + "width": 144.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "79147f6986644769b58d9ed64fe771e1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "c9ec735d1a1046769e5601b2c97c849a", + "m_Guid": { + "m_GuidSerialized": "281a9526-c332-4471-a44e-ece4a1e95ef6" + }, + "m_Name": "Face Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_75569DEA", + "m_OverrideReferenceName": "_FaceTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ca2a1083dc014f39ab8af0cdf140866b", + "m_Id": 0, + "m_DisplayName": "_FaceTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "cb3c0c3f08654b068bea44c4ffb15f4a", + "m_Guid": { + "m_GuidSerialized": "21009d12-8d94-4273-b0d0-a8ee0608ddcf" + }, + "m_Name": "OutlineMode", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_cb3c0c3f08654b068bea44c4ffb15f4a", + "m_OverrideReferenceName": "_OutlineMode", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cb5e9f9567e84f8fa5463efc0e256e19", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "cb7117ecb1d047a8b2cb00ed552cb181", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Alpha", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3032.66650390625, + "y": -3029.33349609375, + "width": 200.0, + "height": 41.33349609375 + } + }, + "m_Slots": [ + { + "m_Id": "724e17584e97443e9e285dfa7253c8e3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Alpha" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cc88101667c9488f9c5a716e851c1b21", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cce40479b6284b6fa3174db9f09d0ac9", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "cd7281fb41aa4e61ac0fdf71d4f4bd46", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cda5e3b4c1054bf3a65c0b7ec6bc778a", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "cdddee3a537c464697357f11b966f9b8", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4420.0, + "y": -4483.0, + "width": 156.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "41b9b79b3859472882bcea393703eec0" + }, + { + "m_Id": "c7d4094601ac4bc1aead609c72b1f1c1" + }, + { + "m_Id": "767769f736d5478cba5f10a415e28e7f" + }, + { + "m_Id": "b691728a389a417d9b4f2d02541209c2" + }, + { + "m_Id": "045c4f6b050549c7a0efb208e6349779" + }, + { + "m_Id": "509e6f38505b4b0695b263706a55028f" + }, + { + "m_Id": "204dacb5a95b424facf11cb6f65bd188" + }, + { + "m_Id": "35cbea6373dd4e4f8d0fea36e8add392" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "cfaf3f3a5a1146e194cddad30c95aada", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d0a791a544614667962a9a9a9ce0c68a", + "m_Title": "Screen Space Ratio", + "m_Position": { + "x": -6485.591796875, + "y": -3365.3779296875 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d0b10e52e21941b183f5f635894c76c8", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d1a17e42e7a04dc38984e3c01149445b", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d219977210094c0082c517d8dc00c8bb", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d258902c6ec74942afdb9ebf8c1d07f8", + "m_Title": "Generate Normal", + "m_Position": { + "x": -4511.33349609375, + "y": -3999.3330078125 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "d30452ac6b244ecca03df4d7b4de9f81", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d48c3871e3064027a10ae9f4babd3be0", + "m_Id": 0, + "m_DisplayName": "_UnderlaySoftness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d4954b7bbbb0412cbc997bcbe7dfa808", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "d4df208fc23b42f2b52364124f1b661c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5236.99951171875, + "y": -3260.999755859375, + "width": 143.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "757174b6f25040fdbb20355a21752222" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "d5173cc3c6cd4f1998550f3187a3e9c8", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d6a6a119394e4082a11bc024a6e42ef8", + "m_Id": 0, + "m_DisplayName": "Outline Color 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d880558893fb442b9320cf55885d1117", + "m_Id": 0, + "m_DisplayName": "_FaceUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d8edec16956c4f15b7d51d6ec10753f4", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d9bcb754db834583b6518c5ed5152114", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d9dc4839ee2847999110bdb234d6041a", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "da7a06d393a44089842070d51d2aa0a6", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "daaf032a109749a88c9b8ff8e1f8b541", + "m_Title": "Offset Scale", + "m_Position": { + "x": -5893.0, + "y": -3921.000244140625 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "dbcb748279484a4590e53518c49122b8", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4744.0, + "y": -2762.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "7a0f504e4175406dbd8134250f4e350b" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "dc75c4e3a1bc4bb0a128086c2b0679a5", + "m_Guid": { + "m_GuidSerialized": "85cd941f-2fd2-43a3-b0fa-9f728bfb4220" + }, + "m_Name": "Face Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_99AFBB3D", + "m_OverrideReferenceName": "_FaceColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "de0c6f7f7af94defa6c3dbc6433de9d4", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "deac82280a2b43078e0e40863e2d974c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "def8e0b9d8384982bc5b4c32d877e458", + "m_Id": 0, + "m_DisplayName": "Outline Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "dff7a66b353a4023b29c9d937da77960", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4602.0, + "y": -4298.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7b8a19bd115e4167a25b59cb3218a817" + }, + { + "m_Id": "0b57f2d35157477ab2b29a5aac14ae8b" + }, + { + "m_Id": "e9e06fcb161e44ba8cc9f6f60264df78" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "e141833aa78b4fd59ecad949beb43a78", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e2d28f29bbac4983a401574480b5ca28", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "e386b183a18245a796b024022f7f3074", + "m_Id": 0, + "m_DisplayName": "Normal (Object Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalOS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e444f2c81d1e48329fa2c91005277e8d", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "e495a9f7a11f4eb89334e83be154ceb9", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e51a636b2621440eb94cc802c1cf4bfc", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e6e80c6b0db545cda26b079a9a78fbb3", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "e818605f8f5a4f01bf61caaa33693581", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "ComputeSDF44 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4113.0, + "y": -3368.999755859375, + "width": 243.99998474121095, + "height": 214.0 + } + }, + "m_Slots": [ + { + "m_Id": "641eda269d7b4da9acb65f8d50035ea9" + }, + { + "m_Id": "f6823778a3cf42d5bbe8a83e5f9c9fa3" + }, + { + "m_Id": "9c26fdddba244d36a854298c00473247" + }, + { + "m_Id": "f684c5678e9e4f078157a3ab7ef5057b" + }, + { + "m_Id": "14ad19bf20a140dd88d58452d7df688b" + }, + { + "m_Id": "215a82c127204988b751de7d3a39b955" + }, + { + "m_Id": "c478c32c45884c57a62f7b2aa8ddc3b0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF44", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "e9e06fcb161e44ba8cc9f6f60264df78", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebbd94a7102a4457a48ac492de3bff14", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebd6d75abcb84108bcadbfe7ee5f6244", + "m_Id": 7, + "m_DisplayName": "TextureHeight", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureHeight", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "ec184d6d9fb2494897774c9e7d279e6d", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4754.0, + "y": -2625.0, + "width": 145.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ca2a1083dc014f39ab8af0cdf140866b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "07946387933e416db576b677f0711e5f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "ec1f2e8bc9fd4ae38b133c60ee6c49b8", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4927.0, + "y": -3204.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "748c31bbcecc4b30bec2e42c0612175b" + }, + { + "m_Id": "4bda5c294e1949138d033640e1d385b4" + }, + { + "m_Id": "4e64dac49ddc47c3b5b1e27b17a08304" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "ec79eb447dfd47a9b3380344c6a60f43", + "m_Guid": { + "m_GuidSerialized": "54c77f8b-0534-4b35-a3f0-83ab2ebe6c1f" + }, + "m_Name": "_OutlineTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1774DE83", + "m_OverrideReferenceName": "_OutlineTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "ecf16c34d46f4502ac601f0c38c7576b", + "m_Title": "Vertex Color", + "m_Position": { + "x": -3614.000244140625, + "y": -3549.000244140625 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ed1d1f1613334c3bb904dd08161cd7e5", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ed6c215a65584deeaefad1d2c7743044", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "edbee7a8952b46529ac5ad0365775774", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "ef0b93f78372439696f50711eaf57d90", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.7353569269180298, + "y": 0.7353569269180298, + "z": 0.7353569269180298 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ef9738ec7e894772a14e9dce441c16c6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "f01d52cdcb1647aab35782b4af535efd", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "f23a8b2b7c85478388ff7a8c8a6de740", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Layer4 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3819.0, + "y": -3286.0, + "width": 193.0, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "0fac35636fca4474a6afaefc3c757775" + }, + { + "m_Id": "cc88101667c9488f9c5a716e851c1b21" + }, + { + "m_Id": "68ec7c31365549d6a8ce883edfc02de2" + }, + { + "m_Id": "02559cbe5ad441a3904ccb75ded2b2c5" + }, + { + "m_Id": "34a67e0fef884f9399e674d9eeaf720c" + }, + { + "m_Id": "3802c81c3be24823aa1d7c9997a33c29" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer4", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "f2903158b3624759bca1fcd843698078", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "f2a351a5375c441b8d9ab7e2c9545a77", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "f383b24f0bc6434dafe44b3e3d338a63", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6318.6669921875, + "y": -3153.3330078125, + "width": 185.33348083496095, + "height": 101.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "fb5e1e2a67c14602808358686bb75091" + }, + { + "m_Id": "712da461f71a454db59d349f752d41ee" + }, + { + "m_Id": "b000f852aa984e9dae25b125a4607f4e" + }, + { + "m_Id": "849275cac05e4ca8bd0b38ab7ae43bf8" + }, + { + "m_Id": "59cea37675824d99995b370f09cef20a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "f3d31c1f18d8491a8ecf5cbc37e4b7db", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4291.33349609375, + "y": -3246.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ed1d1f1613334c3bb904dd08161cd7e5" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f42ad06b3c6a45d3ab33de904c063412", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f48f04ad45d046a8b88e71731ed506e7", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f4ecc442a2d246759f7c2c0412953d28", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a3f8b6e8ae7f48e2989a029904401502" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f6823778a3cf42d5bbe8a83e5f9c9fa3", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f684c5678e9e4f078157a3ab7ef5057b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": { + "x": 3.0, + "y": 2.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "f814deb543c24fbbafbcdb5071d96022", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4569.0, + "y": -3245.000244140625, + "width": 184.0, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "abd59150589b436cadf8c9e6f43ccb8e" + }, + { + "m_Id": "7acfafd73b8c4dfab8c55c18a887e087" + }, + { + "m_Id": "928621a3ca2d41c89a10336bbbc81ddc" + }, + { + "m_Id": "b7f9ac55517141868bfb9d2ad6429792" + }, + { + "m_Id": "09b1b86c1c074337a4c439d3a308dd2e" + }, + { + "m_Id": "1f247658c7ba45fb93c41f51e21acb0d" + }, + { + "m_Id": "d30452ac6b244ecca03df4d7b4de9f81" + }, + { + "m_Id": "215b30ae27784ec3a13360a9029af283" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f864c900600e427ba7793f00c715e971", + "m_Id": 0, + "m_DisplayName": "Outline Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fa6de3be9f5b4411b5081b49e645f424", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "faace8101df943d8956faa31728cb004", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5400.0, + "y": -3851.000244140625, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "77e28f3e930b4c249145630ec961af95" + }, + { + "m_Id": "f2903158b3624759bca1fcd843698078" + }, + { + "m_Id": "30ca940fe2794c949f2a1d4d2caaa446" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "facc84930f544fd7a0205a6176b18ac0", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "fb15d0ba56d54a6192f11e107aeb5fa8", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "fb5e1e2a67c14602808358686bb75091", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "fc2e62201c5847e798fd939314413fcd", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fd0b096ed5b74f9e9ec51327be200731", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "fdb77c3e92ee497b88ca5dc46dc45350", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4171.0, + "y": -2362.0, + "width": 180.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "4328cdbf78b94c038fd614c59bfe1cac" + }, + { + "m_Id": "04dfcc9ff13a4bf282ed46faec39d15c" + }, + { + "m_Id": "71dd947935b64ce38f0d25406dde447b" + }, + { + "m_Id": "61a6ac5f29344d109411f26850ab0a96" + }, + { + "m_Id": "44806230fa384c1e95f9c5918a14f056" + }, + { + "m_Id": "4eb3c00a1ca44e10be833b7ca61ff059" + }, + { + "m_Id": "57abc172afd449e2a4d567f93432507b" + }, + { + "m_Id": "cda5e3b4c1054bf3a65c0b7ec6bc778a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "fe11fa80cc1847a5a37f6757d521cf25", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph.meta new file mode 100644 index 0000000..248825c --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 124c112a6e8f1a54e8b0870e881b56d8 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF.shader new file mode 100644 index 0000000..bbcfd11 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF.shader @@ -0,0 +1,326 @@ +Shader "TextMeshPro/Distance Field" { + +Properties { + _FaceTex ("Face Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 + _SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularPower ("Specular", Range(0,4)) = 2.0 + _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 + _Diffuse ("Diffuse", Range(0,1)) = 0.5 + _Ambient ("Ambient", Range(1,0)) = 0.5 + + _BumpMap ("Normal map", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0 + _BumpFace ("Bump Face", Range(0,1)) = 0 + + _ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1) + _ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + + + _UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma target 3.0 + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ BEVEL_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + #pragma shader_feature __ GLOW_ON + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + struct vertex_t + { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 position : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t + { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 position : SV_POSITION; + fixed4 color : COLOR; + float2 atlas : TEXCOORD0; // Atlas + float4 param : TEXCOORD1; // alphaClip, scale, bias, weight + float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw) + float3 viewDir : TEXCOORD3; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 texcoord2 : TEXCOORD4; // u,v, scale, bias + fixed4 underlayColor : COLOR1; + #endif + + float4 textures : TEXCOORD5; + }; + + // Used by Unity internally to handle Texture Tiling and Offset. + float4 _FaceTex_ST; + float4 _OutlineTex_ST; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input,output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord0.w, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float bias =(.5 - weight) + (.5 / scale); + + float alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _OutlineSoftness * _ScaleRatioA); + + #if GLOW_ON + alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); + #endif + + alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float bScale = scale; + bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale); + float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 bOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Support for texture tiling and offset + float2 textureUV = input.texcoord1; + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + output.position = vPosition; + output.color = input.color; + output.atlas = input.texcoord0; + output.param = float4(alphaClip, scale, bias, weight); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias); + output.underlayColor = underlayColor; + #endif + output.textures = float4(faceUV, outlineUV); + + return output; + } + + + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + float c = tex2D(_MainTex, input.atlas).a; + + #ifndef UNDERLAY_ON + clip(c - input.param.x); + #endif + + float scale = input.param.y; + float bias = input.param.z; + float weight = input.param.w; + float sd = (bias - c) * scale; + + float outline = (_OutlineWidth * _ScaleRatioA) * scale; + float softness = (_OutlineSoftness * _ScaleRatioA) * scale; + + half4 faceColor = _FaceColor; + half4 outlineColor = _OutlineColor; + + faceColor.rgb *= input.color.rgb; + + faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y); + outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y); + + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + + #if BEVEL_ON + float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); + float3 n = GetSurfaceNormal(input.atlas, weight, dxy); + + float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + n = normalize(n- bump); + + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0)); + + float3 col = GetSpecular(n, light); + faceColor.rgb += col*faceColor.a; + faceColor.rgb *= 1-(dot(n, light)*_Diffuse); + faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z); + + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + #endif + + #if UNDERLAY_ON + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); + #endif + + #if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + faceColor.rgb += glowColor.rgb * glowColor.a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + faceColor *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor * input.color.a; + } + ENDCG + } +} + +Fallback "TextMeshPro/Mobile/Distance Field" +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF.shader.meta new file mode 100644 index 0000000..e1cf3f3 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 68e6db2ebdc24f95958faec2be5558d6 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader b/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader new file mode 100644 index 0000000..4012a08 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader @@ -0,0 +1,131 @@ +Shader "TextMeshPro/Sprite" +{ + Properties + { + _MainTex ("Sprite Texture", 2D) = "white" {} + _Color ("Tint", Color) = (1,1,1,1) + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 + } + + SubShader + { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + "PreviewType"="Plane" + "CanUseSpriteAtlas"="True" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + Lighting Off + ZWrite Off + ZTest [unity_GUIZTestMode] + Blend SrcAlpha OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass + { + Name "Default" + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + struct appdata_t + { + float4 vertex : POSITION; + float4 color : COLOR; + float2 texcoord : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord : TEXCOORD0; + float4 worldPosition : TEXCOORD1; + float4 mask : TEXCOORD2; + UNITY_VERTEX_OUTPUT_STEREO + }; + + sampler2D _MainTex; + fixed4 _Color; + fixed4 _TextureSampleAdd; + float4 _ClipRect; + float4 _MainTex_ST; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + + v2f vert(appdata_t v) + { + v2f OUT; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); + float4 vPosition = UnityObjectToClipPos(v.vertex); + OUT.worldPosition = v.vertex; + OUT.vertex = vPosition; + + float2 pixelSize = vPosition.w; + pixelSize /= abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); + OUT.mask = half4(v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy))); + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + v.color.rgb = UIGammaToLinear(v.color.rgb); + } + OUT.color = v.color * _Color; + return OUT; + } + + fixed4 frag(v2f IN) : SV_Target + { + half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; + + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #ifdef UNITY_UI_ALPHACLIP + clip (color.a - 0.001); + #endif + + return color; + } + ENDCG + } + } +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader.meta new file mode 100644 index 0000000..50ba195 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: cf81c85f95fe47e1a27f6ae460cf182c +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMPro.cginc b/Assets/TextMesh Pro/Shaders/TMPro.cginc new file mode 100644 index 0000000..5898130 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro.cginc @@ -0,0 +1,84 @@ +float2 UnpackUV(float uv) +{ + float2 output; + output.x = floor(uv / 4096); + output.y = uv - 4096 * output.x; + + return output * 0.001953125; +} + +fixed4 GetColor(half d, fixed4 faceColor, fixed4 outlineColor, half outline, half softness) +{ + half faceAlpha = 1-saturate((d - outline * 0.5 + softness * 0.5) / (1.0 + softness)); + half outlineAlpha = saturate((d + outline * 0.5)) * sqrt(min(1.0, outline)); + + faceColor.rgb *= faceColor.a; + outlineColor.rgb *= outlineColor.a; + + faceColor = lerp(faceColor, outlineColor, outlineAlpha); + + faceColor *= faceAlpha; + + return faceColor; +} + +float3 GetSurfaceNormal(float4 h, float bias) +{ + bool raisedBevel = step(1, fmod(_ShaderFlags, 2)); + + h += bias+_BevelOffset; + + float bevelWidth = max(.01, _OutlineWidth+_BevelWidth); + + // Track outline + h -= .5; + h /= bevelWidth; + h = saturate(h+.5); + + if(raisedBevel) h = 1 - abs(h*2.0 - 1.0); + h = lerp(h, sin(h*3.141592/2.0), _BevelRoundness); + h = min(h, 1.0-_BevelClamp); + h *= _Bevel * bevelWidth * _GradientScale * -2.0; + + float3 va = normalize(float3(1.0, 0.0, h.y - h.x)); + float3 vb = normalize(float3(0.0, -1.0, h.w - h.z)); + + return cross(va, vb); +} + +float3 GetSurfaceNormal(float2 uv, float bias, float3 delta) +{ + // Read "height field" + float4 h = {tex2D(_MainTex, uv - delta.xz).a, + tex2D(_MainTex, uv + delta.xz).a, + tex2D(_MainTex, uv - delta.zy).a, + tex2D(_MainTex, uv + delta.zy).a}; + + return GetSurfaceNormal(h, bias); +} + +float3 GetSpecular(float3 n, float3 l) +{ + float spec = pow(max(0.0, dot(n, l)), _Reflectivity); + return _SpecularColor.rgb * spec * _SpecularPower; +} + +float4 GetGlowColor(float d, float scale) +{ + float glow = d - (_GlowOffset*_ScaleRatioB) * 0.5 * scale; + float t = lerp(_GlowInner, (_GlowOuter * _ScaleRatioB), step(0.0, glow)) * 0.5 * scale; + glow = saturate(abs(glow/(1.0 + t))); + glow = 1.0-pow(glow, _GlowPower); + glow *= sqrt(min(1.0, t)); // Fade off glow thinner than 1 screen pixel + return float4(_GlowColor.rgb, saturate(_GlowColor.a * glow * 2)); +} + +float4 BlendARGB(float4 overlying, float4 underlying) +{ + overlying.rgb *= overlying.a; + underlying.rgb *= underlying.a; + float3 blended = overlying.rgb + ((1-overlying.a)*underlying.rgb); + float alpha = underlying.a + (1-underlying.a)*overlying.a; + return float4(blended, alpha); +} + diff --git a/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta b/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta new file mode 100644 index 0000000..f21163e --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 407bc68d299748449bbf7f48ee690f8d +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: Version 2.0 + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc b/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc new file mode 100644 index 0000000..d145a77 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc @@ -0,0 +1,165 @@ +struct vertex_t +{ + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 position : POSITION; + float3 normal : NORMAL; + float4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; +}; + +struct pixel_t +{ + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 position : SV_POSITION; + float4 faceColor : COLOR; + float4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; + float4 param : TEXCOORD1; // x = weight, y = no longer used + float2 mask : TEXCOORD2; + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 texcoord2 : TEXCOORD3; + float4 underlayColor : COLOR2; + #endif +}; + +float4 SRGBToLinear(float4 rgba) +{ + return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a); +} + +float _UIMaskSoftnessX; +float _UIMaskSoftnessY; + +pixel_t VertShader(vertex_t input) +{ + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord0.w, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + float4 vPosition = UnityObjectToClipPos(vert); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + float4 color = input.color; + #if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA) + color = SRGBToLinear(input.color); + #endif + + float opacity = color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + float4 faceColor = float4(color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + float4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + + output.position = vPosition; + output.faceColor = faceColor; + output.outlineColor = outlineColor; + output.texcoord0 = float4(input.texcoord0.xy, maskUV.xy); + output.param = float4(0.5 - weight, 0, _OutlineWidth * _ScaleRatioA * 0.5, 0); + + float2 mask = float2(0, 0); + #if UNITY_UI_CLIP_RECT + mask = vert.xy * 2 - clampedRect.xy - clampedRect.zw; + #endif + output.mask = mask; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + + output.texcoord2 = float4(input.texcoord0 + float2(x, y), input.color.a, 0); + output.underlayColor = underlayColor; + #endif + + return output; +} + +float4 PixShader(pixel_t input) : SV_Target +{ + UNITY_SETUP_INSTANCE_ID(input); + + float d = tex2D(_MainTex, input.texcoord0.xy).a; + + float pixelSize = abs(ddx(input.texcoord0.y)) + abs(ddy(input.texcoord0.y)); + pixelSize *= _TextureHeight * 0.75; + float scale = 1 / pixelSize * _GradientScale * (_Sharpness + 1); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + float layerScale = scale; + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = input.param.x * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + #endif + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + + float4 faceColor = input.faceColor * saturate((d - input.param.x) * scale + 0.5); + + #if OUTLINE_ON + float4 outlineColor = lerp(input.faceColor, input.outlineColor, sqrt(min(1.0, input.param.z * scale * 2))); + faceColor = lerp(outlineColor, input.faceColor, saturate((d - input.param.x - input.param.z) * scale + 0.5)); + faceColor *= saturate((d - input.param.x + input.param.z) * scale + 0.5); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord2.xy).a * layerScale; + faceColor += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - layerBias) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float bias = input.param.x * scale - 0.5; + float sd = saturate(d * scale - bias - input.param.z); + d = tex2D(_MainTex, input.texcoord2.xy).a * layerScale; + faceColor += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - layerBias)) * sd * (1 - faceColor.a); + #endif + + #if MASKING + float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a); + float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl; + a = saturate(t / _MaskEdgeSoftness); + faceColor.rgb = lerp(_MaskEdgeColor.rgb * faceColor.a, faceColor.rgb, a); + faceColor *= a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness + #if UNITY_UI_CLIP_RECT + half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + float2 maskZW = 0.25 / (0.25 * maskSoftness + 1 / scale); + float2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * maskZW); + faceColor *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + faceColor *= input.texcoord2.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor; +} diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc.meta b/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc.meta new file mode 100644 index 0000000..4415e50 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c334973cef89a9840b0b0c507e0377ab +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc b/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc new file mode 100644 index 0000000..b806b4f --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc @@ -0,0 +1,80 @@ +// UI Editable properties +uniform sampler2D _FaceTex; // Alpha : Signed Distance +uniform float _FaceUVSpeedX; +uniform float _FaceUVSpeedY; +uniform fixed4 _FaceColor; // RGBA : Color + Opacity +uniform float _FaceDilate; // v[ 0, 1] +uniform float _OutlineSoftness; // v[ 0, 1] + +uniform sampler2D _OutlineTex; // RGBA : Color + Opacity +uniform float _OutlineUVSpeedX; +uniform float _OutlineUVSpeedY; +uniform fixed4 _OutlineColor; // RGBA : Color + Opacity +uniform float _OutlineWidth; // v[ 0, 1] + +uniform float _Bevel; // v[ 0, 1] +uniform float _BevelOffset; // v[-1, 1] +uniform float _BevelWidth; // v[-1, 1] +uniform float _BevelClamp; // v[ 0, 1] +uniform float _BevelRoundness; // v[ 0, 1] + +uniform sampler2D _BumpMap; // Normal map +uniform float _BumpOutline; // v[ 0, 1] +uniform float _BumpFace; // v[ 0, 1] + +uniform samplerCUBE _Cube; // Cube / sphere map +uniform fixed4 _ReflectFaceColor; // RGB intensity +uniform fixed4 _ReflectOutlineColor; +//uniform float _EnvTiltX; // v[-1, 1] +//uniform float _EnvTiltY; // v[-1, 1] +uniform float3 _EnvMatrixRotation; +uniform float4x4 _EnvMatrix; + +uniform fixed4 _SpecularColor; // RGB intensity +uniform float _LightAngle; // v[ 0,Tau] +uniform float _SpecularPower; // v[ 0, 1] +uniform float _Reflectivity; // v[ 5, 15] +uniform float _Diffuse; // v[ 0, 1] +uniform float _Ambient; // v[ 0, 1] + +uniform fixed4 _UnderlayColor; // RGBA : Color + Opacity +uniform float _UnderlayOffsetX; // v[-1, 1] +uniform float _UnderlayOffsetY; // v[-1, 1] +uniform float _UnderlayDilate; // v[-1, 1] +uniform float _UnderlaySoftness; // v[ 0, 1] + +uniform fixed4 _GlowColor; // RGBA : Color + Intesity +uniform float _GlowOffset; // v[-1, 1] +uniform float _GlowOuter; // v[ 0, 1] +uniform float _GlowInner; // v[ 0, 1] +uniform float _GlowPower; // v[ 1, 1/(1+4*4)] + +// API Editable properties +uniform float _ShaderFlags; +uniform float _WeightNormal; +uniform float _WeightBold; + +uniform float _ScaleRatioA; +uniform float _ScaleRatioB; +uniform float _ScaleRatioC; + +uniform float _VertexOffsetX; +uniform float _VertexOffsetY; + +//uniform float _UseClipRect; +uniform float _MaskID; +uniform sampler2D _MaskTex; +uniform float4 _MaskCoord; +uniform float4 _ClipRect; // bottom left(x,y) : top right(z,w) +uniform float _MaskSoftnessX; +uniform float _MaskSoftnessY; + +// Font Atlas properties +uniform sampler2D _MainTex; +uniform float _TextureWidth; +uniform float _TextureHeight; +uniform float _GradientScale; +uniform float _ScaleX; +uniform float _ScaleY; +uniform float _PerspectiveFilter; +uniform float _Sharpness; diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc.meta b/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc.meta new file mode 100644 index 0000000..7b37f2f --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3997e2241185407d80309a82f9148466 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc b/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc new file mode 100644 index 0000000..2153a9a --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc @@ -0,0 +1,99 @@ +void VertShader(inout appdata_full v, out Input data) +{ + v.vertex.x += _VertexOffsetX; + v.vertex.y += _VertexOffsetY; + + UNITY_INITIALIZE_OUTPUT(Input, data); + + float bold = step(v.texcoord.w, 0); + + // Generate normal for backface + float3 view = ObjSpaceViewDir(v.vertex); + v.normal *= sign(dot(v.normal, view)); + +#if USE_DERIVATIVE + data.param.y = 1; +#else + float4 vert = v.vertex; + float4 vPosition = UnityObjectToClipPos(vert); + float2 pixelSize = vPosition.w; + + pixelSize /= float2(_ScaleX, _ScaleY) * mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy); + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(v.texcoord.w) * _GradientScale * (_Sharpness + 1); + scale = lerp(scale * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(v.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + data.param.y = scale; +#endif + + data.param.x = (lerp(_WeightNormal, _WeightBold, bold) / 4.0 + _FaceDilate) * _ScaleRatioA * 0.5; // + data.viewDirEnv = mul((float3x3)_EnvMatrix, WorldSpaceViewDir(v.vertex)); +} + +void PixShader(Input input, inout SurfaceOutput o) +{ + +#if USE_DERIVATIVE + float2 pixelSize = float2(ddx(input.uv_MainTex.y), ddy(input.uv_MainTex.y)); + pixelSize *= _TextureWidth * .75; + float scale = rsqrt(dot(pixelSize, pixelSize)) * _GradientScale * (_Sharpness + 1); +#else + float scale = input.param.y; +#endif + + // Signed distance + float c = tex2D(_MainTex, input.uv_MainTex).a; + float sd = (.5 - c - input.param.x) * scale + .5; + float outline = _OutlineWidth*_ScaleRatioA * scale; + float softness = _OutlineSoftness*_ScaleRatioA * scale; + + // Color & Alpha + float4 faceColor = _FaceColor; + float4 outlineColor = _OutlineColor; + faceColor *= input.color; + outlineColor.a *= input.color.a; + faceColor *= tex2D(_FaceTex, float2(input.uv2_FaceTex.x + _FaceUVSpeedX * _Time.y, input.uv2_FaceTex.y + _FaceUVSpeedY * _Time.y)); + outlineColor *= tex2D(_OutlineTex, float2(input.uv2_OutlineTex.x + _OutlineUVSpeedX * _Time.y, input.uv2_OutlineTex.y + _OutlineUVSpeedY * _Time.y)); + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + faceColor.rgb /= max(faceColor.a, 0.0001); + +#if BEVEL_ON + float3 delta = float3(1.0 / _TextureWidth, 1.0 / _TextureHeight, 0.0); + + float4 smp4x = {tex2D(_MainTex, input.uv_MainTex - delta.xz).a, + tex2D(_MainTex, input.uv_MainTex + delta.xz).a, + tex2D(_MainTex, input.uv_MainTex - delta.zy).a, + tex2D(_MainTex, input.uv_MainTex + delta.zy).a }; + + // Face Normal + float3 n = GetSurfaceNormal(smp4x, input.param.x); + + // Bumpmap + float3 bump = UnpackNormal(tex2D(_BumpMap, input.uv2_FaceTex.xy)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + bump = lerp(float3(0, 0, 1), bump, faceColor.a); + n = normalize(n - bump); + + // Cubemap reflection + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDirEnv, mul((float3x3)unity_ObjectToWorld, n))); + float3 emission = reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; +#else + float3 n = float3(0, 0, -1); + float3 emission = float3(0, 0, 0); +#endif + +#if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + glowColor.a *= input.color.a; + emission += glowColor.rgb*glowColor.a; + faceColor = BlendARGB(glowColor, faceColor); + faceColor.rgb /= max(faceColor.a, 0.0001); +#endif + + // Set Standard output structure + o.Albedo = faceColor.rgb; + o.Normal = -n; + o.Emission = emission; + o.Specular = lerp(_FaceShininess, _OutlineShininess, saturate(sd + outline * 0.5)); + o.Gloss = 1; + o.Alpha = faceColor.a; +} diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc.meta b/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc.meta new file mode 100644 index 0000000..41ef4b1 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d930090c0cd643c7b55f19a38538c162 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Sprites.meta b/Assets/TextMesh Pro/Sprites.meta new file mode 100644 index 0000000..8b699e5 --- /dev/null +++ b/Assets/TextMesh Pro/Sprites.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0603b6d5186471b96c778c3949c7ce2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt b/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt new file mode 100644 index 0000000..384180a --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt @@ -0,0 +1,3 @@ +This sample of beautiful emojis are provided by EmojiOne https://www.emojione.com/ + +Please visit their website to view the complete set of their emojis and review their licensing terms. \ No newline at end of file diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt.meta b/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt.meta new file mode 100644 index 0000000..0d30e65 --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne Attribution.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 381dcb09d5029d14897e55f98031fca5 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne.json b/Assets/TextMesh Pro/Sprites/EmojiOne.json new file mode 100644 index 0000000..6c4e50b --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne.json @@ -0,0 +1,156 @@ +{"frames": [ + +{ + "filename": "1f60a.png", + "frame": {"x":0,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f60b.png", + "frame": {"x":128,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f60d.png", + "frame": {"x":256,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f60e.png", + "frame": {"x":384,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f600.png", + "frame": {"x":0,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f601.png", + "frame": {"x":128,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f602.png", + "frame": {"x":256,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f603.png", + "frame": {"x":384,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f604.png", + "frame": {"x":0,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f605.png", + "frame": {"x":128,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f606.png", + "frame": {"x":256,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f609.png", + "frame": {"x":384,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f618.png", + "frame": {"x":0,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1f923.png", + "frame": {"x":128,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "263a.png", + "frame": {"x":256,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "2639.png", + "frame": {"x":384,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128}, + "pivot": {"x":0.5,"y":0.5} +}], +"meta": { + "app": "http://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "EmojiOne.png", + "format": "RGBA8888", + "size": {"w":512,"h":512}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:196a26a2e149d875b91ffc8fa3581e76:fc928c7e275404b7e0649307410475cb:424723c3774975ddb2053fd5c4b85f6e$" +} +} diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne.json.meta b/Assets/TextMesh Pro/Sprites/EmojiOne.json.meta new file mode 100644 index 0000000..762cf15 --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne.json.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f05276190cf498a8153f6cbe761d4e6 +timeCreated: 1480316860 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne.png b/Assets/TextMesh Pro/Sprites/EmojiOne.png new file mode 100644 index 0000000..c0de66d Binary files /dev/null and b/Assets/TextMesh Pro/Sprites/EmojiOne.png differ diff --git a/Assets/TextMesh Pro/Sprites/EmojiOne.png.meta b/Assets/TextMesh Pro/Sprites/EmojiOne.png.meta new file mode 100644 index 0000000..c9fa1a7 --- /dev/null +++ b/Assets/TextMesh Pro/Sprites/EmojiOne.png.meta @@ -0,0 +1,431 @@ +fileFormatVersion: 2 +guid: dffef66376be4fa480fb02b19edbe903 +TextureImporter: + fileIDToRecycleName: + 21300000: EmojiOne_0 + 21300002: EmojiOne_1 + 21300004: EmojiOne_2 + 21300006: EmojiOne_3 + 21300008: EmojiOne_4 + 21300010: EmojiOne_6 + 21300012: EmojiOne_7 + 21300014: EmojiOne_8 + 21300016: EmojiOne_9 + 21300018: EmojiOne_10 + 21300020: EmojiOne_11 + 21300022: EmojiOne_12 + 21300024: EmojiOne_13 + 21300026: EmojiOne_5 + 21300028: EmojiOne_14 + externalObjects: {} + serializedVersion: 5 + 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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 2 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: EmojiOne_0 + rect: + serializedVersion: 2 + x: 0 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 4bcc36da2108f2c4ba3de5c921d25c3c + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_1 + rect: + serializedVersion: 2 + x: 128 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: e9eea8093eaeaee4d901c4553f572c22 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_2 + rect: + serializedVersion: 2 + x: 256 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 49451da35411dcc42a3692e39b0fde70 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_3 + rect: + serializedVersion: 2 + x: 384 + y: 384 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: f65709664b924904790c850a50ca82bc + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_4 + rect: + serializedVersion: 2 + x: 0 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 5b92c568a5ec9ad4b9ed90e271f1c9a8 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_6 + rect: + serializedVersion: 2 + x: 256 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: b10f2b48b7281594bb8a24a6511a35af + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_7 + rect: + serializedVersion: 2 + x: 384 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 10a600f9329dc2246a897e89f4d283cd + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_8 + rect: + serializedVersion: 2 + x: 0 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 66cffa363b90ab14787d8a5b90cf4502 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_9 + rect: + serializedVersion: 2 + x: 128 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 55cf3d409c9b89349b1e1bdc1cc224ad + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_10 + rect: + serializedVersion: 2 + x: 256 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 2a9e58eaf96feef42bcefa1cf257193f + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_11 + rect: + serializedVersion: 2 + x: 384 + y: 128 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 2489120affc155840ae6a7be2e93ce19 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_12 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 412349a150598d14da4d7140df5c0286 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_13 + rect: + serializedVersion: 2 + x: 128 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: a937464b42bb3634782dea34c6becb6c + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_5 + rect: + serializedVersion: 2 + x: 256 + y: 0 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: b0f933b217682124dbfc5e6b89abe3d0 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: EmojiOne_14 + rect: + serializedVersion: 2 + x: 128 + y: 256 + width: 128 + height: 128 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: f7235c763afe4434e8bb666750a41096 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 3e32d8f5477abfc43b19066e8ad5032e + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniversalRenderPipelineGlobalSettings.asset b/Assets/UniversalRenderPipelineGlobalSettings.asset new file mode 100644 index 0000000..2bdb0a3 --- /dev/null +++ b/Assets/UniversalRenderPipelineGlobalSettings.asset @@ -0,0 +1,346 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 2ec995e51a6e251468d2a3fd8a686257, type: 3} + m_Name: UniversalRenderPipelineGlobalSettings + m_EditorClassIdentifier: + m_ShaderStrippingSetting: + m_Version: 0 + m_ExportShaderVariants: 1 + m_ShaderVariantLogLevel: 0 + m_StripRuntimeDebugShaders: 1 + m_URPShaderStrippingSetting: + m_Version: 0 + m_StripUnusedPostProcessingVariants: 1 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + m_ShaderVariantLogLevel: 0 + m_ExportShaderVariants: 1 + m_StripDebugVariants: 1 + m_StripUnusedPostProcessingVariants: 1 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + supportRuntimeDebugDisplay: 0 + m_EnableRenderGraph: 0 + m_Settings: + m_SettingsList: + m_List: + - rid: 2906203349116518400 + - rid: 2906203349116518401 + - rid: 2906203349116518402 + - rid: 2906203349116518403 + - rid: 2906203349116518404 + - rid: 2906203349116518405 + - rid: 2906203349116518406 + - rid: 2906203349116518407 + - rid: 2906203349116518408 + - rid: 2906203349116518409 + - rid: 2906203349116518410 + - rid: 2906203349116518411 + - rid: 2906203349116518412 + - rid: 2906203349116518413 + - rid: 2906203349116518414 + - rid: 2906203349116518415 + - rid: 2906203349116518416 + - rid: 2906203349116518417 + - rid: 2906203349116518418 + - rid: 2906203349116518419 + - rid: 2906203349116518420 + - rid: 2906203349116518421 + m_RuntimeSettings: + m_List: [] + m_AssetVersion: 8 + m_ObsoleteDefaultVolumeProfile: {fileID: 0} + m_RenderingLayerNames: + - Light Layer default + - Light Layer 1 + - Light Layer 2 + - Light Layer 3 + - Light Layer 4 + - Light Layer 5 + - Light Layer 6 + - Light Layer 7 + m_ValidRenderingLayers: 255 + lightLayerName0: Light Layer default + lightLayerName1: Light Layer 1 + lightLayerName2: Light Layer 2 + lightLayerName3: Light Layer 3 + lightLayerName4: Light Layer 4 + lightLayerName5: Light Layer 5 + lightLayerName6: Light Layer 6 + lightLayerName7: Light Layer 7 + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + references: + version: 2 + RefIds: + - rid: 2906203349116518400 + type: {class: UniversalRenderPipelineEditorAssets, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DefaultSettingsVolumeProfile: {fileID: 11400000, guid: eda47df5b85f4f249abf7abd73db2cb2, + type: 2} + - rid: 2906203349116518401 + type: {class: UniversalRenderPipelineEditorMaterials, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DefaultMaterial: {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, + type: 2} + m_DefaultParticleMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d, + type: 2} + m_DefaultLineMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d, + type: 2} + m_DefaultTerrainMaterial: {fileID: 2100000, guid: 594ea882c5a793440b60ff72d896021e, + type: 2} + m_DefaultDecalMaterial: {fileID: 2100000, guid: 31d0dcc6f2dd4e4408d18036a2c93862, + type: 2} + m_DefaultSpriteMaterial: {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, + type: 2} + - rid: 2906203349116518402 + type: {class: UniversalRenderPipelineRuntimeTextures, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 1 + m_BlueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, + type: 3} + m_BayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, + type: 3} + m_DebugFontTex: {fileID: 2800000, guid: 26a413214480ef144b2915d6ff4d0beb, + type: 3} + - rid: 2906203349116518403 + type: {class: UniversalRenderPipelineDebugShaders, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DebugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, + type: 3} + m_HdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, + type: 3} + m_ProbeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, + type: 3} + - rid: 2906203349116518404 + type: {class: UniversalRenderPipelineRuntimeShaders, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_FallbackErrorShader: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, + type: 3} + m_BlitHDROverlay: {fileID: 4800000, guid: a89bee29cffa951418fc1e2da94d1959, + type: 3} + m_CoreBlitPS: {fileID: 4800000, guid: 93446b5c5339d4f00b85c159e1159b7c, type: 3} + m_CoreBlitColorAndDepthPS: {fileID: 4800000, guid: d104b2fc1ca6445babb8e90b0758136b, + type: 3} + m_SamplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + m_TerrainDetailLit: {fileID: 4800000, guid: f6783ab646d374f94b199774402a5144, + type: 3} + m_TerrainDetailGrassBillboard: {fileID: 4800000, guid: 29868e73b638e48ca99a19ea58c48d90, + type: 3} + m_TerrainDetailGrass: {fileID: 4800000, guid: e507fdfead5ca47e8b9a768b51c291a1, + type: 3} + - rid: 2906203349116518405 + type: {class: UniversalRenderPipelineRuntimeXRResources, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_xrOcclusionMeshPS: {fileID: 4800000, guid: 4431b1f1f743fbf4eb310a967890cbea, + type: 3} + m_xrMirrorViewPS: {fileID: 4800000, guid: d5a307c014552314b9f560906d708772, + type: 3} + m_xrMotionVector: {fileID: 4800000, guid: f89aac1e4f84468418fe30e611dff395, + type: 3} + - rid: 2906203349116518406 + type: {class: URPDefaultVolumeProfileSettings, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_VolumeProfile: {fileID: 11400000, guid: 4d700d2576e8690408c7f734564d78f7, + type: 2} + - rid: 2906203349116518407 + type: {class: UniversalRenderPipelineEditorShaders, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_AutodeskInteractive: {fileID: 4800000, guid: 0e9d5a909a1f7e84882a534d0d11e49f, + type: 3} + m_AutodeskInteractiveTransparent: {fileID: 4800000, guid: 5c81372d981403744adbdda4433c9c11, + type: 3} + m_AutodeskInteractiveMasked: {fileID: 4800000, guid: 80aa867ac363ac043847b06ad71604cd, + type: 3} + m_TerrainDetailLit: {fileID: 4800000, guid: f6783ab646d374f94b199774402a5144, + type: 3} + m_TerrainDetailGrassBillboard: {fileID: 4800000, guid: 29868e73b638e48ca99a19ea58c48d90, + type: 3} + m_TerrainDetailGrass: {fileID: 4800000, guid: e507fdfead5ca47e8b9a768b51c291a1, + type: 3} + m_DefaultSpeedTree7Shader: {fileID: 4800000, guid: 0f4122b9a743b744abe2fb6a0a88868b, + type: 3} + m_DefaultSpeedTree8Shader: {fileID: -6465566751694194690, guid: 9920c1f1781549a46ba081a2a15a16ec, + type: 3} + m_DefaultSpeedTree9Shader: {fileID: -6465566751694194690, guid: cbd3e1cc4ae141c42a30e33b4d666a61, + type: 3} + - rid: 2906203349116518408 + type: {class: RenderGraphSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_EnableRenderCompatibilityMode: 1 + - rid: 2906203349116518409 + type: {class: UniversalRendererResources, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_CopyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + m_CameraMotionVector: {fileID: 4800000, guid: c56b7e0d4c7cb484e959caeeedae9bbf, + type: 3} + m_StencilDeferredPS: {fileID: 4800000, guid: e9155b26e1bc55942a41e518703fe304, + type: 3} + m_DBufferClear: {fileID: 4800000, guid: f056d8bd2a1c7e44e9729144b4c70395, + type: 3} + - rid: 2906203349116518410 + type: {class: URPShaderStrippingSetting, ns: UnityEngine.Rendering.Universal, + asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_StripUnusedPostProcessingVariants: 1 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + - rid: 2906203349116518411 + type: {class: Renderer2DResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_LightShader: {fileID: 4800000, guid: 3f6c848ca3d7bca4bbe846546ac701a1, type: 3} + m_ProjectedShadowShader: {fileID: 4800000, guid: ce09d4a80b88c5a4eb9768fab4f1ee00, + type: 3} + m_SpriteShadowShader: {fileID: 4800000, guid: 44fc62292b65ab04eabcf310e799ccf6, + type: 3} + m_SpriteUnshadowShader: {fileID: 4800000, guid: de02b375720b5c445afe83cd483bedf3, + type: 3} + m_GeometryShadowShader: {fileID: 4800000, guid: 19349a0f9a7ed4c48a27445bcf92e5e1, + type: 3} + m_GeometryUnshadowShader: {fileID: 4800000, guid: 77774d9009bb81447b048c907d4c6273, + type: 3} + m_FallOffLookup: {fileID: 2800000, guid: 5688ab254e4c0634f8d6c8e0792331ca, + type: 3} + m_CopyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + m_DefaultLitMaterial: {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, + type: 2} + m_DefaultUnlitMaterial: {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, + type: 2} + m_DefaultMaskMaterial: {fileID: 2100000, guid: 15d0c3709176029428a0da2f8cecf0b5, + type: 2} + - rid: 2906203349116518412 + type: {class: GPUResidentDrawerResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.GPUDriven.Runtime} + data: + m_Version: 0 + m_InstanceDataBufferCopyKernels: {fileID: 7200000, guid: f984aeb540ded8b4fbb8a2047ab5b2e2, + type: 3} + m_InstanceDataBufferUploadKernels: {fileID: 7200000, guid: 53864816eb00f2343b60e1a2c5a262ef, + type: 3} + m_TransformUpdaterKernels: {fileID: 7200000, guid: 2a567b9b2733f8d47a700c3c85bed75b, + type: 3} + m_WindDataUpdaterKernels: {fileID: 7200000, guid: fde76746e4fd0ed418c224f6b4084114, + type: 3} + m_OccluderDepthPyramidKernels: {fileID: 7200000, guid: 08b2b5fb307b0d249860612774a987da, + type: 3} + m_InstanceOcclusionCullingKernels: {fileID: 7200000, guid: f6d223acabc2f974795a5a7864b50e6c, + type: 3} + m_OcclusionCullingDebugKernels: {fileID: 7200000, guid: b23e766bcf50ca4438ef186b174557df, + type: 3} + m_DebugOcclusionTestPS: {fileID: 4800000, guid: d3f0849180c2d0944bc71060693df100, + type: 3} + m_DebugOccluderPS: {fileID: 4800000, guid: b3c92426a88625841ab15ca6a7917248, + type: 3} + - rid: 2906203349116518413 + type: {class: RenderGraphGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_version: 0 + m_EnableCompilationCaching: 1 + m_EnableValidityChecks: 1 + - rid: 2906203349116518414 + type: {class: ProbeVolumeRuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + probeVolumeBlendStatesCS: {fileID: 7200000, guid: a3f7b8c99de28a94684cb1daebeccf5d, + type: 3} + probeVolumeUploadDataCS: {fileID: 7200000, guid: 0951de5992461754fa73650732c4954c, + type: 3} + probeVolumeUploadDataL2CS: {fileID: 7200000, guid: 6196f34ed825db14b81fb3eb0ea8d931, + type: 3} + - rid: 2906203349116518415 + type: {class: IncludeAdditionalRPAssets, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_version: 0 + m_IncludeReferencedInScenes: 0 + m_IncludeAssetsByLabel: 0 + m_LabelToInclude: + - rid: 2906203349116518416 + type: {class: ProbeVolumeBakingResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + dilationShader: {fileID: 7200000, guid: 6bb382f7de370af41b775f54182e491d, + type: 3} + subdivideSceneCS: {fileID: 7200000, guid: bb86f1f0af829fd45b2ebddda1245c22, + type: 3} + voxelizeSceneShader: {fileID: 4800000, guid: c8b6a681c7b4e2e4785ffab093907f9e, + type: 3} + traceVirtualOffsetCS: {fileID: -6772857160820960102, guid: ff2cbab5da58bf04d82c5f34037ed123, + type: 3} + traceVirtualOffsetRT: {fileID: -5126288278712620388, guid: ff2cbab5da58bf04d82c5f34037ed123, + type: 3} + skyOcclusionCS: {fileID: -6772857160820960102, guid: 5a2a534753fbdb44e96c3c78b5a6999d, + type: 3} + skyOcclusionRT: {fileID: -5126288278712620388, guid: 5a2a534753fbdb44e96c3c78b5a6999d, + type: 3} + renderingLayerCS: {fileID: -6772857160820960102, guid: 94a070d33e408384bafc1dea4a565df9, + type: 3} + renderingLayerRT: {fileID: -5126288278712620388, guid: 94a070d33e408384bafc1dea4a565df9, + type: 3} + - rid: 2906203349116518417 + type: {class: RenderGraphUtilsResources, ns: UnityEngine.Rendering.RenderGraphModule.Util, + asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 0 + m_CoreCopyPS: {fileID: 4800000, guid: 12dc59547ea167a4ab435097dd0f9add, type: 3} + - rid: 2906203349116518418 + type: {class: ProbeVolumeDebugResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + probeVolumeDebugShader: {fileID: 4800000, guid: 3b21275fd12d65f49babb5286f040f2d, + type: 3} + probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 3a80877c579b9144ebdcc6d923bca303, + type: 3} + probeVolumeSamplingDebugShader: {fileID: 4800000, guid: bf54e6528c79a224e96346799064c393, + type: 3} + probeVolumeOffsetDebugShader: {fileID: 4800000, guid: db8bd7436dc2c5f4c92655307d198381, + type: 3} + probeSamplingDebugMesh: {fileID: -3555484719484374845, guid: 20be25aac4e22ee49a7db76fb3df6de2, + type: 3} + numbersDisplayTex: {fileID: 2800000, guid: 73fe53b428c5b3440b7e87ee830b608a, + type: 3} + - rid: 2906203349116518419 + type: {class: ProbeVolumeGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + m_ProbeVolumeDisableStreamingAssets: 0 + - rid: 2906203349116518420 + type: {class: ShaderStrippingSetting, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 0 + m_ExportShaderVariants: 1 + m_ShaderVariantLogLevel: 0 + m_StripRuntimeDebugShaders: 1 + - rid: 2906203349116518421 + type: {class: STP/RuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_setupCS: {fileID: 7200000, guid: 33be2e9a5506b2843bdb2bdff9cad5e1, type: 3} + m_preTaaCS: {fileID: 7200000, guid: a679dba8ec4d9ce45884a270b0e22dda, type: 3} + m_taaCS: {fileID: 7200000, guid: 3923900e2b41b5e47bc25bfdcbcdc9e6, type: 3} diff --git a/Assets/UniversalRenderPipelineGlobalSettings.asset.meta b/Assets/UniversalRenderPipelineGlobalSettings.asset.meta new file mode 100644 index 0000000..81b84f2 --- /dev/null +++ b/Assets/UniversalRenderPipelineGlobalSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 18dc0cd2c080841dea60987a38ce93fa +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net.meta b/Assets/com.rlabrecque.steamworks.net.meta new file mode 100644 index 0000000..b5bb4a0 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: db6ac70a3a0d83048aa9552cfded5206 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Editor.meta b/Assets/com.rlabrecque.steamworks.net/Editor.meta new file mode 100644 index 0000000..68854c4 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e621350345100524c9fa97c4bc4716a7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Editor/RedistCopy.cs b/Assets/com.rlabrecque.steamworks.net/Editor/RedistCopy.cs new file mode 100644 index 0000000..7408b93 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Editor/RedistCopy.cs @@ -0,0 +1,76 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using UnityEngine; +using UnityEditor; +using UnityEditor.Callbacks; +using System.IO; +using Steamworks; + +public class RedistCopy { + [PostProcessBuild] + public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) { + // We only want to do this on Steam supported platforms. + if ((target != BuildTarget.StandaloneWindows) && (target != BuildTarget.StandaloneWindows64) && (target != BuildTarget.StandaloneLinux64)) { + return; + } + + CopyDebugInfo(target, pathToBuiltProject); + + DeleteOldSteamApiDlls(target, pathToBuiltProject); + } + + static void CopyDebugInfo(BuildTarget target, string pathToBuiltProject) { + string baseDir = Path.Combine(Path.GetDirectoryName(pathToBuiltProject), Path.GetFileNameWithoutExtension(pathToBuiltProject) + "_Data"); + string pluginsDir = Path.Combine(baseDir, "Plugins"); + + // Create if it doesn't exist yet + Directory.CreateDirectory(pluginsDir); + + string[] DebugInfo = { + "Steamworks.NET created by Riley Labrecque", + "http://steamworks.github.io", + "", + "Steamworks.NET Version: " + Steamworks.Version.SteamworksNETVersion, + "Steamworks SDK Version: " + Steamworks.Version.SteamworksSDKVersion, + "Steam API DLL Version: " + Steamworks.Version.SteamAPIDLLVersion, + "Steam API DLL Size: " + Steamworks.Version.SteamAPIDLLSize, + "Steam API64 DLL Size: " + Steamworks.Version.SteamAPI64DLLSize, + "" + }; + File.WriteAllLines(Path.Combine(pluginsDir, "Steamworks.NET.txt"), DebugInfo); + } + + static void DeleteOldSteamApiDlls(BuildTarget target, string pathToBuiltProject) { + string strDllPath = Path.Combine(pathToBuiltProject, "steam_api.dll"); + if (File.Exists(strDllPath)) { + try { + File.Delete(strDllPath); + } + catch (System.Exception e) { + Debug.LogWarning($"[Steamworks.NET] Attempted to delete an old copy of 'steam_api.dll' in the following location: '{strDllPath}', but could not due to the following exception:"); + Debug.LogException(e); + } + } + + string strDll64Path = Path.Combine(pathToBuiltProject, "steam_api64.dll"); + if (File.Exists(strDll64Path)) { + try { + File.Delete(strDll64Path); + } + catch (System.Exception e) { + Debug.LogWarning($"[Steamworks.NET] Attempted to delete an old copy of 'steam_api64.dll' in the following location: '{strDll64Path}', but could not due to the following exception:"); + Debug.LogException(e); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Editor/RedistCopy.cs.meta b/Assets/com.rlabrecque.steamworks.net/Editor/RedistCopy.cs.meta new file mode 100644 index 0000000..905837f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Editor/RedistCopy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 96dd4cffb1a008c4e8d429c9f4186034 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Editor/RedistInstall.cs b/Assets/com.rlabrecque.steamworks.net/Editor/RedistInstall.cs new file mode 100644 index 0000000..2354bb9 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Editor/RedistInstall.cs @@ -0,0 +1,70 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +using UnityEngine; +using UnityEditor; +using System.IO; +using System.Collections.Generic; + +// This copys various files into their required locations when Unity is launched to make installation a breeze. +[InitializeOnLoad] +public class RedistInstall { + static RedistInstall() { + WriteSteamAppIdTxtFile(); + AddDefineSymbols(); + CheckForOldDlls(); + } + + static void WriteSteamAppIdTxtFile() { + string strCWDPath = Directory.GetCurrentDirectory(); + string strSteamAppIdPath = Path.Combine(strCWDPath, "steam_appid.txt"); + + // If the steam_appid.txt file already exists, then there's nothing to do. + if (File.Exists(strSteamAppIdPath)) { + return; + } + + Debug.Log("[Steamworks.NET] 'steam_appid.txt' is not present in the project root. Writing..."); + + try { + StreamWriter appIdFile = File.CreateText(strSteamAppIdPath); + appIdFile.Write("480"); + appIdFile.Close(); + + Debug.Log("[Steamworks.NET] Successfully copied 'steam_appid.txt' into the project root."); + } + catch (System.Exception e) { + Debug.LogWarning("[Steamworks.NET] Could not copy 'steam_appid.txt' into the project root. Please place 'steam_appid.txt' into the project root manually."); + Debug.LogException(e); + } + } + + static void CheckForOldDlls() { + string strCwdPath = Directory.GetCurrentDirectory(); + + // Unfortunately we can't just delete these outright because Unity loads the dlls in the project root instantly and Windows won't let us delete them because they are in use. + + string strDllPath = Path.Combine(strCwdPath, "steam_api.dll"); + if (File.Exists(strDllPath)) { + Debug.LogError("[Steamworks.NET] Please delete the old version of 'steam_api.dll' in your project root before continuing."); + } + + string strDll64Path = Path.Combine(strCwdPath, "steam_api64.dll"); + if (File.Exists(strDll64Path)) { + Debug.LogError("[Steamworks.NET] Please delete the old version of 'steam_api64.dll' in your project root before continuing."); + } + } + + static void AddDefineSymbols() { + string currentDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup); + HashSet defines = new HashSet(currentDefines.Split(';')) { + "STEAMWORKS_NET" + }; + + string newDefines = string.Join(";", defines); + if (newDefines != currentDefines) { + PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, newDefines); + } + } +} diff --git a/Assets/com.rlabrecque.steamworks.net/Editor/RedistInstall.cs.meta b/Assets/com.rlabrecque.steamworks.net/Editor/RedistInstall.cs.meta new file mode 100644 index 0000000..1becd9f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Editor/RedistInstall.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a716febd50f03244b98d9a5a0c6b36f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Editor/com.rlabrecque.steamworks.net.editor.asmdef b/Assets/com.rlabrecque.steamworks.net/Editor/com.rlabrecque.steamworks.net.editor.asmdef new file mode 100644 index 0000000..eab0b2b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Editor/com.rlabrecque.steamworks.net.editor.asmdef @@ -0,0 +1,18 @@ +{ + "name": "com.rlabrecque.steamworks.net.editor", + "rootNamespace": "", + "references": [ + "GUID:68bd7fdb68ef2684e982e8a9825b18a5" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Editor/com.rlabrecque.steamworks.net.editor.asmdef.meta b/Assets/com.rlabrecque.steamworks.net/Editor/com.rlabrecque.steamworks.net.editor.asmdef.meta new file mode 100644 index 0000000..9e4d5d8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Editor/com.rlabrecque.steamworks.net.editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: be281b7992e9e1840851a78ba9db107c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/LICENSE.md b/Assets/com.rlabrecque.steamworks.net/LICENSE.md new file mode 100644 index 0000000..65b3d3a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013-2022 Riley Labrecque + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Assets/com.rlabrecque.steamworks.net/LICENSE.md.meta b/Assets/com.rlabrecque.steamworks.net/LICENSE.md.meta new file mode 100644 index 0000000..e004c97 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/LICENSE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f23c4f821952c184fa3ad2e4ac6cb65b +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins.meta b/Assets/com.rlabrecque.steamworks.net/Plugins.meta new file mode 100644 index 0000000..ce4bfc8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a5651469b1f07af4694f149e4b02cb30 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/libsteam_api.so b/Assets/com.rlabrecque.steamworks.net/Plugins/libsteam_api.so new file mode 100644 index 0000000..4217a2e Binary files /dev/null and b/Assets/com.rlabrecque.steamworks.net/Plugins/libsteam_api.so differ diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/libsteam_api.so.meta b/Assets/com.rlabrecque.steamworks.net/Plugins/libsteam_api.so.meta new file mode 100644 index 0000000..f406ea5 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/libsteam_api.so.meta @@ -0,0 +1,64 @@ +fileFormatVersion: 2 +guid: 84c3b1e1d4f89ad42aca9ac3476a89f9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 0 + Exclude Win64: 0 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: Linux + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: None + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle.meta b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle.meta new file mode 100644 index 0000000..71ab7fb --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle.meta @@ -0,0 +1,65 @@ +fileFormatVersion: 2 +guid: 0b376df920bc50246801677e7b167d14 +folderAsset: yes +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 0 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: OSX + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: x86_64 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents.meta b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents.meta new file mode 100644 index 0000000..b13e7ab --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 66bf26858879bfe4fbd81f069c52d05f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/Info.plist b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/Info.plist new file mode 100644 index 0000000..459c256 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/Info.plist @@ -0,0 +1,38 @@ + + + + + BuildMachineOSBuild + 11G63 + CFBundleDevelopmentRegion + English + CFBundleExecutable + libsteam_api.dylib + CFBundleIdentifier + com.rileylabrecque.steam_api + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.57 + CSResourcesFileMapped + yes + DTCompiler + + DTPlatformBuild + 4H1503 + DTPlatformVersion + GM + DTSDKBuild + 11E52 + DTSDKName + macosx10.7 + DTXcode + 0463 + DTXcodeBuild + 4H1503 + + diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/Info.plist.meta b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/Info.plist.meta new file mode 100644 index 0000000..8fb8f59 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/Info.plist.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 471cce660e3c5e74194241e0d00ce331 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS.meta b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS.meta new file mode 100644 index 0000000..df23567 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 77908b167592ab84cbc53e9051278227 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib new file mode 100644 index 0000000..5237be0 Binary files /dev/null and b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib differ diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib.meta b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib.meta new file mode 100644 index 0000000..82cfe52 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 86a6af8103340ea4a831e76b240601c0 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.dll b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.dll new file mode 100644 index 0000000..49f738b Binary files /dev/null and b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.dll differ diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.dll.meta b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.dll.meta new file mode 100644 index 0000000..d3c89bc --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.dll.meta @@ -0,0 +1,64 @@ +fileFormatVersion: 2 +guid: f167045178ff20d45821bd7cb37231f7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude WebGL: 1 + Exclude Win: 0 + Exclude Win64: 0 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86 + DefaultValueInitialized: true + OS: Windows + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: None + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api64.dll b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api64.dll new file mode 100644 index 0000000..2b42812 Binary files /dev/null and b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api64.dll differ diff --git a/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api64.dll.meta b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api64.dll.meta new file mode 100644 index 0000000..ad52a8d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Plugins/steam_api64.dll.meta @@ -0,0 +1,64 @@ +fileFormatVersion: 2 +guid: 46713ca58de687b4db4d9684c7021923 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude WebGL: 1 + Exclude Win: 0 + Exclude Win64: 0 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: Windows + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: x86_64 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/README.md b/Assets/com.rlabrecque.steamworks.net/README.md new file mode 100644 index 0000000..46fd5fb --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/README.md @@ -0,0 +1,15 @@ +# Steamworks.NET + +_Steamworks.NET_ is a C# Wrapper for Valve's Steamworks API, it can be used either with Unity or your C# based Application. + +_Steamworks.NET_ was designed to be as close as possible to the original C++ API, as such the documentation provided from Valve largely covers usage of _Steamworks.NET_. +Niceties and C# Idioms can be easily implemented on top of _Steamworks.NET_. + +_Steamworks.NET_ fully supports Windows (32 and 64 bit), OSX, and Linux. Currently building against Steamworks SDK 1.55. + +* Author: [Riley Labrecque](https://github.com/rlabrecque) +* License: [MIT](http://www.opensource.org/licenses/mit-license.php) +* [Documentation](https://steamworks.github.io/) +* [Discussion Thread](http://steamcommunity.com/groups/steamworks/discussions/0/666827974770212954/) +* [Reporting Issues](https://github.com/rlabrecque/Steamworks.NET/issues) + Note that only Steamworks.NET specific issues should be reported, general API questions/issues should be asked on the [Steamworks discussion board](http://steamcommunity.com/groups/steamworks/discussions). diff --git a/Assets/com.rlabrecque.steamworks.net/README.md.meta b/Assets/com.rlabrecque.steamworks.net/README.md.meta new file mode 100644 index 0000000..4fe525c --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a380fe31740b8a0419ed0d7bafe229bf +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime.meta b/Assets/com.rlabrecque.steamworks.net/Runtime.meta new file mode 100644 index 0000000..4e924c2 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 376866c7c50f30c4093ff0997e4dab4f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackDispatcher.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackDispatcher.cs new file mode 100644 index 0000000..f27be5e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackDispatcher.cs @@ -0,0 +1,400 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +#if UNITY_3_5 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 + #error Unsupported Unity platform. Steamworks.NET requires Unity 4.7 or higher. +#elif UNITY_4_7 || UNITY_5 || UNITY_2017 || UNITY_2017_1_OR_NEWER + #if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR) + #define WINDOWS_BUILD + #endif +#elif STEAMWORKS_WIN + #define WINDOWS_BUILD +#elif STEAMWORKS_LIN_OSX + // So that we don't enter the else block below. +#else + #error You need to define STEAMWORKS_WIN, or STEAMWORKS_LIN_OSX. Refer to the readme for more details. +#endif + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Steamworks { + public static class CallbackDispatcher { + // We catch exceptions inside callbacks and reroute them here. + // For some reason throwing an exception causes RunCallbacks() to break otherwise. + // If you have a custom ExceptionHandler in your engine you can register it here manually until we get something more elegant hooked up. + public static void ExceptionHandler(Exception e) { +#if UNITY_STANDALONE + UnityEngine.Debug.LogException(e); +#elif STEAMWORKS_WIN || STEAMWORKS_LIN_OSX + Console.WriteLine(e.Message); +#endif + } + + private static Dictionary> m_registeredCallbacks = new Dictionary>(); + private static Dictionary> m_registeredGameServerCallbacks = new Dictionary>(); + private static Dictionary> m_registeredCallResults = new Dictionary>(); + private static object m_sync = new object(); + private static IntPtr m_pCallbackMsg; + private static int m_initCount; + + public static bool IsInitialized { + get { return m_initCount > 0; } + } + + internal static void Initialize() { + lock (m_sync) { + if (m_initCount == 0) { + NativeMethods.SteamAPI_ManualDispatch_Init(); + m_pCallbackMsg = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CallbackMsg_t))); + } + ++m_initCount; + } + } + + internal static void Shutdown() { + lock (m_sync) { + --m_initCount; + if (m_initCount == 0) { + UnregisterAll(); + Marshal.FreeHGlobal(m_pCallbackMsg); + m_pCallbackMsg = IntPtr.Zero; + } + } + } + + internal static void Register(Callback cb) { + int iCallback = CallbackIdentities.GetCallbackIdentity(cb.GetCallbackType()); + var callbacksRegistry = cb.IsGameServer ? m_registeredGameServerCallbacks : m_registeredCallbacks; + lock (m_sync) { + List callbacksList; + if (!callbacksRegistry.TryGetValue(iCallback, out callbacksList)) { + callbacksList = new List(); + callbacksRegistry.Add(iCallback, callbacksList); + } + + callbacksList.Add(cb); + } + } + + internal static void Register(SteamAPICall_t asyncCall, CallResult cr) { + lock (m_sync) { + List callResultsList; + if (!m_registeredCallResults.TryGetValue((ulong)asyncCall, out callResultsList)) { + callResultsList = new List(); + m_registeredCallResults.Add((ulong)asyncCall, callResultsList); + } + + callResultsList.Add(cr); + } + } + + internal static void Unregister(Callback cb) { + int iCallback = CallbackIdentities.GetCallbackIdentity(cb.GetCallbackType()); + var callbacksRegistry = cb.IsGameServer ? m_registeredGameServerCallbacks : m_registeredCallbacks; + lock (m_sync) { + List callbacksList; + if (callbacksRegistry.TryGetValue(iCallback, out callbacksList)) { + callbacksList.Remove(cb); + if (callbacksList.Count == 0) + callbacksRegistry.Remove(iCallback); + } + } + } + + internal static void Unregister(SteamAPICall_t asyncCall, CallResult cr) { + lock (m_sync) { + List callResultsList; + if (m_registeredCallResults.TryGetValue((ulong)asyncCall, out callResultsList)) { + callResultsList.Remove(cr); + if (callResultsList.Count == 0) + m_registeredCallResults.Remove((ulong)asyncCall); + } + } + } + + private static void UnregisterAll() { + List callbacks = new List(); + List callResults = new List(); + lock (m_sync) { + foreach (var pair in m_registeredCallbacks) { + callbacks.AddRange(pair.Value); + } + m_registeredCallbacks.Clear(); + + foreach (var pair in m_registeredGameServerCallbacks) { + callbacks.AddRange(pair.Value); + } + m_registeredGameServerCallbacks.Clear(); + + foreach (var pair in m_registeredCallResults) { + callResults.AddRange(pair.Value); + } + m_registeredCallResults.Clear(); + + foreach (var callback in callbacks) { + callback.SetUnregistered(); + } + + foreach (var callResult in callResults) { + callResult.SetUnregistered(); + } + } + } + + internal static void RunFrame(bool isGameServer) { + if (!IsInitialized) throw new InvalidOperationException("Callback dispatcher is not initialized."); + + HSteamPipe hSteamPipe = (HSteamPipe)(isGameServer ? NativeMethods.SteamGameServer_GetHSteamPipe() : NativeMethods.SteamAPI_GetHSteamPipe()); + NativeMethods.SteamAPI_ManualDispatch_RunFrame(hSteamPipe); + var callbacksRegistry = isGameServer ? m_registeredGameServerCallbacks : m_registeredCallbacks; + while (NativeMethods.SteamAPI_ManualDispatch_GetNextCallback(hSteamPipe, m_pCallbackMsg)) { + CallbackMsg_t callbackMsg = (CallbackMsg_t)Marshal.PtrToStructure(m_pCallbackMsg, typeof(CallbackMsg_t)); + try { + // Check for dispatching API call results + if (callbackMsg.m_iCallback == SteamAPICallCompleted_t.k_iCallback) { + SteamAPICallCompleted_t callCompletedCb = (SteamAPICallCompleted_t)Marshal.PtrToStructure(callbackMsg.m_pubParam, typeof(SteamAPICallCompleted_t)); + IntPtr pTmpCallResult = Marshal.AllocHGlobal((int)callCompletedCb.m_cubParam); + bool bFailed; + if (NativeMethods.SteamAPI_ManualDispatch_GetAPICallResult(hSteamPipe, callCompletedCb.m_hAsyncCall, pTmpCallResult, (int)callCompletedCb.m_cubParam, callCompletedCb.m_iCallback, out bFailed)) { + lock (m_sync) { + List callResults; + if (m_registeredCallResults.TryGetValue((ulong)callCompletedCb.m_hAsyncCall, out callResults)) { + m_registeredCallResults.Remove((ulong)callCompletedCb.m_hAsyncCall); + foreach (var cr in callResults) { + cr.OnRunCallResult(pTmpCallResult, bFailed, (ulong)callCompletedCb.m_hAsyncCall); + cr.SetUnregistered(); + } + } + } + } + Marshal.FreeHGlobal(pTmpCallResult); + } else { + List callbacks; + if (callbacksRegistry.TryGetValue(callbackMsg.m_iCallback, out callbacks)) { + List callbacksCopy; + lock (m_sync) { + callbacksCopy = new List(callbacks); + } + foreach (var callback in callbacksCopy) { + callback.OnRunCallback(callbackMsg.m_pubParam); + } + } + } + } catch (Exception e) { + ExceptionHandler(e); + } finally { + NativeMethods.SteamAPI_ManualDispatch_FreeLastCallback(hSteamPipe); + } + } + } + } + + public abstract class Callback { + public abstract bool IsGameServer { get; } + internal abstract Type GetCallbackType(); + internal abstract void OnRunCallback(IntPtr pvParam); + internal abstract void SetUnregistered(); + } + + public sealed class Callback : Callback, IDisposable { + public delegate void DispatchDelegate(T param); + private event DispatchDelegate m_Func; + + private bool m_bGameServer; + private bool m_bIsRegistered; + + private bool m_bDisposed = false; + + /// + /// Creates a new Callback. You must be calling SteamAPI.RunCallbacks() to retrieve the callbacks. + /// Returns a handle to the Callback. + /// This MUST be assigned to a member variable to prevent the GC from cleaning it up. + /// + public static Callback Create(DispatchDelegate func) { + return new Callback(func, bGameServer: false); + } + + /// + /// Creates a new GameServer Callback. You must be calling GameServer.RunCallbacks() to retrieve the callbacks. + /// Returns a handle to the Callback. + /// This MUST be assigned to a member variable to prevent the GC from cleaning it up. + /// + public static Callback CreateGameServer(DispatchDelegate func) { + return new Callback(func, bGameServer: true); + } + + public Callback(DispatchDelegate func, bool bGameServer = false) { + m_bGameServer = bGameServer; + Register(func); + } + + ~Callback() { + Dispose(); + } + + public void Dispose() { + if (m_bDisposed) { + return; + } + + GC.SuppressFinalize(this); + + if (m_bIsRegistered) + Unregister(); + + m_bDisposed = true; + } + + // Manual registration of the callback + public void Register(DispatchDelegate func) { + if (func == null) { + throw new Exception("Callback function must not be null."); + } + + if (m_bIsRegistered) { + Unregister(); + } + + m_Func = func; + + CallbackDispatcher.Register(this); + m_bIsRegistered = true; + } + + public void Unregister() { + CallbackDispatcher.Unregister(this); + m_bIsRegistered = false; + } + + public override bool IsGameServer { + get { return m_bGameServer; } + } + + internal override Type GetCallbackType() { + return typeof(T); + } + + internal override void OnRunCallback(IntPtr pvParam) { + try { + m_Func((T)Marshal.PtrToStructure(pvParam, typeof(T))); + } + catch (Exception e) { + CallbackDispatcher.ExceptionHandler(e); + } + } + + internal override void SetUnregistered() { + m_bIsRegistered = false; + } + } + + public abstract class CallResult { + internal abstract Type GetCallbackType(); + internal abstract void OnRunCallResult(IntPtr pvParam, bool bFailed, ulong hSteamAPICall); + internal abstract void SetUnregistered(); + } + + public sealed class CallResult : CallResult, IDisposable { + public delegate void APIDispatchDelegate(T param, bool bIOFailure); + private event APIDispatchDelegate m_Func; + + private SteamAPICall_t m_hAPICall = SteamAPICall_t.Invalid; + public SteamAPICall_t Handle { get { return m_hAPICall; } } + + private bool m_bDisposed = false; + + /// + /// Creates a new async CallResult. You must be calling SteamAPI.RunCallbacks() to retrieve the callback. + /// Returns a handle to the CallResult. + /// This MUST be assigned to a member variable to prevent the GC from cleaning it up. + /// + public static CallResult Create(APIDispatchDelegate func = null) { + return new CallResult(func); + } + + public CallResult(APIDispatchDelegate func = null) { + m_Func = func; + } + + ~CallResult() { + Dispose(); + } + + public void Dispose() { + if (m_bDisposed) { + return; + } + + GC.SuppressFinalize(this); + + Cancel(); + + m_bDisposed = true; + } + + public void Set(SteamAPICall_t hAPICall, APIDispatchDelegate func = null) { + // Unlike the official SDK we let the user assign a single function during creation, + // and allow them to skip having to do so every time that they call .Set() + if (func != null) { + m_Func = func; + } + + if (m_Func == null) { + throw new Exception("CallResult function was null, you must either set it in the CallResult Constructor or via Set()"); + } + + if (m_hAPICall != SteamAPICall_t.Invalid) { + CallbackDispatcher.Unregister(m_hAPICall, this); + } + + m_hAPICall = hAPICall; + + if (hAPICall != SteamAPICall_t.Invalid) { + CallbackDispatcher.Register(hAPICall, this); + } + } + + public bool IsActive() { + return (m_hAPICall != SteamAPICall_t.Invalid); + } + + public void Cancel() { + if (IsActive()) + CallbackDispatcher.Unregister(m_hAPICall, this); + } + + internal override Type GetCallbackType() { + return typeof(T); + } + + internal override void OnRunCallResult(IntPtr pvParam, bool bFailed, ulong hSteamAPICall_) { + SteamAPICall_t hSteamAPICall = (SteamAPICall_t)hSteamAPICall_; + if (hSteamAPICall == m_hAPICall) { + try { + m_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)), bFailed); + } + catch (Exception e) { + CallbackDispatcher.ExceptionHandler(e); + } + } + } + + internal override void SetUnregistered() { + m_hAPICall = SteamAPICall_t.Invalid; + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackDispatcher.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackDispatcher.cs.meta new file mode 100644 index 0000000..1cf8fbc --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackDispatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 67e97b7dd9922a94f8e5e866125a2eb3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackIdentity.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackIdentity.cs new file mode 100644 index 0000000..0862d0a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackIdentity.cs @@ -0,0 +1,35 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +namespace Steamworks { + class CallbackIdentities { + public static int GetCallbackIdentity(System.Type callbackStruct) { +#if UNITY_EDITOR || UNITY_STANDALONE || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX + foreach (CallbackIdentityAttribute attribute in callbackStruct.GetCustomAttributes(typeof(CallbackIdentityAttribute), false)) { + return attribute.Identity; + } +#endif + throw new System.Exception("Callback number not found for struct " + callbackStruct); + } + } + + [System.AttributeUsage(System.AttributeTargets.Struct, AllowMultiple = false)] + internal class CallbackIdentityAttribute : System.Attribute { + public int Identity { get; set; } + public CallbackIdentityAttribute(int callbackNum) { + Identity = callbackNum; + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackIdentity.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackIdentity.cs.meta new file mode 100644 index 0000000..dcf2883 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/CallbackIdentity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 853cf3b9a25c4b44b84691b4af4f4dcf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/ISteamMatchmakingResponses.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/ISteamMatchmakingResponses.cs new file mode 100644 index 0000000..63b5b2b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/ISteamMatchmakingResponses.cs @@ -0,0 +1,490 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +// Unity 32bit Mono on Windows crashes with ThisCall for some reason, StdCall without the 'this' ptr is the only thing that works..? +#if (UNITY_EDITOR_WIN && !UNITY_EDITOR_64) || (!UNITY_EDITOR && UNITY_STANDALONE_WIN && !UNITY_64) + #define NOTHISPTR +#endif + +using System; +using System.Runtime.InteropServices; + +namespace Steamworks { + //----------------------------------------------------------------------------- + // Purpose: Callback interface for receiving responses after a server list refresh + // or an individual server update. + // + // Since you get these callbacks after requesting full list refreshes you will + // usually implement this interface inside an object like CServerBrowser. If that + // object is getting destructed you should use ISteamMatchMakingServers()->CancelQuery() + // to cancel any in-progress queries so you don't get a callback into the destructed + // object and crash. + //----------------------------------------------------------------------------- + public class ISteamMatchmakingServerListResponse { + // Server has responded ok with updated data + public delegate void ServerResponded(HServerListRequest hRequest, int iServer); + // Server has failed to respond + public delegate void ServerFailedToRespond(HServerListRequest hRequest, int iServer); + // A list refresh you had initiated is now 100% completed + public delegate void RefreshComplete(HServerListRequest hRequest, EMatchMakingServerResponse response); + + private VTable m_VTable; + private IntPtr m_pVTable; + private GCHandle m_pGCHandle; + private ServerResponded m_ServerResponded; + private ServerFailedToRespond m_ServerFailedToRespond; + private RefreshComplete m_RefreshComplete; + + public ISteamMatchmakingServerListResponse(ServerResponded onServerResponded, ServerFailedToRespond onServerFailedToRespond, RefreshComplete onRefreshComplete) { + if (onServerResponded == null || onServerFailedToRespond == null || onRefreshComplete == null) { + throw new ArgumentNullException(); + } + m_ServerResponded = onServerResponded; + m_ServerFailedToRespond = onServerFailedToRespond; + m_RefreshComplete = onRefreshComplete; + + m_VTable = new VTable() { + m_VTServerResponded = InternalOnServerResponded, + m_VTServerFailedToRespond = InternalOnServerFailedToRespond, + m_VTRefreshComplete = InternalOnRefreshComplete + }; + m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable))); + Marshal.StructureToPtr(m_VTable, m_pVTable, false); + + m_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned); + } + + ~ISteamMatchmakingServerListResponse() { + if (m_pVTable != IntPtr.Zero) { + Marshal.FreeHGlobal(m_pVTable); + } + + if (m_pGCHandle.IsAllocated) { + m_pGCHandle.Free(); + } + } + +#if NOTHISPTR + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void InternalServerResponded(HServerListRequest hRequest, int iServer); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void InternalServerFailedToRespond(HServerListRequest hRequest, int iServer); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void InternalRefreshComplete(HServerListRequest hRequest, EMatchMakingServerResponse response); + private void InternalOnServerResponded(HServerListRequest hRequest, int iServer) { + try + { + m_ServerResponded(hRequest, iServer); + } + catch (Exception e) + { + CallbackDispatcher.ExceptionHandler(e); + } + } + private void InternalOnServerFailedToRespond(HServerListRequest hRequest, int iServer) { + try + { + m_ServerFailedToRespond(hRequest, iServer); + } + catch (Exception e) + { + CallbackDispatcher.ExceptionHandler(e); + } + } + private void InternalOnRefreshComplete(HServerListRequest hRequest, EMatchMakingServerResponse response) { + try + { + m_RefreshComplete(hRequest, response); + } + catch (Exception e) + { + CallbackDispatcher.ExceptionHandler(e); + } + } +#else + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate void InternalServerResponded(IntPtr thisptr, HServerListRequest hRequest, int iServer); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate void InternalServerFailedToRespond(IntPtr thisptr, HServerListRequest hRequest, int iServer); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate void InternalRefreshComplete(IntPtr thisptr, HServerListRequest hRequest, EMatchMakingServerResponse response); + private void InternalOnServerResponded(IntPtr thisptr, HServerListRequest hRequest, int iServer) { + try + { + m_ServerResponded(hRequest, iServer); + } + catch (Exception e) + { + CallbackDispatcher.ExceptionHandler(e); + } + } + private void InternalOnServerFailedToRespond(IntPtr thisptr, HServerListRequest hRequest, int iServer) { + try + { + m_ServerFailedToRespond(hRequest, iServer); + } + catch (Exception e) + { + CallbackDispatcher.ExceptionHandler(e); + } + } + private void InternalOnRefreshComplete(IntPtr thisptr, HServerListRequest hRequest, EMatchMakingServerResponse response) { + try + { + m_RefreshComplete(hRequest, response); + } + catch (Exception e) + { + CallbackDispatcher.ExceptionHandler(e); + } + } +#endif + + [StructLayout(LayoutKind.Sequential)] + private class VTable { + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalServerResponded m_VTServerResponded; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalServerFailedToRespond m_VTServerFailedToRespond; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRefreshComplete m_VTRefreshComplete; + } + + public static explicit operator System.IntPtr(ISteamMatchmakingServerListResponse that) { + return that.m_pGCHandle.AddrOfPinnedObject(); + } + }; + + //----------------------------------------------------------------------------- + // Purpose: Callback interface for receiving responses after pinging an individual server + // + // These callbacks all occur in response to querying an individual server + // via the ISteamMatchmakingServers()->PingServer() call below. If you are + // destructing an object that implements this interface then you should call + // ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query + // which is in progress. Failure to cancel in progress queries when destructing + // a callback handler may result in a crash when a callback later occurs. + //----------------------------------------------------------------------------- + public class ISteamMatchmakingPingResponse { + // Server has responded successfully and has updated data + public delegate void ServerResponded(gameserveritem_t server); + + // Server failed to respond to the ping request + public delegate void ServerFailedToRespond(); + + private VTable m_VTable; + private IntPtr m_pVTable; + private GCHandle m_pGCHandle; + private ServerResponded m_ServerResponded; + private ServerFailedToRespond m_ServerFailedToRespond; + + public ISteamMatchmakingPingResponse(ServerResponded onServerResponded, ServerFailedToRespond onServerFailedToRespond) { + if (onServerResponded == null || onServerFailedToRespond == null) { + throw new ArgumentNullException(); + } + m_ServerResponded = onServerResponded; + m_ServerFailedToRespond = onServerFailedToRespond; + + m_VTable = new VTable() { + m_VTServerResponded = InternalOnServerResponded, + m_VTServerFailedToRespond = InternalOnServerFailedToRespond, + }; + m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable))); + Marshal.StructureToPtr(m_VTable, m_pVTable, false); + + m_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned); + } + + ~ISteamMatchmakingPingResponse() { + if (m_pVTable != IntPtr.Zero) { + Marshal.FreeHGlobal(m_pVTable); + } + + if (m_pGCHandle.IsAllocated) { + m_pGCHandle.Free(); + } + } + +#if NOTHISPTR + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void InternalServerResponded(gameserveritem_t server); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void InternalServerFailedToRespond(); + private void InternalOnServerResponded(gameserveritem_t server) { + m_ServerResponded(server); + } + private void InternalOnServerFailedToRespond() { + m_ServerFailedToRespond(); + } +#else + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate void InternalServerResponded(IntPtr thisptr, gameserveritem_t server); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate void InternalServerFailedToRespond(IntPtr thisptr); + private void InternalOnServerResponded(IntPtr thisptr, gameserveritem_t server) { + m_ServerResponded(server); + } + private void InternalOnServerFailedToRespond(IntPtr thisptr) { + m_ServerFailedToRespond(); + } +#endif + + [StructLayout(LayoutKind.Sequential)] + private class VTable { + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalServerResponded m_VTServerResponded; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalServerFailedToRespond m_VTServerFailedToRespond; + } + + public static explicit operator System.IntPtr(ISteamMatchmakingPingResponse that) { + return that.m_pGCHandle.AddrOfPinnedObject(); + } + }; + + //----------------------------------------------------------------------------- + // Purpose: Callback interface for receiving responses after requesting details on + // who is playing on a particular server. + // + // These callbacks all occur in response to querying an individual server + // via the ISteamMatchmakingServers()->PlayerDetails() call below. If you are + // destructing an object that implements this interface then you should call + // ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query + // which is in progress. Failure to cancel in progress queries when destructing + // a callback handler may result in a crash when a callback later occurs. + //----------------------------------------------------------------------------- + public class ISteamMatchmakingPlayersResponse { + // Got data on a new player on the server -- you'll get this callback once per player + // on the server which you have requested player data on. + public delegate void AddPlayerToList(string pchName, int nScore, float flTimePlayed); + + // The server failed to respond to the request for player details + public delegate void PlayersFailedToRespond(); + + // The server has finished responding to the player details request + // (ie, you won't get anymore AddPlayerToList callbacks) + public delegate void PlayersRefreshComplete(); + + private VTable m_VTable; + private IntPtr m_pVTable; + private GCHandle m_pGCHandle; + private AddPlayerToList m_AddPlayerToList; + private PlayersFailedToRespond m_PlayersFailedToRespond; + private PlayersRefreshComplete m_PlayersRefreshComplete; + + public ISteamMatchmakingPlayersResponse(AddPlayerToList onAddPlayerToList, PlayersFailedToRespond onPlayersFailedToRespond, PlayersRefreshComplete onPlayersRefreshComplete) { + if (onAddPlayerToList == null || onPlayersFailedToRespond == null || onPlayersRefreshComplete == null) { + throw new ArgumentNullException(); + } + m_AddPlayerToList = onAddPlayerToList; + m_PlayersFailedToRespond = onPlayersFailedToRespond; + m_PlayersRefreshComplete = onPlayersRefreshComplete; + + m_VTable = new VTable() { + m_VTAddPlayerToList = InternalOnAddPlayerToList, + m_VTPlayersFailedToRespond = InternalOnPlayersFailedToRespond, + m_VTPlayersRefreshComplete = InternalOnPlayersRefreshComplete + }; + m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable))); + Marshal.StructureToPtr(m_VTable, m_pVTable, false); + + m_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned); + } + + ~ISteamMatchmakingPlayersResponse() { + if (m_pVTable != IntPtr.Zero) { + Marshal.FreeHGlobal(m_pVTable); + } + + if (m_pGCHandle.IsAllocated) { + m_pGCHandle.Free(); + } + } + +#if NOTHISPTR + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void InternalAddPlayerToList(IntPtr pchName, int nScore, float flTimePlayed); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void InternalPlayersFailedToRespond(); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void InternalPlayersRefreshComplete(); + private void InternalOnAddPlayerToList(IntPtr pchName, int nScore, float flTimePlayed) { + m_AddPlayerToList(InteropHelp.PtrToStringUTF8(pchName), nScore, flTimePlayed); + } + private void InternalOnPlayersFailedToRespond() { + m_PlayersFailedToRespond(); + } + private void InternalOnPlayersRefreshComplete() { + m_PlayersRefreshComplete(); + } +#else + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate void InternalAddPlayerToList(IntPtr thisptr, IntPtr pchName, int nScore, float flTimePlayed); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate void InternalPlayersFailedToRespond(IntPtr thisptr); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate void InternalPlayersRefreshComplete(IntPtr thisptr); + private void InternalOnAddPlayerToList(IntPtr thisptr, IntPtr pchName, int nScore, float flTimePlayed) { + m_AddPlayerToList(InteropHelp.PtrToStringUTF8(pchName), nScore, flTimePlayed); + } + private void InternalOnPlayersFailedToRespond(IntPtr thisptr) { + m_PlayersFailedToRespond(); + } + private void InternalOnPlayersRefreshComplete(IntPtr thisptr) { + m_PlayersRefreshComplete(); + } +#endif + + [StructLayout(LayoutKind.Sequential)] + private class VTable { + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalAddPlayerToList m_VTAddPlayerToList; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalPlayersFailedToRespond m_VTPlayersFailedToRespond; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalPlayersRefreshComplete m_VTPlayersRefreshComplete; + } + + public static explicit operator System.IntPtr(ISteamMatchmakingPlayersResponse that) { + return that.m_pGCHandle.AddrOfPinnedObject(); + } + }; + + //----------------------------------------------------------------------------- + // Purpose: Callback interface for receiving responses after requesting rules + // details on a particular server. + // + // These callbacks all occur in response to querying an individual server + // via the ISteamMatchmakingServers()->ServerRules() call below. If you are + // destructing an object that implements this interface then you should call + // ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query + // which is in progress. Failure to cancel in progress queries when destructing + // a callback handler may result in a crash when a callback later occurs. + //----------------------------------------------------------------------------- + public class ISteamMatchmakingRulesResponse { + // Got data on a rule on the server -- you'll get one of these per rule defined on + // the server you are querying + public delegate void RulesResponded(string pchRule, string pchValue); + + // The server failed to respond to the request for rule details + public delegate void RulesFailedToRespond(); + + // The server has finished responding to the rule details request + // (ie, you won't get anymore RulesResponded callbacks) + public delegate void RulesRefreshComplete(); + + private VTable m_VTable; + private IntPtr m_pVTable; + private GCHandle m_pGCHandle; + private RulesResponded m_RulesResponded; + private RulesFailedToRespond m_RulesFailedToRespond; + private RulesRefreshComplete m_RulesRefreshComplete; + + public ISteamMatchmakingRulesResponse(RulesResponded onRulesResponded, RulesFailedToRespond onRulesFailedToRespond, RulesRefreshComplete onRulesRefreshComplete) { + if (onRulesResponded == null || onRulesFailedToRespond == null || onRulesRefreshComplete == null) { + throw new ArgumentNullException(); + } + m_RulesResponded = onRulesResponded; + m_RulesFailedToRespond = onRulesFailedToRespond; + m_RulesRefreshComplete = onRulesRefreshComplete; + + m_VTable = new VTable() { + m_VTRulesResponded = InternalOnRulesResponded, + m_VTRulesFailedToRespond = InternalOnRulesFailedToRespond, + m_VTRulesRefreshComplete = InternalOnRulesRefreshComplete + }; + m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable))); + Marshal.StructureToPtr(m_VTable, m_pVTable, false); + + m_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned); + } + + ~ISteamMatchmakingRulesResponse() { + if (m_pVTable != IntPtr.Zero) { + Marshal.FreeHGlobal(m_pVTable); + } + + if (m_pGCHandle.IsAllocated) { + m_pGCHandle.Free(); + } + } + +#if NOTHISPTR + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void InternalRulesResponded(IntPtr pchRule, IntPtr pchValue); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void InternalRulesFailedToRespond(); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void InternalRulesRefreshComplete(); + private void InternalOnRulesResponded(IntPtr pchRule, IntPtr pchValue) { + m_RulesResponded(InteropHelp.PtrToStringUTF8(pchRule), InteropHelp.PtrToStringUTF8(pchValue)); + } + private void InternalOnRulesFailedToRespond() { + m_RulesFailedToRespond(); + } + private void InternalOnRulesRefreshComplete() { + m_RulesRefreshComplete(); + } +#else + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate void InternalRulesResponded(IntPtr thisptr, IntPtr pchRule, IntPtr pchValue); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate void InternalRulesFailedToRespond(IntPtr thisptr); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate void InternalRulesRefreshComplete(IntPtr thisptr); + private void InternalOnRulesResponded(IntPtr thisptr, IntPtr pchRule, IntPtr pchValue) { + m_RulesResponded(InteropHelp.PtrToStringUTF8(pchRule), InteropHelp.PtrToStringUTF8(pchValue)); + } + private void InternalOnRulesFailedToRespond(IntPtr thisptr) { + m_RulesFailedToRespond(); + } + private void InternalOnRulesRefreshComplete(IntPtr thisptr) { + m_RulesRefreshComplete(); + } +#endif + + [StructLayout(LayoutKind.Sequential)] + private class VTable { + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesResponded m_VTRulesResponded; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesFailedToRespond m_VTRulesFailedToRespond; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesRefreshComplete m_VTRulesRefreshComplete; + } + + public static explicit operator System.IntPtr(ISteamMatchmakingRulesResponse that) { + return that.m_pGCHandle.AddrOfPinnedObject(); + } + }; +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/ISteamMatchmakingResponses.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/ISteamMatchmakingResponses.cs.meta new file mode 100644 index 0000000..8e0f1c7 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/ISteamMatchmakingResponses.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 577f601da41ba9c4d934e78cbf1edfa6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs new file mode 100644 index 0000000..a9ae57a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs @@ -0,0 +1,267 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +using System.Text; + +namespace Steamworks { + public class InteropHelp { + public static void TestIfPlatformSupported() { +#if !UNITY_EDITOR && !UNITY_STANDALONE && !STEAMWORKS_WIN && !STEAMWORKS_LIN_OSX + throw new System.InvalidOperationException("Steamworks functions can only be called on platforms that Steam is available on."); +#endif + } + + public static void TestIfAvailableClient() { + TestIfPlatformSupported(); + if (CSteamAPIContext.GetSteamClient() == System.IntPtr.Zero) { + if (!CSteamAPIContext.Init()) { + throw new System.InvalidOperationException("Steamworks is not initialized."); + } + } + } + + public static void TestIfAvailableGameServer() { + TestIfPlatformSupported(); + if (CSteamGameServerAPIContext.GetSteamClient() == System.IntPtr.Zero) { + if (!CSteamGameServerAPIContext.Init()) { + throw new System.InvalidOperationException("Steamworks GameServer is not initialized."); + } + } + } + + // This continues to exist for both 'out string' and strings returned by Steamworks functions. + public static string PtrToStringUTF8(IntPtr nativeUtf8) { + if (nativeUtf8 == IntPtr.Zero) { + return null; + } + + int len = 0; + + while (Marshal.ReadByte(nativeUtf8, len) != 0) { + ++len; + } + + if (len == 0) { + return string.Empty; + } + + byte[] buffer = new byte[len]; + Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length); + return Encoding.UTF8.GetString(buffer); + } + + public static string ByteArrayToStringUTF8(byte[] buffer) { + int length = 0; + while (length < buffer.Length && buffer[length] != 0) { + length++; + } + + return Encoding.UTF8.GetString(buffer, 0, length); + } + + public static void StringToByteArrayUTF8(string str, byte[] outArrayBuffer, int outArrayBufferSize) + { + outArrayBuffer = new byte[outArrayBufferSize]; + int length = Encoding.UTF8.GetBytes(str, 0, str.Length, outArrayBuffer, 0); + outArrayBuffer[length] = 0; + } + + // This is for 'const char *' arguments which we need to ensure do not get GC'd while Steam is using them. + // We can't use an ICustomMarshaler because Unity crashes when a string between 96 and 127 characters long is defined/initialized at the top of class scope... +#if UNITY_EDITOR || UNITY_STANDALONE || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX + public class UTF8StringHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { + public UTF8StringHandle(string str) + : base(true) { + if (str == null) { + SetHandle(IntPtr.Zero); + return; + } + + // +1 for '\0' + byte[] strbuf = new byte[Encoding.UTF8.GetByteCount(str) + 1]; + Encoding.UTF8.GetBytes(str, 0, str.Length, strbuf, 0); + IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length); + Marshal.Copy(strbuf, 0, buffer, strbuf.Length); + + SetHandle(buffer); + } + + protected override bool ReleaseHandle() { + if (!IsInvalid) { + Marshal.FreeHGlobal(handle); + } + return true; + } + } +#else + public class UTF8StringHandle : IDisposable { + public UTF8StringHandle(string str) { } + public void Dispose() {} + } +#endif + + // TODO - Should be IDisposable + // We can't use an ICustomMarshaler because Unity dies when MarshalManagedToNative() gets called with a generic type. + public class SteamParamStringArray { + // The pointer to each AllocHGlobal() string + IntPtr[] m_Strings; + // The pointer to the condensed version of m_Strings + IntPtr m_ptrStrings; + // The pointer to the StructureToPtr version of SteamParamStringArray_t that will get marshaled + IntPtr m_pSteamParamStringArray; + + public SteamParamStringArray(System.Collections.Generic.IList strings) { + if (strings == null) { + m_pSteamParamStringArray = IntPtr.Zero; + return; + } + + m_Strings = new IntPtr[strings.Count]; + for (int i = 0; i < strings.Count; ++i) { + byte[] strbuf = new byte[Encoding.UTF8.GetByteCount(strings[i]) + 1]; + Encoding.UTF8.GetBytes(strings[i], 0, strings[i].Length, strbuf, 0); + m_Strings[i] = Marshal.AllocHGlobal(strbuf.Length); + Marshal.Copy(strbuf, 0, m_Strings[i], strbuf.Length); + } + + m_ptrStrings = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * m_Strings.Length); + SteamParamStringArray_t stringArray = new SteamParamStringArray_t() { + m_ppStrings = m_ptrStrings, + m_nNumStrings = m_Strings.Length + }; + Marshal.Copy(m_Strings, 0, stringArray.m_ppStrings, m_Strings.Length); + + m_pSteamParamStringArray = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SteamParamStringArray_t))); + Marshal.StructureToPtr(stringArray, m_pSteamParamStringArray, false); + } + + ~SteamParamStringArray() { + if (m_Strings != null) { + foreach (IntPtr ptr in m_Strings) { + Marshal.FreeHGlobal(ptr); + } + } + + if (m_ptrStrings != IntPtr.Zero) { + Marshal.FreeHGlobal(m_ptrStrings); + } + + if (m_pSteamParamStringArray != IntPtr.Zero) { + Marshal.FreeHGlobal(m_pSteamParamStringArray); + } + } + + public static implicit operator IntPtr(SteamParamStringArray that) { + return that.m_pSteamParamStringArray; + } + } + } + + // TODO - Should be IDisposable + // MatchMaking Key-Value Pair Marshaller + public class MMKVPMarshaller { + private IntPtr m_pNativeArray; + private IntPtr m_pArrayEntries; + + public MMKVPMarshaller(MatchMakingKeyValuePair_t[] filters) { + if (filters == null) { + return; + } + + int sizeOfMMKVP = Marshal.SizeOf(typeof(MatchMakingKeyValuePair_t)); + + m_pNativeArray = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * filters.Length); + m_pArrayEntries = Marshal.AllocHGlobal(sizeOfMMKVP * filters.Length); + for (int i = 0; i < filters.Length; ++i) { + Marshal.StructureToPtr(filters[i], new IntPtr(m_pArrayEntries.ToInt64() + (i * sizeOfMMKVP)), false); + } + + Marshal.WriteIntPtr(m_pNativeArray, m_pArrayEntries); + } + + ~MMKVPMarshaller() { + if (m_pArrayEntries != IntPtr.Zero) { + Marshal.FreeHGlobal(m_pArrayEntries); + } + if (m_pNativeArray != IntPtr.Zero) { + Marshal.FreeHGlobal(m_pNativeArray); + } + } + + public static implicit operator IntPtr(MMKVPMarshaller that) { + return that.m_pNativeArray; + } + } + + public class DllCheck { +#if DISABLED + [DllImport("kernel32.dll")] + public static extern IntPtr GetModuleHandle(string lpModuleName); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + extern static int GetModuleFileName(IntPtr hModule, StringBuilder strFullPath, int nSize); +#endif + + /// + /// This is an optional runtime check to ensure that the dlls are the correct version. Returns false only if the steam_api.dll is found and it's the wrong size or version number. + /// + public static bool Test() { +#if DISABLED + bool ret = CheckSteamAPIDLL(); +#endif + return true; + } + +#if DISABLED + private static bool CheckSteamAPIDLL() { + string fileName; + int fileBytes; + if (IntPtr.Size == 4) { + fileName = "steam_api.dll"; + fileBytes = Version.SteamAPIDLLSize; + } + else { + fileName = "steam_api64.dll"; + fileBytes = Version.SteamAPI64DLLSize; + } + + IntPtr handle = GetModuleHandle(fileName); + if (handle == IntPtr.Zero) { + return true; + } + + StringBuilder filePath = new StringBuilder(256); + GetModuleFileName(handle, filePath, filePath.Capacity); + string file = filePath.ToString(); + + // If we can not find the file we'll just skip it and let the DllNotFoundException take care of it. + if (System.IO.File.Exists(file)) { + System.IO.FileInfo fInfo = new System.IO.FileInfo(file); + if (fInfo.Length != fileBytes) { + return false; + } + + if (System.Diagnostics.FileVersionInfo.GetVersionInfo(file).FileVersion != Version.SteamAPIDLLVersion) { + return false; + } + } + return true; + } +#endif + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs.meta new file mode 100644 index 0000000..8dedcf8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7521a262d02c9ee47a1f08824a22b094 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/Packsize.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/Packsize.cs new file mode 100644 index 0000000..3b2efb0 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/Packsize.cs @@ -0,0 +1,71 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +// If we're running in the Unity Editor we need the editors platform. +#if UNITY_EDITOR_WIN + #define VALVE_CALLBACK_PACK_LARGE +#elif UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX + #define VALVE_CALLBACK_PACK_SMALL + +// Otherwise we want the target platform. +#elif UNITY_STANDALONE_WIN || STEAMWORKS_WIN + #define VALVE_CALLBACK_PACK_LARGE +#elif UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_LIN_OSX + #define VALVE_CALLBACK_PACK_SMALL + +// We do not want to throw a warning when we're building in Unity but for an unsupported platform. So we'll silently let this slip by. +// It would be nice if Unity itself would define 'UNITY' or something like that... +#elif UNITY_3_5 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_2017_1_OR_NEWER + #define VALVE_CALLBACK_PACK_SMALL + +// But we do want to be explicit on the Standalone build for XNA/Monogame. +#else + #define VALVE_CALLBACK_PACK_LARGE + #warning You need to define STEAMWORKS_WIN, or STEAMWORKS_LIN_OSX. Refer to the readme for more details. +#endif + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class Packsize { +#if VALVE_CALLBACK_PACK_LARGE + public const int value = 8; +#elif VALVE_CALLBACK_PACK_SMALL + public const int value = 4; +#endif + + public static bool Test() { + int sentinelSize = Marshal.SizeOf(typeof(ValvePackingSentinel_t)); + int subscribedFilesSize = Marshal.SizeOf(typeof(RemoteStorageEnumerateUserSubscribedFilesResult_t)); +#if VALVE_CALLBACK_PACK_LARGE + if (sentinelSize != 32 || subscribedFilesSize != (1 + 1 + 1 + 50 + 100) * 4 + 4) + return false; +#elif VALVE_CALLBACK_PACK_SMALL + if (sentinelSize != 24 || subscribedFilesSize != (1 + 1 + 1 + 50 + 100) * 4) + return false; +#endif + return true; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + struct ValvePackingSentinel_t { + uint m_u32; + ulong m_u64; + ushort m_u16; + double m_d; + }; + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/Packsize.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/Packsize.cs.meta new file mode 100644 index 0000000..3d78af9 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/Packsize.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c871c983f47850a41a28b6c09b5d9542 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/Steam.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/Steam.cs new file mode 100644 index 0000000..5141233 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/Steam.cs @@ -0,0 +1,568 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamAPI { + //----------------------------------------------------------------------------------------------------------------------------------------------------------// + // Steam API setup & shutdown + // + // These functions manage loading, initializing and shutdown of the steamclient.dll + // + //----------------------------------------------------------------------------------------------------------------------------------------------------------// + + + // SteamAPI_Init must be called before using any other API functions. If it fails, an + // error message will be output to the debugger (or stderr) with further information. + public static bool Init() { + InteropHelp.TestIfPlatformSupported(); + + bool ret = NativeMethods.SteamAPI_Init(); + + // Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it + // every time that Unity reloads binaries, so we also check if the pointers are available and initialized + // before each call to any interface functions. That is in InteropHelp.cs + if (ret) { + ret = CSteamAPIContext.Init(); + } + + if (ret) { + CallbackDispatcher.Initialize(); + } + + return ret; + } + + // SteamAPI_Shutdown should be called during process shutdown if possible. + public static void Shutdown() { + InteropHelp.TestIfPlatformSupported(); + NativeMethods.SteamAPI_Shutdown(); + CSteamAPIContext.Clear(); + CallbackDispatcher.Shutdown(); + } + + // SteamAPI_RestartAppIfNecessary ensures that your executable was launched through Steam. + // + // Returns true if the current process should terminate. Steam is now re-launching your application. + // + // Returns false if no action needs to be taken. This means that your executable was started through + // the Steam client, or a steam_appid.txt file is present in your game's directory (for development). + // Your current process should continue if false is returned. + // + // NOTE: If you use the Steam DRM wrapper on your primary executable file, this check is unnecessary + // since the DRM wrapper will ensure that your application was launched properly through Steam. + public static bool RestartAppIfNecessary(AppId_t unOwnAppID) { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamAPI_RestartAppIfNecessary(unOwnAppID); + } + + // Many Steam API functions allocate a small amount of thread-local memory for parameter storage. + // SteamAPI_ReleaseCurrentThreadMemory() will free API memory associated with the calling thread. + // This function is also called automatically by SteamAPI_RunCallbacks(), so a single-threaded + // program never needs to explicitly call this function. + public static void ReleaseCurrentThreadMemory() { + InteropHelp.TestIfPlatformSupported(); + NativeMethods.SteamAPI_ReleaseCurrentThreadMemory(); + } + + //----------------------------------------------------------------------------------------------------------------------------------------------------------// + // steam callback and call-result helpers + // + // The following macros and classes are used to register your application for + // callbacks and call-results, which are delivered in a predictable manner. + // + // STEAM_CALLBACK macros are meant for use inside of a C++ class definition. + // They map a Steam notification callback directly to a class member function + // which is automatically prototyped as "void func( callback_type *pParam )". + // + // CCallResult is used with specific Steam APIs that return "result handles". + // The handle can be passed to a CCallResult object's Set function, along with + // an object pointer and member-function pointer. The member function will + // be executed once the results of the Steam API call are available. + // + // CCallback and CCallbackManual classes can be used instead of STEAM_CALLBACK + // macros if you require finer control over registration and unregistration. + // + // Callbacks and call-results are queued automatically and are only + // delivered/executed when your application calls SteamAPI_RunCallbacks(). + // + // Note that there is an alternative, lower level callback dispatch mechanism. + // See SteamAPI_ManualDispatch_Init + //----------------------------------------------------------------------------------------------------------------------------------------------------------// + + // Dispatch all queued Steamworks callbacks. + // + // This is safe to call from multiple threads simultaneously, + // but if you choose to do this, callback code could be executed on any thread. + // One alternative is to call SteamAPI_RunCallbacks from the main thread only, + // and call SteamAPI_ReleaseCurrentThreadMemory regularly on other threads. + public static void RunCallbacks() { + CallbackDispatcher.RunFrame(false); + } + + //----------------------------------------------------------------------------------------------------------------------------------------------------------// + // steamclient.dll private wrapper functions + // + // The following functions are part of abstracting API access to the steamclient.dll, but should only be used in very specific cases + //----------------------------------------------------------------------------------------------------------------------------------------------------------// + + // SteamAPI_IsSteamRunning() returns true if Steam is currently running + public static bool IsSteamRunning() { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamAPI_IsSteamRunning(); + } + + // returns the pipe we are communicating to Steam with + public static HSteamPipe GetHSteamPipe() { + InteropHelp.TestIfPlatformSupported(); + return (HSteamPipe)NativeMethods.SteamAPI_GetHSteamPipe(); + } + + public static HSteamUser GetHSteamUser() { + InteropHelp.TestIfPlatformSupported(); + return (HSteamUser)NativeMethods.SteamAPI_GetHSteamUser(); + } + } + + public static class GameServer { + // Initialize SteamGameServer client and interface objects, and set server properties which may not be changed. + // + // After calling this function, you should set any additional server parameters, and then + // call ISteamGameServer::LogOnAnonymous() or ISteamGameServer::LogOn() + // + // - unIP will usually be zero. If you are on a machine with multiple IP addresses, you can pass a non-zero + // value here and the relevant sockets will be bound to that IP. This can be used to ensure that + // the IP you desire is the one used in the server browser. + // - usGamePort is the port that clients will connect to for gameplay. You will usually open up your + // own socket bound to this port. + // - usQueryPort is the port that will manage server browser related duties and info + // pings from clients. If you pass STEAMGAMESERVER_QUERY_PORT_SHARED for usQueryPort, then it + // will use "GameSocketShare" mode, which means that the game is responsible for sending and receiving + // UDP packets for the master server updater. (See ISteamGameServer::HandleIncomingPacket and + // ISteamGameServer::GetNextOutgoingPacket.) + // - The version string should be in the form x.x.x.x, and is used by the master server to detect when the + // server is out of date. (Only servers with the latest version will be listed.) + public static bool Init(uint unIP, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, string pchVersionString) { + InteropHelp.TestIfPlatformSupported(); + + bool ret; + using (var pchVersionString2 = new InteropHelp.UTF8StringHandle(pchVersionString)) { + ret = NativeMethods.SteamInternal_GameServer_Init(unIP, 0, usGamePort, usQueryPort, eServerMode, pchVersionString2); + } + + // Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it + // every time that Unity reloads binaries, so we also check if the pointers are available and initialized + // before each call to any interface functions. That is in InteropHelp.cs + if (ret) { + ret = CSteamGameServerAPIContext.Init(); + } + + if (ret) { + CallbackDispatcher.Initialize(); + } + + return ret; + } + + // Shutdown SteamGameSeverXxx interfaces, log out, and free resources. + public static void Shutdown() { + InteropHelp.TestIfPlatformSupported(); + NativeMethods.SteamGameServer_Shutdown(); + CSteamGameServerAPIContext.Clear(); + CallbackDispatcher.Shutdown(); + } + + public static void RunCallbacks() { + CallbackDispatcher.RunFrame(true); + } + + // Most Steam API functions allocate some amount of thread-local memory for + // parameter storage. Calling SteamGameServer_ReleaseCurrentThreadMemory() + // will free all API-related memory associated with the calling thread. + // This memory is released automatically by SteamGameServer_RunCallbacks(), + // so single-threaded servers do not need to explicitly call this function. + public static void ReleaseCurrentThreadMemory() { + InteropHelp.TestIfPlatformSupported(); + NativeMethods.SteamGameServer_ReleaseCurrentThreadMemory(); + } + + public static bool BSecure() { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamGameServer_BSecure(); + } + + public static CSteamID GetSteamID() { + InteropHelp.TestIfPlatformSupported(); + return (CSteamID)NativeMethods.SteamGameServer_GetSteamID(); + } + + public static HSteamPipe GetHSteamPipe() { + InteropHelp.TestIfPlatformSupported(); + return (HSteamPipe)NativeMethods.SteamGameServer_GetHSteamPipe(); + } + + public static HSteamUser GetHSteamUser() { + InteropHelp.TestIfPlatformSupported(); + return (HSteamUser)NativeMethods.SteamGameServer_GetHSteamUser(); + } + } + + public static class SteamEncryptedAppTicket { + public static bool BDecryptTicket(byte[] rgubTicketEncrypted, uint cubTicketEncrypted, byte[] rgubTicketDecrypted, ref uint pcubTicketDecrypted, byte[] rgubKey, int cubKey) { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamEncryptedAppTicket_BDecryptTicket(rgubTicketEncrypted, cubTicketEncrypted, rgubTicketDecrypted, ref pcubTicketDecrypted, rgubKey, cubKey); + } + + public static bool BIsTicketForApp(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, AppId_t nAppID) { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamEncryptedAppTicket_BIsTicketForApp(rgubTicketDecrypted, cubTicketDecrypted, nAppID); + } + + public static uint GetTicketIssueTime(byte[] rgubTicketDecrypted, uint cubTicketDecrypted) { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamEncryptedAppTicket_GetTicketIssueTime(rgubTicketDecrypted, cubTicketDecrypted); + } + + public static void GetTicketSteamID(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, out CSteamID psteamID) { + InteropHelp.TestIfPlatformSupported(); + NativeMethods.SteamEncryptedAppTicket_GetTicketSteamID(rgubTicketDecrypted, cubTicketDecrypted, out psteamID); + } + + public static uint GetTicketAppID(byte[] rgubTicketDecrypted, uint cubTicketDecrypted) { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamEncryptedAppTicket_GetTicketAppID(rgubTicketDecrypted, cubTicketDecrypted); + } + + public static bool BUserOwnsAppInTicket(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, AppId_t nAppID) { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamEncryptedAppTicket_BUserOwnsAppInTicket(rgubTicketDecrypted, cubTicketDecrypted, nAppID); + } + + public static bool BUserIsVacBanned(byte[] rgubTicketDecrypted, uint cubTicketDecrypted) { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamEncryptedAppTicket_BUserIsVacBanned(rgubTicketDecrypted, cubTicketDecrypted); + } + + public static byte[] GetUserVariableData(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, out uint pcubUserData) { + InteropHelp.TestIfPlatformSupported(); + IntPtr punSecretData = NativeMethods.SteamEncryptedAppTicket_GetUserVariableData(rgubTicketDecrypted, cubTicketDecrypted, out pcubUserData); + byte[] ret = new byte[pcubUserData]; + System.Runtime.InteropServices.Marshal.Copy(punSecretData, ret, 0, (int)pcubUserData); + return ret; + } + + public static bool BIsTicketSigned(byte[] rgubTicketDecrypted, uint cubTicketDecrypted, byte[] pubRSAKey, uint cubRSAKey) { + InteropHelp.TestIfPlatformSupported(); + return NativeMethods.SteamEncryptedAppTicket_BIsTicketSigned(rgubTicketDecrypted, cubTicketDecrypted, pubRSAKey, cubRSAKey); + } + } + + internal static class CSteamAPIContext { + internal static void Clear() { + m_pSteamClient = IntPtr.Zero; + m_pSteamUser = IntPtr.Zero; + m_pSteamFriends = IntPtr.Zero; + m_pSteamUtils = IntPtr.Zero; + m_pSteamMatchmaking = IntPtr.Zero; + m_pSteamUserStats = IntPtr.Zero; + m_pSteamApps = IntPtr.Zero; + m_pSteamMatchmakingServers = IntPtr.Zero; + m_pSteamNetworking = IntPtr.Zero; + m_pSteamRemoteStorage = IntPtr.Zero; + m_pSteamHTTP = IntPtr.Zero; + m_pSteamScreenshots = IntPtr.Zero; + m_pSteamGameSearch = IntPtr.Zero; + m_pSteamMusic = IntPtr.Zero; + m_pController = IntPtr.Zero; + m_pSteamUGC = IntPtr.Zero; + m_pSteamAppList = IntPtr.Zero; + m_pSteamMusic = IntPtr.Zero; + m_pSteamMusicRemote = IntPtr.Zero; + m_pSteamHTMLSurface = IntPtr.Zero; + m_pSteamInventory = IntPtr.Zero; + m_pSteamVideo = IntPtr.Zero; + m_pSteamParentalSettings = IntPtr.Zero; + m_pSteamInput = IntPtr.Zero; + m_pSteamParties = IntPtr.Zero; + m_pSteamRemotePlay = IntPtr.Zero; + m_pSteamNetworkingUtils = IntPtr.Zero; + m_pSteamNetworkingSockets = IntPtr.Zero; + m_pSteamNetworkingMessages = IntPtr.Zero; + } + + internal static bool Init() { + HSteamUser hSteamUser = SteamAPI.GetHSteamUser(); + HSteamPipe hSteamPipe = SteamAPI.GetHSteamPipe(); + if (hSteamPipe == (HSteamPipe)0) { return false; } + + using (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMCLIENT_INTERFACE_VERSION)) { + m_pSteamClient = NativeMethods.SteamInternal_CreateInterface(pchVersionString); + } + + if (m_pSteamClient == IntPtr.Zero) { return false; } + + m_pSteamUser = SteamClient.GetISteamUser(hSteamUser, hSteamPipe, Constants.STEAMUSER_INTERFACE_VERSION); + if (m_pSteamUser == IntPtr.Zero) { return false; } + + m_pSteamFriends = SteamClient.GetISteamFriends(hSteamUser, hSteamPipe, Constants.STEAMFRIENDS_INTERFACE_VERSION); + if (m_pSteamFriends == IntPtr.Zero) { return false; } + + m_pSteamUtils = SteamClient.GetISteamUtils(hSteamPipe, Constants.STEAMUTILS_INTERFACE_VERSION); + if (m_pSteamUtils == IntPtr.Zero) { return false; } + + m_pSteamMatchmaking = SteamClient.GetISteamMatchmaking(hSteamUser, hSteamPipe, Constants.STEAMMATCHMAKING_INTERFACE_VERSION); + if (m_pSteamMatchmaking == IntPtr.Zero) { return false; } + + m_pSteamMatchmakingServers = SteamClient.GetISteamMatchmakingServers(hSteamUser, hSteamPipe, Constants.STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION); + if (m_pSteamMatchmakingServers == IntPtr.Zero) { return false; } + + m_pSteamUserStats = SteamClient.GetISteamUserStats(hSteamUser, hSteamPipe, Constants.STEAMUSERSTATS_INTERFACE_VERSION); + if (m_pSteamUserStats == IntPtr.Zero) { return false; } + + m_pSteamApps = SteamClient.GetISteamApps(hSteamUser, hSteamPipe, Constants.STEAMAPPS_INTERFACE_VERSION); + if (m_pSteamApps == IntPtr.Zero) { return false; } + + m_pSteamNetworking = SteamClient.GetISteamNetworking(hSteamUser, hSteamPipe, Constants.STEAMNETWORKING_INTERFACE_VERSION); + if (m_pSteamNetworking == IntPtr.Zero) { return false; } + + m_pSteamRemoteStorage = SteamClient.GetISteamRemoteStorage(hSteamUser, hSteamPipe, Constants.STEAMREMOTESTORAGE_INTERFACE_VERSION); + if (m_pSteamRemoteStorage == IntPtr.Zero) { return false; } + + m_pSteamScreenshots = SteamClient.GetISteamScreenshots(hSteamUser, hSteamPipe, Constants.STEAMSCREENSHOTS_INTERFACE_VERSION); + if (m_pSteamScreenshots == IntPtr.Zero) { return false; } + + m_pSteamGameSearch = SteamClient.GetISteamGameSearch(hSteamUser, hSteamPipe, Constants.STEAMGAMESEARCH_INTERFACE_VERSION); + if (m_pSteamGameSearch == IntPtr.Zero) { return false; } + + m_pSteamHTTP = SteamClient.GetISteamHTTP(hSteamUser, hSteamPipe, Constants.STEAMHTTP_INTERFACE_VERSION); + if (m_pSteamHTTP == IntPtr.Zero) { return false; } + + m_pSteamUGC = SteamClient.GetISteamUGC(hSteamUser, hSteamPipe, Constants.STEAMUGC_INTERFACE_VERSION); + if (m_pSteamUGC == IntPtr.Zero) { return false; } + + m_pSteamAppList = SteamClient.GetISteamAppList(hSteamUser, hSteamPipe, Constants.STEAMAPPLIST_INTERFACE_VERSION); + if (m_pSteamAppList == IntPtr.Zero) { return false; } + + m_pSteamMusic = SteamClient.GetISteamMusic(hSteamUser, hSteamPipe, Constants.STEAMMUSIC_INTERFACE_VERSION); + if (m_pSteamMusic == IntPtr.Zero) { return false; } + + m_pSteamMusicRemote = SteamClient.GetISteamMusicRemote(hSteamUser, hSteamPipe, Constants.STEAMMUSICREMOTE_INTERFACE_VERSION); + if (m_pSteamMusicRemote == IntPtr.Zero) { return false; } + + m_pSteamHTMLSurface = SteamClient.GetISteamHTMLSurface(hSteamUser, hSteamPipe, Constants.STEAMHTMLSURFACE_INTERFACE_VERSION); + if (m_pSteamHTMLSurface == IntPtr.Zero) { return false; } + + m_pSteamInventory = SteamClient.GetISteamInventory(hSteamUser, hSteamPipe, Constants.STEAMINVENTORY_INTERFACE_VERSION); + if (m_pSteamInventory == IntPtr.Zero) { return false; } + + m_pSteamVideo = SteamClient.GetISteamVideo(hSteamUser, hSteamPipe, Constants.STEAMVIDEO_INTERFACE_VERSION); + if (m_pSteamVideo == IntPtr.Zero) { return false; } + + m_pSteamParentalSettings = SteamClient.GetISteamParentalSettings(hSteamUser, hSteamPipe, Constants.STEAMPARENTALSETTINGS_INTERFACE_VERSION); + if (m_pSteamParentalSettings == IntPtr.Zero) { return false; } + + m_pSteamInput = SteamClient.GetISteamInput(hSteamUser, hSteamPipe, Constants.STEAMINPUT_INTERFACE_VERSION); + if (m_pSteamInput == IntPtr.Zero) { return false; } + + m_pSteamParties = SteamClient.GetISteamParties(hSteamUser, hSteamPipe, Constants.STEAMPARTIES_INTERFACE_VERSION); + if (m_pSteamParties == IntPtr.Zero) { return false; } + + m_pSteamRemotePlay = SteamClient.GetISteamRemotePlay(hSteamUser, hSteamPipe, Constants.STEAMREMOTEPLAY_INTERFACE_VERSION); + if (m_pSteamRemotePlay == IntPtr.Zero) { return false; } + + using (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMNETWORKINGUTILS_INTERFACE_VERSION)) + { + m_pSteamNetworkingUtils = + NativeMethods.SteamInternal_FindOrCreateUserInterface(hSteamUser, pchVersionString) != IntPtr.Zero ? + NativeMethods.SteamInternal_FindOrCreateUserInterface(hSteamUser, pchVersionString) : + NativeMethods.SteamInternal_FindOrCreateGameServerInterface(hSteamUser, pchVersionString); + } + if (m_pSteamNetworkingUtils == IntPtr.Zero) { return false; } + + using (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMNETWORKINGSOCKETS_INTERFACE_VERSION)) + { + m_pSteamNetworkingSockets = + NativeMethods.SteamInternal_FindOrCreateUserInterface(hSteamUser, pchVersionString); + } + if (m_pSteamNetworkingSockets == IntPtr.Zero) { return false; } + + using (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMNETWORKINGMESSAGES_INTERFACE_VERSION)) + { + m_pSteamNetworkingMessages = + NativeMethods.SteamInternal_FindOrCreateUserInterface(hSteamUser, pchVersionString); + } + if (m_pSteamNetworkingMessages == IntPtr.Zero) { return false; } + + return true; + } + + internal static IntPtr GetSteamClient() { return m_pSteamClient; } + internal static IntPtr GetSteamUser() { return m_pSteamUser; } + internal static IntPtr GetSteamFriends() { return m_pSteamFriends; } + internal static IntPtr GetSteamUtils() { return m_pSteamUtils; } + internal static IntPtr GetSteamMatchmaking() { return m_pSteamMatchmaking; } + internal static IntPtr GetSteamUserStats() { return m_pSteamUserStats; } + internal static IntPtr GetSteamApps() { return m_pSteamApps; } + internal static IntPtr GetSteamMatchmakingServers() { return m_pSteamMatchmakingServers; } + internal static IntPtr GetSteamNetworking() { return m_pSteamNetworking; } + internal static IntPtr GetSteamRemoteStorage() { return m_pSteamRemoteStorage; } + internal static IntPtr GetSteamScreenshots() { return m_pSteamScreenshots; } + internal static IntPtr GetSteamGameSearch() { return m_pSteamGameSearch; } + internal static IntPtr GetSteamHTTP() { return m_pSteamHTTP; } + internal static IntPtr GetSteamController() { return m_pController; } + internal static IntPtr GetSteamUGC() { return m_pSteamUGC; } + internal static IntPtr GetSteamAppList() { return m_pSteamAppList; } + internal static IntPtr GetSteamMusic() { return m_pSteamMusic; } + internal static IntPtr GetSteamMusicRemote() { return m_pSteamMusicRemote; } + internal static IntPtr GetSteamHTMLSurface() { return m_pSteamHTMLSurface; } + internal static IntPtr GetSteamInventory() { return m_pSteamInventory; } + internal static IntPtr GetSteamVideo() { return m_pSteamVideo; } + internal static IntPtr GetSteamParentalSettings() { return m_pSteamParentalSettings; } + internal static IntPtr GetSteamInput() { return m_pSteamInput; } + internal static IntPtr GetSteamParties() { return m_pSteamParties; } + internal static IntPtr GetSteamRemotePlay() { return m_pSteamRemotePlay; } + internal static IntPtr GetSteamNetworkingUtils() { return m_pSteamNetworkingUtils; } + internal static IntPtr GetSteamNetworkingSockets() { return m_pSteamNetworkingSockets; } + internal static IntPtr GetSteamNetworkingMessages() { return m_pSteamNetworkingMessages; } + + private static IntPtr m_pSteamClient; + private static IntPtr m_pSteamUser; + private static IntPtr m_pSteamFriends; + private static IntPtr m_pSteamUtils; + private static IntPtr m_pSteamMatchmaking; + private static IntPtr m_pSteamUserStats; + private static IntPtr m_pSteamApps; + private static IntPtr m_pSteamMatchmakingServers; + private static IntPtr m_pSteamNetworking; + private static IntPtr m_pSteamRemoteStorage; + private static IntPtr m_pSteamScreenshots; + private static IntPtr m_pSteamGameSearch; + private static IntPtr m_pSteamHTTP; + private static IntPtr m_pController; + private static IntPtr m_pSteamUGC; + private static IntPtr m_pSteamAppList; + private static IntPtr m_pSteamMusic; + private static IntPtr m_pSteamMusicRemote; + private static IntPtr m_pSteamHTMLSurface; + private static IntPtr m_pSteamInventory; + private static IntPtr m_pSteamVideo; + private static IntPtr m_pSteamParentalSettings; + private static IntPtr m_pSteamInput; + private static IntPtr m_pSteamParties; + private static IntPtr m_pSteamRemotePlay; + private static IntPtr m_pSteamNetworkingUtils; + private static IntPtr m_pSteamNetworkingSockets; + private static IntPtr m_pSteamNetworkingMessages; + } + + internal static class CSteamGameServerAPIContext { + internal static void Clear() { + m_pSteamClient = IntPtr.Zero; + m_pSteamGameServer = IntPtr.Zero; + m_pSteamUtils = IntPtr.Zero; + m_pSteamNetworking = IntPtr.Zero; + m_pSteamGameServerStats = IntPtr.Zero; + m_pSteamHTTP = IntPtr.Zero; + m_pSteamInventory = IntPtr.Zero; + m_pSteamUGC = IntPtr.Zero; + m_pSteamNetworkingUtils = IntPtr.Zero; + m_pSteamNetworkingSockets = IntPtr.Zero; + m_pSteamNetworkingMessages = IntPtr.Zero; + } + + internal static bool Init() { + HSteamUser hSteamUser = GameServer.GetHSteamUser(); + HSteamPipe hSteamPipe = GameServer.GetHSteamPipe(); + if (hSteamPipe == (HSteamPipe)0) { return false; } + + using (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMCLIENT_INTERFACE_VERSION)) { + m_pSteamClient = NativeMethods.SteamInternal_CreateInterface(pchVersionString); + } + if (m_pSteamClient == IntPtr.Zero) { return false; } + + m_pSteamGameServer = SteamGameServerClient.GetISteamGameServer(hSteamUser, hSteamPipe, Constants.STEAMGAMESERVER_INTERFACE_VERSION); + if (m_pSteamGameServer == IntPtr.Zero) { return false; } + + m_pSteamUtils = SteamGameServerClient.GetISteamUtils(hSteamPipe, Constants.STEAMUTILS_INTERFACE_VERSION); + if (m_pSteamUtils == IntPtr.Zero) { return false; } + + m_pSteamNetworking = SteamGameServerClient.GetISteamNetworking(hSteamUser, hSteamPipe, Constants.STEAMNETWORKING_INTERFACE_VERSION); + if (m_pSteamNetworking == IntPtr.Zero) { return false; } + + m_pSteamGameServerStats = SteamGameServerClient.GetISteamGameServerStats(hSteamUser, hSteamPipe, Constants.STEAMGAMESERVERSTATS_INTERFACE_VERSION); + if (m_pSteamGameServerStats == IntPtr.Zero) { return false; } + + m_pSteamHTTP = SteamGameServerClient.GetISteamHTTP(hSteamUser, hSteamPipe, Constants.STEAMHTTP_INTERFACE_VERSION); + if (m_pSteamHTTP == IntPtr.Zero) { return false; } + + m_pSteamInventory = SteamGameServerClient.GetISteamInventory(hSteamUser, hSteamPipe, Constants.STEAMINVENTORY_INTERFACE_VERSION); + if (m_pSteamInventory == IntPtr.Zero) { return false; } + + m_pSteamUGC = SteamGameServerClient.GetISteamUGC(hSteamUser, hSteamPipe, Constants.STEAMUGC_INTERFACE_VERSION); + if (m_pSteamUGC == IntPtr.Zero) { return false; } + + using (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMNETWORKINGUTILS_INTERFACE_VERSION)) + { + m_pSteamNetworkingUtils = + NativeMethods.SteamInternal_FindOrCreateUserInterface(hSteamUser, pchVersionString) != IntPtr.Zero ? + NativeMethods.SteamInternal_FindOrCreateUserInterface(hSteamUser, pchVersionString) : + NativeMethods.SteamInternal_FindOrCreateGameServerInterface(hSteamUser, pchVersionString); + } + if (m_pSteamNetworkingUtils == IntPtr.Zero) { return false; } + + using (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMNETWORKINGSOCKETS_INTERFACE_VERSION)) + { + m_pSteamNetworkingSockets = + NativeMethods.SteamInternal_FindOrCreateGameServerInterface(hSteamUser, pchVersionString); + } + if (m_pSteamNetworkingSockets == IntPtr.Zero) { return false; } + + using (var pchVersionString = new InteropHelp.UTF8StringHandle(Constants.STEAMNETWORKINGMESSAGES_INTERFACE_VERSION)) + { + m_pSteamNetworkingMessages = + NativeMethods.SteamInternal_FindOrCreateGameServerInterface(hSteamUser, pchVersionString); + } + if (m_pSteamNetworkingMessages == IntPtr.Zero) { return false; } + + return true; + } + + internal static IntPtr GetSteamClient() { return m_pSteamClient; } + internal static IntPtr GetSteamGameServer() { return m_pSteamGameServer; } + internal static IntPtr GetSteamUtils() { return m_pSteamUtils; } + internal static IntPtr GetSteamNetworking() { return m_pSteamNetworking; } + internal static IntPtr GetSteamGameServerStats() { return m_pSteamGameServerStats; } + internal static IntPtr GetSteamHTTP() { return m_pSteamHTTP; } + internal static IntPtr GetSteamInventory() { return m_pSteamInventory; } + internal static IntPtr GetSteamUGC() { return m_pSteamUGC; } + internal static IntPtr GetSteamNetworkingUtils() { return m_pSteamNetworkingUtils; } + internal static IntPtr GetSteamNetworkingSockets() { return m_pSteamNetworkingSockets; } + internal static IntPtr GetSteamNetworkingMessages() { return m_pSteamNetworkingMessages; } + + private static IntPtr m_pSteamClient; + private static IntPtr m_pSteamGameServer; + private static IntPtr m_pSteamUtils; + private static IntPtr m_pSteamNetworking; + private static IntPtr m_pSteamGameServerStats; + private static IntPtr m_pSteamHTTP; + private static IntPtr m_pSteamInventory; + private static IntPtr m_pSteamUGC; + private static IntPtr m_pSteamNetworkingUtils; + private static IntPtr m_pSteamNetworkingSockets; + private static IntPtr m_pSteamNetworkingMessages; + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/Steam.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/Steam.cs.meta new file mode 100644 index 0000000..58d78df --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/Steam.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c098e483776b9b4e9d4fd8af8558ba1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/Version.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/Version.cs new file mode 100644 index 0000000..387af1f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/Version.cs @@ -0,0 +1,24 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) +#define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +namespace Steamworks { + public static class Version { + public const string SteamworksNETVersion = "20.2.0"; + public const string SteamworksSDKVersion = "1.57"; + public const string SteamAPIDLLVersion = "08.02.21.95"; + public const int SteamAPIDLLSize = 266600; + public const int SteamAPI64DLLSize = 298856; + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/Version.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/Version.cs.meta new file mode 100644 index 0000000..d3eafce --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/Version.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 392a7b7ab9d780b4ea56fa9efbd249af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen.meta new file mode 100644 index 0000000..4526f9c --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1214e34c8204bed46a26ab9d7f6b5a7b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs new file mode 100644 index 0000000..80f45a0 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs @@ -0,0 +1,3337 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +#if UNITY_EDITOR_64 || (UNITY_STANDALONE && !UNITY_EDITOR && UNITY_64) + #define STEAMWORKS_X64 +#elif UNITY_EDITOR_32 || (UNITY_STANDALONE && !UNITY_EDITOR && !UNITY_64) + #define STEAMWORKS_X86 +#endif + +#if UNITY_EDITOR_WIN + #define STEAMWORKS_WIN +#elif UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX + #define STEAMWORKS_LIN_OSX +#elif UNITY_STANDALONE_WIN + #define STEAMWORKS_WIN +#elif UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX + #define STEAMWORKS_LIN_OSX +#endif + +#if !STEAMWORKS_WIN && !STEAMWORKS_LIN_OSX + #error You must define STEAMWORKS_WIN or STEAMWORKS_LIN_OSX if you're not using Unity. +#endif + +#define STEAMNETWORKINGSOCKETS_ENABLE_SDR + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Security.SuppressUnmanagedCodeSecurity()] + internal static class NativeMethods { +#if STEAMWORKS_WIN && STEAMWORKS_X64 + internal const string NativeLibraryName = "steam_api64"; + internal const string NativeLibrary_SDKEncryptedAppTicket = "sdkencryptedappticket64"; +#else + internal const string NativeLibraryName = "steam_api"; + internal const string NativeLibrary_SDKEncryptedAppTicket = "sdkencryptedappticket"; +#endif + +#region steam_api.h + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_Init", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_Init(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_Shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_Shutdown(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_RestartAppIfNecessary", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_RestartAppIfNecessary(AppId_t unOwnAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ReleaseCurrentThreadMemory", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_ReleaseCurrentThreadMemory(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_WriteMiniDump", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_WriteMiniDump(uint uStructuredExceptionCode, IntPtr pvExceptionInfo, uint uBuildID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SetMiniDumpComment", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SetMiniDumpComment(InteropHelp.UTF8StringHandle pchMsg); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_RunCallbacks", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_RunCallbacks(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_RegisterCallback", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_RegisterCallback(IntPtr pCallback, int iCallback); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_UnregisterCallback", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_UnregisterCallback(IntPtr pCallback); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_RegisterCallResult", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_RegisterCallResult(IntPtr pCallback, ulong hAPICall); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_UnregisterCallResult", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_UnregisterCallResult(IntPtr pCallback, ulong hAPICall); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_IsSteamRunning", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_IsSteamRunning(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_GetSteamInstallPath", CallingConvention = CallingConvention.Cdecl)] + public static extern int SteamAPI_GetSteamInstallPath(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_GetHSteamPipe", CallingConvention = CallingConvention.Cdecl)] + public static extern int SteamAPI_GetHSteamPipe(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SetTryCatchCallbacks", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SetTryCatchCallbacks([MarshalAs(UnmanagedType.I1)] bool bTryCatchCallbacks); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_GetHSteamUser", CallingConvention = CallingConvention.Cdecl)] + public static extern int SteamAPI_GetHSteamUser(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamInternal_ContextInit", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamInternal_ContextInit(IntPtr pContextInitData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamInternal_CreateInterface", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamInternal_CreateInterface(InteropHelp.UTF8StringHandle ver); + + [DllImport(NativeLibraryName, EntryPoint = "SteamInternal_FindOrCreateUserInterface", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamInternal_FindOrCreateUserInterface(HSteamUser hSteamUser, InteropHelp.UTF8StringHandle pszVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamInternal_FindOrCreateGameServerInterface", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamInternal_FindOrCreateGameServerInterface(HSteamUser hSteamUser, InteropHelp.UTF8StringHandle pszVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_UseBreakpadCrashHandler", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_UseBreakpadCrashHandler(InteropHelp.UTF8StringHandle pchVersion, InteropHelp.UTF8StringHandle pchDate, InteropHelp.UTF8StringHandle pchTime, [MarshalAs(UnmanagedType.I1)] bool bFullMemoryDumps, IntPtr pvContext, IntPtr m_pfnPreMinidumpCallback); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SetBreakpadAppID", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SetBreakpadAppID(uint unAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ManualDispatch_Init", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_ManualDispatch_Init(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ManualDispatch_RunFrame", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_ManualDispatch_RunFrame(HSteamPipe hSteamPipe); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ManualDispatch_GetNextCallback", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_ManualDispatch_GetNextCallback(HSteamPipe hSteamPipe, IntPtr pCallbackMsg); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ManualDispatch_FreeLastCallback", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_ManualDispatch_FreeLastCallback(HSteamPipe hSteamPipe); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ManualDispatch_GetAPICallResult", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_ManualDispatch_GetAPICallResult(HSteamPipe hSteamPipe, SteamAPICall_t hSteamAPICall, IntPtr pCallback, int cubCallback, int iCallbackExpected, out bool pbFailed); +#endregion +#region steam_gameserver.h + [DllImport(NativeLibraryName, EntryPoint = "SteamGameServer_Shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamGameServer_Shutdown(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamGameServer_RunCallbacks", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamGameServer_RunCallbacks(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamGameServer_ReleaseCurrentThreadMemory", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamGameServer_ReleaseCurrentThreadMemory(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamGameServer_BSecure", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamGameServer_BSecure(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamGameServer_GetSteamID", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong SteamGameServer_GetSteamID(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamGameServer_GetHSteamPipe", CallingConvention = CallingConvention.Cdecl)] + public static extern int SteamGameServer_GetHSteamPipe(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamGameServer_GetHSteamUser", CallingConvention = CallingConvention.Cdecl)] + public static extern int SteamGameServer_GetHSteamUser(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamInternal_GameServer_Init", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamInternal_GameServer_Init(uint unIP, ushort usPort, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, InteropHelp.UTF8StringHandle pchVersionString); +#endregion +#region SteamAPI Accessors + [DllImport(NativeLibraryName, EntryPoint = "SteamClient", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamClient(); + + [DllImport(NativeLibraryName, EntryPoint = "SteamGameServerClient", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamGameServerClient(); +#endregion +#region SteamNetworkingIPAddr Accessors + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_Clear", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIPAddr_Clear(ref SteamNetworkingIPAddr self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_IsIPv6AllZeros", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIPAddr_IsIPv6AllZeros(ref SteamNetworkingIPAddr self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_SetIPv6", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIPAddr_SetIPv6(ref SteamNetworkingIPAddr self, [In, Out] byte[] ipv6, ushort nPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_SetIPv4", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIPAddr_SetIPv4(ref SteamNetworkingIPAddr self, uint nIP, ushort nPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_IsIPv4", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIPAddr_IsIPv4(ref SteamNetworkingIPAddr self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_GetIPv4", CallingConvention = CallingConvention.Cdecl)] + public static extern uint SteamAPI_SteamNetworkingIPAddr_GetIPv4(ref SteamNetworkingIPAddr self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost(ref SteamNetworkingIPAddr self, ushort nPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_IsLocalHost", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIPAddr_IsLocalHost(ref SteamNetworkingIPAddr self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_ToString", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIPAddr_ToString(ref SteamNetworkingIPAddr self, IntPtr buf, uint cbBuf, [MarshalAs(UnmanagedType.I1)] bool bWithPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_ParseString", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIPAddr_ParseString(ref SteamNetworkingIPAddr self, InteropHelp.UTF8StringHandle pszStr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_IsEqualTo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIPAddr_IsEqualTo(ref SteamNetworkingIPAddr self, ref SteamNetworkingIPAddr x); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_GetFakeIPType", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingFakeIPType SteamAPI_SteamNetworkingIPAddr_GetFakeIPType(ref SteamNetworkingIPAddr self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_IsFakeIP", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIPAddr_IsFakeIP(ref SteamNetworkingIPAddr self); +#endregion +#region SteamNetworkingIdentity Accessors + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_Clear", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIdentity_Clear(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_IsInvalid", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIdentity_IsInvalid(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetSteamID", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIdentity_SetSteamID(ref SteamNetworkingIdentity self, ulong steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetSteamID", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong SteamAPI_SteamNetworkingIdentity_GetSteamID(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetSteamID64", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIdentity_SetSteamID64(ref SteamNetworkingIdentity self, ulong steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetSteamID64", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong SteamAPI_SteamNetworkingIdentity_GetSteamID64(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetXboxPairwiseID", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIdentity_SetXboxPairwiseID(ref SteamNetworkingIdentity self, InteropHelp.UTF8StringHandle pszString); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetXboxPairwiseID", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamAPI_SteamNetworkingIdentity_GetXboxPairwiseID(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetPSNID", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIdentity_SetPSNID(ref SteamNetworkingIdentity self, ulong id); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetPSNID", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong SteamAPI_SteamNetworkingIdentity_GetPSNID(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetStadiaID", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIdentity_SetStadiaID(ref SteamNetworkingIdentity self, ulong id); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetStadiaID", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong SteamAPI_SteamNetworkingIdentity_GetStadiaID(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetIPAddr", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamAPI_SteamNetworkingIdentity_SetIPAddr(ref SteamNetworkingIdentity self, ref SteamNetworkingIPAddr addr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetIPAddr", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamAPI_SteamNetworkingIdentity_GetIPAddr(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetIPv4Addr", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIdentity_SetIPv4Addr(ref SteamNetworkingIdentity self, uint nIPv4, ushort nPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetIPv4", CallingConvention = CallingConvention.Cdecl)] + public static extern uint SteamAPI_SteamNetworkingIdentity_GetIPv4(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetFakeIPType", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingFakeIPType SteamAPI_SteamNetworkingIdentity_GetFakeIPType(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_IsFakeIP", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIdentity_IsFakeIP(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetLocalHost", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIdentity_SetLocalHost(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_IsLocalHost", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIdentity_IsLocalHost(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetGenericString", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIdentity_SetGenericString(ref SteamNetworkingIdentity self, InteropHelp.UTF8StringHandle pszString); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetGenericString", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamAPI_SteamNetworkingIdentity_GetGenericString(ref SteamNetworkingIdentity self); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_SetGenericBytes", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIdentity_SetGenericBytes(ref SteamNetworkingIdentity self, [In, Out] byte[] data, uint cbLen); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_GetGenericBytes", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamAPI_SteamNetworkingIdentity_GetGenericBytes(ref SteamNetworkingIdentity self, out int cbLen); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_IsEqualTo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIdentity_IsEqualTo(ref SteamNetworkingIdentity self, ref SteamNetworkingIdentity x); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_ToString", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingIdentity_ToString(ref SteamNetworkingIdentity self, IntPtr buf, uint cbBuf); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingIdentity_ParseString", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_SteamNetworkingIdentity_ParseString(ref SteamNetworkingIdentity self, InteropHelp.UTF8StringHandle pszStr); +#endregion +#region SteamNetworkingMessage_t Accessors + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_SteamNetworkingMessage_t_Release", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_SteamNetworkingMessage_t_Release(IntPtr self); +#endregion +#region ISteamNetworkingConnectionSignaling Accessors + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingConnectionSignaling_SendSignal", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamAPI_ISteamNetworkingConnectionSignaling_SendSignal(ref ISteamNetworkingConnectionSignaling self, HSteamNetConnection hConn, ref SteamNetConnectionInfo_t info, IntPtr pMsg, int cbMsg); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingConnectionSignaling_Release", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_ISteamNetworkingConnectionSignaling_Release(ref ISteamNetworkingConnectionSignaling self); +#endregion +#region ISteamNetworkingSignalingRecvContext Accessors + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSignalingRecvContext_OnConnectRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamAPI_ISteamNetworkingSignalingRecvContext_OnConnectRequest(ref ISteamNetworkingSignalingRecvContext self, HSteamNetConnection hConn, ref SteamNetworkingIdentity identityPeer, int nLocalVirtualPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSignalingRecvContext_SendRejectionSignal", CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamAPI_ISteamNetworkingSignalingRecvContext_SendRejectionSignal(ref ISteamNetworkingSignalingRecvContext self, ref SteamNetworkingIdentity identityPeer, IntPtr pMsg, int cbMsg); +#endregion +#region steamencryptedappticket.h + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamEncryptedAppTicket_BDecryptTicket([In, Out] byte[] rgubTicketEncrypted, uint cubTicketEncrypted, [In, Out] byte[] rgubTicketDecrypted, ref uint pcubTicketDecrypted, [MarshalAs(UnmanagedType.LPArray, SizeConst=Constants.k_nSteamEncryptedAppTicketSymmetricKeyLen)] byte[] rgubKey, int cubKey); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamEncryptedAppTicket_BIsTicketForApp([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, AppId_t nAppID); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SteamEncryptedAppTicket_GetTicketIssueTime([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + public static extern void SteamEncryptedAppTicket_GetTicketSteamID([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, out CSteamID psteamID); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SteamEncryptedAppTicket_GetTicketAppID([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamEncryptedAppTicket_BUserOwnsAppInTicket([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, AppId_t nAppID); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamEncryptedAppTicket_BUserIsVacBanned([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SteamEncryptedAppTicket_GetUserVariableData([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, out uint pcubUserData); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamEncryptedAppTicket_BIsTicketSigned([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted, [In, Out] byte[] pubRSAKey, uint cubRSAKey); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamEncryptedAppTicket_BIsLicenseBorrowed([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted); + + [DllImport(NativeLibrary_SDKEncryptedAppTicket, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool SteamEncryptedAppTicket_BIsLicenseTemporary([In, Out] byte[] rgubTicketDecrypted, uint cubTicketDecrypted); +#endregion +#region SteamAppList + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamAppList_GetNumInstalledApps", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamAppList_GetNumInstalledApps(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamAppList_GetInstalledApps", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamAppList_GetInstalledApps(IntPtr instancePtr, [In, Out] AppId_t[] pvecAppID, uint unMaxAppIDs); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamAppList_GetAppName", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamAppList_GetAppName(IntPtr instancePtr, AppId_t nAppID, IntPtr pchName, int cchNameMax); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamAppList_GetAppInstallDir", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamAppList_GetAppInstallDir(IntPtr instancePtr, AppId_t nAppID, IntPtr pchDirectory, int cchNameMax); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamAppList_GetAppBuildId", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamAppList_GetAppBuildId(IntPtr instancePtr, AppId_t nAppID); +#endregion +#region SteamApps + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsSubscribed", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsSubscribed(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsLowViolence", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsLowViolence(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsCybercafe", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsCybercafe(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsVACBanned", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsVACBanned(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetCurrentGameLanguage", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamApps_GetCurrentGameLanguage(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetAvailableGameLanguages", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamApps_GetAvailableGameLanguages(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsSubscribedApp", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsSubscribedApp(IntPtr instancePtr, AppId_t appID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsDlcInstalled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsDlcInstalled(IntPtr instancePtr, AppId_t appID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetEarliestPurchaseUnixTime", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamApps_GetEarliestPurchaseUnixTime(IntPtr instancePtr, AppId_t nAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsSubscribedFromFreeWeekend", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsSubscribedFromFreeWeekend(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetDLCCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamApps_GetDLCCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BGetDLCDataByIndex", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BGetDLCDataByIndex(IntPtr instancePtr, int iDLC, out AppId_t pAppID, out bool pbAvailable, IntPtr pchName, int cchNameBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_InstallDLC", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamApps_InstallDLC(IntPtr instancePtr, AppId_t nAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_UninstallDLC", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamApps_UninstallDLC(IntPtr instancePtr, AppId_t nAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_RequestAppProofOfPurchaseKey", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamApps_RequestAppProofOfPurchaseKey(IntPtr instancePtr, AppId_t nAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetCurrentBetaName", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_GetCurrentBetaName(IntPtr instancePtr, IntPtr pchName, int cchNameBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_MarkContentCorrupt", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_MarkContentCorrupt(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bMissingFilesOnly); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetInstalledDepots", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamApps_GetInstalledDepots(IntPtr instancePtr, AppId_t appID, [In, Out] DepotId_t[] pvecDepots, uint cMaxDepots); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetAppInstallDir", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamApps_GetAppInstallDir(IntPtr instancePtr, AppId_t appID, IntPtr pchFolder, uint cchFolderBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsAppInstalled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsAppInstalled(IntPtr instancePtr, AppId_t appID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetAppOwner", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamApps_GetAppOwner(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetLaunchQueryParam", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamApps_GetLaunchQueryParam(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetDlcDownloadProgress", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_GetDlcDownloadProgress(IntPtr instancePtr, AppId_t nAppID, out ulong punBytesDownloaded, out ulong punBytesTotal); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetAppBuildId", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamApps_GetAppBuildId(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_RequestAllProofOfPurchaseKeys", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamApps_RequestAllProofOfPurchaseKeys(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetFileDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamApps_GetFileDetails(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszFileName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_GetLaunchCommandLine", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamApps_GetLaunchCommandLine(IntPtr instancePtr, IntPtr pszCommandLine, int cubCommandLine); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsSubscribedFromFamilySharing", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsSubscribedFromFamilySharing(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_BIsTimedTrial", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_BIsTimedTrial(IntPtr instancePtr, out uint punSecondsAllowed, out uint punSecondsPlayed); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamApps_SetDlcContext", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamApps_SetDlcContext(IntPtr instancePtr, AppId_t nAppID); +#endregion +#region SteamClient + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_CreateSteamPipe", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamClient_CreateSteamPipe(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_BReleaseSteamPipe", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamClient_BReleaseSteamPipe(IntPtr instancePtr, HSteamPipe hSteamPipe); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_ConnectToGlobalUser", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamClient_ConnectToGlobalUser(IntPtr instancePtr, HSteamPipe hSteamPipe); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_CreateLocalUser", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamClient_CreateLocalUser(IntPtr instancePtr, out HSteamPipe phSteamPipe, EAccountType eAccountType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_ReleaseUser", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamClient_ReleaseUser(IntPtr instancePtr, HSteamPipe hSteamPipe, HSteamUser hUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamUser", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamUser(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamGameServer", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamGameServer(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_SetLocalIPBinding", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamClient_SetLocalIPBinding(IntPtr instancePtr, ref SteamIPAddress_t unIP, ushort usPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamFriends", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamFriends(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamUtils", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamUtils(IntPtr instancePtr, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamMatchmaking", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamMatchmaking(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamMatchmakingServers", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamMatchmakingServers(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamGenericInterface", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamGenericInterface(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamUserStats", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamUserStats(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamGameServerStats", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamGameServerStats(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamApps", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamApps(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamNetworking", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamNetworking(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamRemoteStorage", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamRemoteStorage(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamScreenshots", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamScreenshots(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamGameSearch", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamGameSearch(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetIPCCallCount", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamClient_GetIPCCallCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_SetWarningMessageHook", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamClient_SetWarningMessageHook(IntPtr instancePtr, SteamAPIWarningMessageHook_t pFunction); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_BShutdownIfAllPipesClosed", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamClient_BShutdownIfAllPipesClosed(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamHTTP", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamHTTP(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamController", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamController(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamUGC", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamUGC(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamAppList", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamAppList(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamMusic", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamMusic(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamMusicRemote", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamMusicRemote(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamHTMLSurface", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamHTMLSurface(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamInventory", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamInventory(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamVideo", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamVideo(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamParentalSettings", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamParentalSettings(IntPtr instancePtr, HSteamUser hSteamuser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamInput", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamInput(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamParties", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamParties(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamClient_GetISteamRemotePlay", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamClient_GetISteamRemotePlay(IntPtr instancePtr, HSteamUser hSteamUser, HSteamPipe hSteamPipe, InteropHelp.UTF8StringHandle pchVersion); +#endregion +#region SteamFriends + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetPersonaName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetPersonaName(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_SetPersonaName", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_SetPersonaName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchPersonaName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetPersonaState", CallingConvention = CallingConvention.Cdecl)] + public static extern EPersonaState ISteamFriends_GetPersonaState(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetFriendCount(IntPtr instancePtr, EFriendFlags iFriendFlags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_GetFriendByIndex(IntPtr instancePtr, int iFriend, EFriendFlags iFriendFlags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendRelationship", CallingConvention = CallingConvention.Cdecl)] + public static extern EFriendRelationship ISteamFriends_GetFriendRelationship(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendPersonaState", CallingConvention = CallingConvention.Cdecl)] + public static extern EPersonaState ISteamFriends_GetFriendPersonaState(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendPersonaName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetFriendPersonaName(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendGamePlayed", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_GetFriendGamePlayed(IntPtr instancePtr, CSteamID steamIDFriend, out FriendGameInfo_t pFriendGameInfo); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendPersonaNameHistory", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetFriendPersonaNameHistory(IntPtr instancePtr, CSteamID steamIDFriend, int iPersonaName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendSteamLevel", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetFriendSteamLevel(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetPlayerNickname", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetPlayerNickname(IntPtr instancePtr, CSteamID steamIDPlayer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendsGroupCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetFriendsGroupCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendsGroupIDByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern short ISteamFriends_GetFriendsGroupIDByIndex(IntPtr instancePtr, int iFG); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendsGroupName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetFriendsGroupName(IntPtr instancePtr, FriendsGroupID_t friendsGroupID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendsGroupMembersCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetFriendsGroupMembersCount(IntPtr instancePtr, FriendsGroupID_t friendsGroupID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendsGroupMembersList", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_GetFriendsGroupMembersList(IntPtr instancePtr, FriendsGroupID_t friendsGroupID, [In, Out] CSteamID[] pOutSteamIDMembers, int nMembersCount); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_HasFriend", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_HasFriend(IntPtr instancePtr, CSteamID steamIDFriend, EFriendFlags iFriendFlags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetClanCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_GetClanByIndex(IntPtr instancePtr, int iClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetClanName(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanTag", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetClanTag(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanActivityCounts", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_GetClanActivityCounts(IntPtr instancePtr, CSteamID steamIDClan, out int pnOnline, out int pnInGame, out int pnChatting); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_DownloadClanActivityCounts", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_DownloadClanActivityCounts(IntPtr instancePtr, [In, Out] CSteamID[] psteamIDClans, int cClansToRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendCountFromSource", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetFriendCountFromSource(IntPtr instancePtr, CSteamID steamIDSource); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendFromSourceByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_GetFriendFromSourceByIndex(IntPtr instancePtr, CSteamID steamIDSource, int iFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_IsUserInSource", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_IsUserInSource(IntPtr instancePtr, CSteamID steamIDUser, CSteamID steamIDSource); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_SetInGameVoiceSpeaking", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_SetInGameVoiceSpeaking(IntPtr instancePtr, CSteamID steamIDUser, [MarshalAs(UnmanagedType.I1)] bool bSpeaking); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ActivateGameOverlay", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_ActivateGameOverlay(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchDialog); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ActivateGameOverlayToUser", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_ActivateGameOverlayToUser(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchDialog, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ActivateGameOverlayToWebPage", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_ActivateGameOverlayToWebPage(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchURL, EActivateGameOverlayToWebPageMode eMode); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ActivateGameOverlayToStore", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_ActivateGameOverlayToStore(IntPtr instancePtr, AppId_t nAppID, EOverlayToStoreFlag eFlag); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_SetPlayedWith", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_SetPlayedWith(IntPtr instancePtr, CSteamID steamIDUserPlayedWith); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ActivateGameOverlayInviteDialog", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_ActivateGameOverlayInviteDialog(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetSmallFriendAvatar", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetSmallFriendAvatar(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetMediumFriendAvatar", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetMediumFriendAvatar(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetLargeFriendAvatar", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetLargeFriendAvatar(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_RequestUserInformation", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_RequestUserInformation(IntPtr instancePtr, CSteamID steamIDUser, [MarshalAs(UnmanagedType.I1)] bool bRequireNameOnly); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_RequestClanOfficerList", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_RequestClanOfficerList(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanOwner", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_GetClanOwner(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanOfficerCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetClanOfficerCount(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanOfficerByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_GetClanOfficerByIndex(IntPtr instancePtr, CSteamID steamIDClan, int iOfficer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetUserRestrictions", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamFriends_GetUserRestrictions(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_SetRichPresence", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_SetRichPresence(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ClearRichPresence", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_ClearRichPresence(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendRichPresence", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetFriendRichPresence(IntPtr instancePtr, CSteamID steamIDFriend, InteropHelp.UTF8StringHandle pchKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendRichPresenceKeyCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetFriendRichPresenceKeyCount(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendRichPresenceKeyByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetFriendRichPresenceKeyByIndex(IntPtr instancePtr, CSteamID steamIDFriend, int iKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_RequestFriendRichPresence", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_RequestFriendRichPresence(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_InviteUserToGame", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_InviteUserToGame(IntPtr instancePtr, CSteamID steamIDFriend, InteropHelp.UTF8StringHandle pchConnectString); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetCoplayFriendCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetCoplayFriendCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetCoplayFriend", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_GetCoplayFriend(IntPtr instancePtr, int iCoplayFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendCoplayTime", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetFriendCoplayTime(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendCoplayGame", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamFriends_GetFriendCoplayGame(IntPtr instancePtr, CSteamID steamIDFriend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_JoinClanChatRoom", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_JoinClanChatRoom(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_LeaveClanChatRoom", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_LeaveClanChatRoom(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanChatMemberCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetClanChatMemberCount(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetChatMemberByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_GetChatMemberByIndex(IntPtr instancePtr, CSteamID steamIDClan, int iUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_SendClanChatMessage", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_SendClanChatMessage(IntPtr instancePtr, CSteamID steamIDClanChat, InteropHelp.UTF8StringHandle pchText); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetClanChatMessage", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetClanChatMessage(IntPtr instancePtr, CSteamID steamIDClanChat, int iMessage, IntPtr prgchText, int cchTextMax, out EChatEntryType peChatEntryType, out CSteamID psteamidChatter); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_IsClanChatAdmin", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_IsClanChatAdmin(IntPtr instancePtr, CSteamID steamIDClanChat, CSteamID steamIDUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_IsClanChatWindowOpenInSteam", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_IsClanChatWindowOpenInSteam(IntPtr instancePtr, CSteamID steamIDClanChat); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_OpenClanChatWindowInSteam", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_OpenClanChatWindowInSteam(IntPtr instancePtr, CSteamID steamIDClanChat); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_CloseClanChatWindowInSteam", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_CloseClanChatWindowInSteam(IntPtr instancePtr, CSteamID steamIDClanChat); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_SetListenForFriendsMessages", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_SetListenForFriendsMessages(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bInterceptEnabled); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ReplyToFriendMessage", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_ReplyToFriendMessage(IntPtr instancePtr, CSteamID steamIDFriend, InteropHelp.UTF8StringHandle pchMsgToSend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFriendMessage", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetFriendMessage(IntPtr instancePtr, CSteamID steamIDFriend, int iMessageID, IntPtr pvData, int cubData, out EChatEntryType peChatEntryType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetFollowerCount", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_GetFollowerCount(IntPtr instancePtr, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_IsFollowing", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_IsFollowing(IntPtr instancePtr, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_EnumerateFollowingList", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_EnumerateFollowingList(IntPtr instancePtr, uint unStartIndex); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_IsClanPublic", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_IsClanPublic(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_IsClanOfficialGameGroup", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_IsClanOfficialGameGroup(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetNumChatsWithUnreadPriorityMessages", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamFriends_GetNumChatsWithUnreadPriorityMessages(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ActivateGameOverlayRemotePlayTogetherInviteDialog", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_ActivateGameOverlayRemotePlayTogetherInviteDialog(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_RegisterProtocolInOverlayBrowser", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_RegisterProtocolInOverlayBrowser(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchProtocol); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_ActivateGameOverlayInviteDialogConnectString", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamFriends_ActivateGameOverlayInviteDialogConnectString(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchConnectString); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_RequestEquippedProfileItems", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamFriends_RequestEquippedProfileItems(IntPtr instancePtr, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_BHasEquippedProfileItem", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamFriends_BHasEquippedProfileItem(IntPtr instancePtr, CSteamID steamID, ECommunityProfileItemType itemType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetProfileItemPropertyString", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamFriends_GetProfileItemPropertyString(IntPtr instancePtr, CSteamID steamID, ECommunityProfileItemType itemType, ECommunityProfileItemProperty prop); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamFriends_GetProfileItemPropertyUint", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamFriends_GetProfileItemPropertyUint(IntPtr instancePtr, CSteamID steamID, ECommunityProfileItemType itemType, ECommunityProfileItemProperty prop); +#endregion +#region SteamGameServer + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetProduct", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetProduct(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszProduct); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetGameDescription", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetGameDescription(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszGameDescription); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetModDir", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetModDir(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszModDir); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetDedicatedServer", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetDedicatedServer(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bDedicated); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_LogOn", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_LogOn(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszToken); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_LogOnAnonymous", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_LogOnAnonymous(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_LogOff", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_LogOff(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_BLoggedOn", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServer_BLoggedOn(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_BSecure", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServer_BSecure(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_GetSteamID", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamGameServer_GetSteamID(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_WasRestartRequested", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServer_WasRestartRequested(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetMaxPlayerCount", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetMaxPlayerCount(IntPtr instancePtr, int cPlayersMax); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetBotPlayerCount", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetBotPlayerCount(IntPtr instancePtr, int cBotplayers); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetServerName", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetServerName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszServerName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetMapName", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetMapName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszMapName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetPasswordProtected", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetPasswordProtected(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bPasswordProtected); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetSpectatorPort", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetSpectatorPort(IntPtr instancePtr, ushort unSpectatorPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetSpectatorServerName", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetSpectatorServerName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszSpectatorServerName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_ClearAllKeyValues", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_ClearAllKeyValues(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetKeyValue", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetKeyValue(IntPtr instancePtr, InteropHelp.UTF8StringHandle pKey, InteropHelp.UTF8StringHandle pValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetGameTags", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetGameTags(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchGameTags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetGameData", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetGameData(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchGameData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetRegion", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetRegion(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszRegion); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SetAdvertiseServerActive", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SetAdvertiseServerActive(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bActive); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_GetAuthSessionTicket", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamGameServer_GetAuthSessionTicket(IntPtr instancePtr, byte[] pTicket, int cbMaxTicket, out uint pcbTicket, ref SteamNetworkingIdentity pSnid); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_BeginAuthSession", CallingConvention = CallingConvention.Cdecl)] + public static extern EBeginAuthSessionResult ISteamGameServer_BeginAuthSession(IntPtr instancePtr, byte[] pAuthTicket, int cbAuthTicket, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_EndAuthSession", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_EndAuthSession(IntPtr instancePtr, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_CancelAuthTicket", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_CancelAuthTicket(IntPtr instancePtr, HAuthTicket hAuthTicket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_UserHasLicenseForApp", CallingConvention = CallingConvention.Cdecl)] + public static extern EUserHasLicenseForAppResult ISteamGameServer_UserHasLicenseForApp(IntPtr instancePtr, CSteamID steamID, AppId_t appID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_RequestUserGroupStatus", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServer_RequestUserGroupStatus(IntPtr instancePtr, CSteamID steamIDUser, CSteamID steamIDGroup); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_GetGameplayStats", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_GetGameplayStats(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_GetServerReputation", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamGameServer_GetServerReputation(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_GetPublicIP", CallingConvention = CallingConvention.Cdecl)] + public static extern SteamIPAddress_t ISteamGameServer_GetPublicIP(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_HandleIncomingPacket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServer_HandleIncomingPacket(IntPtr instancePtr, byte[] pData, int cbData, uint srcIP, ushort srcPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_GetNextOutgoingPacket", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamGameServer_GetNextOutgoingPacket(IntPtr instancePtr, byte[] pOut, int cbMaxOut, out uint pNetAdr, out ushort pPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_AssociateWithClan", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamGameServer_AssociateWithClan(IntPtr instancePtr, CSteamID steamIDClan); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_ComputeNewPlayerCompatibility", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamGameServer_ComputeNewPlayerCompatibility(IntPtr instancePtr, CSteamID steamIDNewPlayer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SendUserConnectAndAuthenticate_DEPRECATED", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServer_SendUserConnectAndAuthenticate_DEPRECATED(IntPtr instancePtr, uint unIPClient, byte[] pvAuthBlob, uint cubAuthBlobSize, out CSteamID pSteamIDUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_CreateUnauthenticatedUserConnection", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamGameServer_CreateUnauthenticatedUserConnection(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_SendUserDisconnect_DEPRECATED", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamGameServer_SendUserDisconnect_DEPRECATED(IntPtr instancePtr, CSteamID steamIDUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServer_BUpdateUserData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServer_BUpdateUserData(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchPlayerName, uint uScore); +#endregion +#region SteamGameServerStats + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_RequestUserStats", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamGameServerStats_RequestUserStats(IntPtr instancePtr, CSteamID steamIDUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_GetUserStatInt32", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServerStats_GetUserStatInt32(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out int pData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_GetUserStatFloat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServerStats_GetUserStatFloat(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out float pData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_GetUserAchievement", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServerStats_GetUserAchievement(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_SetUserStatInt32", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServerStats_SetUserStatInt32(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, int nData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_SetUserStatFloat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServerStats_SetUserStatFloat(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, float fData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_UpdateUserAvgRateStat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServerStats_UpdateUserAvgRateStat(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, float flCountThisSession, double dSessionLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_SetUserAchievement", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServerStats_SetUserAchievement(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_ClearUserAchievement", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamGameServerStats_ClearUserAchievement(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameServerStats_StoreUserStats", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamGameServerStats_StoreUserStats(IntPtr instancePtr, CSteamID steamIDUser); +#endregion +#region SteamHTMLSurface + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_Init", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTMLSurface_Init(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_Shutdown", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTMLSurface_Shutdown(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_CreateBrowser", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamHTMLSurface_CreateBrowser(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchUserAgent, InteropHelp.UTF8StringHandle pchUserCSS); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_RemoveBrowser", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_RemoveBrowser(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_LoadURL", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_LoadURL(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, InteropHelp.UTF8StringHandle pchURL, InteropHelp.UTF8StringHandle pchPostData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_SetSize", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_SetSize(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint unWidth, uint unHeight); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_StopLoad", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_StopLoad(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_Reload", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_Reload(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_GoBack", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_GoBack(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_GoForward", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_GoForward(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_AddHeader", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_AddHeader(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_ExecuteJavascript", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_ExecuteJavascript(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, InteropHelp.UTF8StringHandle pchScript); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_MouseUp", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_MouseUp(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_MouseDown", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_MouseDown(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_MouseDoubleClick", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_MouseDoubleClick(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_MouseMove", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_MouseMove(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, int x, int y); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_MouseWheel", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_MouseWheel(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, int nDelta); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_KeyDown", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_KeyDown(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers, [MarshalAs(UnmanagedType.I1)] bool bIsSystemKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_KeyUp", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_KeyUp(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_KeyChar", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_KeyChar(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint cUnicodeChar, EHTMLKeyModifiers eHTMLKeyModifiers); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_SetHorizontalScroll", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_SetHorizontalScroll(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint nAbsolutePixelScroll); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_SetVerticalScroll", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_SetVerticalScroll(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, uint nAbsolutePixelScroll); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_SetKeyFocus", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_SetKeyFocus(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, [MarshalAs(UnmanagedType.I1)] bool bHasKeyFocus); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_ViewSource", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_ViewSource(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_CopyToClipboard", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_CopyToClipboard(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_PasteFromClipboard", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_PasteFromClipboard(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_Find", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_Find(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, InteropHelp.UTF8StringHandle pchSearchStr, [MarshalAs(UnmanagedType.I1)] bool bCurrentlyInFind, [MarshalAs(UnmanagedType.I1)] bool bReverse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_StopFind", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_StopFind(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_GetLinkAtPosition", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_GetLinkAtPosition(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, int x, int y); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_SetCookie", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_SetCookie(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchHostname, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue, InteropHelp.UTF8StringHandle pchPath, uint nExpires, [MarshalAs(UnmanagedType.I1)] bool bSecure, [MarshalAs(UnmanagedType.I1)] bool bHTTPOnly); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_SetPageScaleFactor", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_SetPageScaleFactor(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, float flZoom, int nPointX, int nPointY); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_SetBackgroundMode", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_SetBackgroundMode(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, [MarshalAs(UnmanagedType.I1)] bool bBackgroundMode); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_SetDPIScalingFactor", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_SetDPIScalingFactor(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, float flDPIScaling); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_OpenDeveloperTools", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_OpenDeveloperTools(IntPtr instancePtr, HHTMLBrowser unBrowserHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_AllowStartRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_AllowStartRequest(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, [MarshalAs(UnmanagedType.I1)] bool bAllowed); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_JSDialogResponse", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_JSDialogResponse(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, [MarshalAs(UnmanagedType.I1)] bool bResult); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTMLSurface_FileLoadDialogResponse", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamHTMLSurface_FileLoadDialogResponse(IntPtr instancePtr, HHTMLBrowser unBrowserHandle, IntPtr pchSelectedFiles); +#endregion +#region SteamHTTP + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_CreateHTTPRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamHTTP_CreateHTTPRequest(IntPtr instancePtr, EHTTPMethod eHTTPRequestMethod, InteropHelp.UTF8StringHandle pchAbsoluteURL); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestContextValue", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestContextValue(IntPtr instancePtr, HTTPRequestHandle hRequest, ulong ulContextValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestNetworkActivityTimeout", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestNetworkActivityTimeout(IntPtr instancePtr, HTTPRequestHandle hRequest, uint unTimeoutSeconds); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestHeaderValue", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestHeaderValue(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchHeaderName, InteropHelp.UTF8StringHandle pchHeaderValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestGetOrPostParameter", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestGetOrPostParameter(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchParamName, InteropHelp.UTF8StringHandle pchParamValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SendHTTPRequest", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SendHTTPRequest(IntPtr instancePtr, HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SendHTTPRequestAndStreamResponse", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SendHTTPRequestAndStreamResponse(IntPtr instancePtr, HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_DeferHTTPRequest", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_DeferHTTPRequest(IntPtr instancePtr, HTTPRequestHandle hRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_PrioritizeHTTPRequest", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_PrioritizeHTTPRequest(IntPtr instancePtr, HTTPRequestHandle hRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_GetHTTPResponseHeaderSize", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_GetHTTPResponseHeaderSize(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchHeaderName, out uint unResponseHeaderSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_GetHTTPResponseHeaderValue", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_GetHTTPResponseHeaderValue(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchHeaderName, byte[] pHeaderValueBuffer, uint unBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_GetHTTPResponseBodySize", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_GetHTTPResponseBodySize(IntPtr instancePtr, HTTPRequestHandle hRequest, out uint unBodySize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_GetHTTPResponseBodyData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_GetHTTPResponseBodyData(IntPtr instancePtr, HTTPRequestHandle hRequest, byte[] pBodyDataBuffer, uint unBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_GetHTTPStreamingResponseBodyData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_GetHTTPStreamingResponseBodyData(IntPtr instancePtr, HTTPRequestHandle hRequest, uint cOffset, byte[] pBodyDataBuffer, uint unBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_ReleaseHTTPRequest", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_ReleaseHTTPRequest(IntPtr instancePtr, HTTPRequestHandle hRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_GetHTTPDownloadProgressPct", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_GetHTTPDownloadProgressPct(IntPtr instancePtr, HTTPRequestHandle hRequest, out float pflPercentOut); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestRawPostBody", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestRawPostBody(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchContentType, byte[] pubBody, uint unBodyLen); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_CreateCookieContainer", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamHTTP_CreateCookieContainer(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bAllowResponsesToModify); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_ReleaseCookieContainer", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_ReleaseCookieContainer(IntPtr instancePtr, HTTPCookieContainerHandle hCookieContainer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetCookie", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetCookie(IntPtr instancePtr, HTTPCookieContainerHandle hCookieContainer, InteropHelp.UTF8StringHandle pchHost, InteropHelp.UTF8StringHandle pchUrl, InteropHelp.UTF8StringHandle pchCookie); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestCookieContainer", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestCookieContainer(IntPtr instancePtr, HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestUserAgentInfo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestUserAgentInfo(IntPtr instancePtr, HTTPRequestHandle hRequest, InteropHelp.UTF8StringHandle pchUserAgentInfo); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestRequiresVerifiedCertificate", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestRequiresVerifiedCertificate(IntPtr instancePtr, HTTPRequestHandle hRequest, [MarshalAs(UnmanagedType.I1)] bool bRequireVerifiedCertificate); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_SetHTTPRequestAbsoluteTimeoutMS", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_SetHTTPRequestAbsoluteTimeoutMS(IntPtr instancePtr, HTTPRequestHandle hRequest, uint unMilliseconds); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamHTTP_GetHTTPRequestWasTimedOut", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamHTTP_GetHTTPRequestWasTimedOut(IntPtr instancePtr, HTTPRequestHandle hRequest, out bool pbWasTimedOut); +#endregion +#region SteamInput + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_Init", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInput_Init(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bExplicitlyCallRunFrame); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_Shutdown", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInput_Shutdown(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_SetInputActionManifestFilePath", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInput_SetInputActionManifestFilePath(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchInputActionManifestAbsolutePath); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_RunFrame", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_RunFrame(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bReservedValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_BWaitForData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInput_BWaitForData(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bWaitForever, uint unTimeout); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_BNewDataAvailable", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInput_BNewDataAvailable(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetConnectedControllers", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamInput_GetConnectedControllers(IntPtr instancePtr, [In, Out] InputHandle_t[] handlesOut); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_EnableDeviceCallbacks", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_EnableDeviceCallbacks(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_EnableActionEventCallbacks", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_EnableActionEventCallbacks(IntPtr instancePtr, SteamInputActionEventCallbackPointer pCallback); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetActionSetHandle", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInput_GetActionSetHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionSetName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_ActivateActionSet", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_ActivateActionSet(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetCurrentActionSet", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInput_GetCurrentActionSet(IntPtr instancePtr, InputHandle_t inputHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_ActivateActionSetLayer", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_ActivateActionSetLayer(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetLayerHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_DeactivateActionSetLayer", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_DeactivateActionSetLayer(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetLayerHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_DeactivateAllActionSetLayers", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_DeactivateAllActionSetLayers(IntPtr instancePtr, InputHandle_t inputHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetActiveActionSetLayers", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamInput_GetActiveActionSetLayers(IntPtr instancePtr, InputHandle_t inputHandle, [In, Out] InputActionSetHandle_t[] handlesOut); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetDigitalActionHandle", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInput_GetDigitalActionHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetDigitalActionData", CallingConvention = CallingConvention.Cdecl)] + public static extern InputDigitalActionData_t ISteamInput_GetDigitalActionData(IntPtr instancePtr, InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetDigitalActionOrigins", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamInput_GetDigitalActionOrigins(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputDigitalActionHandle_t digitalActionHandle, [In, Out] EInputActionOrigin[] originsOut); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetStringForDigitalActionName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamInput_GetStringForDigitalActionName(IntPtr instancePtr, InputDigitalActionHandle_t eActionHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetAnalogActionHandle", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInput_GetAnalogActionHandle(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszActionName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetAnalogActionData", CallingConvention = CallingConvention.Cdecl)] + public static extern InputAnalogActionData_t ISteamInput_GetAnalogActionData(IntPtr instancePtr, InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetAnalogActionOrigins", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamInput_GetAnalogActionOrigins(IntPtr instancePtr, InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputAnalogActionHandle_t analogActionHandle, [In, Out] EInputActionOrigin[] originsOut); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetGlyphPNGForActionOrigin", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamInput_GetGlyphPNGForActionOrigin(IntPtr instancePtr, EInputActionOrigin eOrigin, ESteamInputGlyphSize eSize, uint unFlags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetGlyphSVGForActionOrigin", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamInput_GetGlyphSVGForActionOrigin(IntPtr instancePtr, EInputActionOrigin eOrigin, uint unFlags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetGlyphForActionOrigin_Legacy", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamInput_GetGlyphForActionOrigin_Legacy(IntPtr instancePtr, EInputActionOrigin eOrigin); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetStringForActionOrigin", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamInput_GetStringForActionOrigin(IntPtr instancePtr, EInputActionOrigin eOrigin); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetStringForAnalogActionName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamInput_GetStringForAnalogActionName(IntPtr instancePtr, InputAnalogActionHandle_t eActionHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_StopAnalogActionMomentum", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_StopAnalogActionMomentum(IntPtr instancePtr, InputHandle_t inputHandle, InputAnalogActionHandle_t eAction); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetMotionData", CallingConvention = CallingConvention.Cdecl)] + public static extern InputMotionData_t ISteamInput_GetMotionData(IntPtr instancePtr, InputHandle_t inputHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_TriggerVibration", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_TriggerVibration(IntPtr instancePtr, InputHandle_t inputHandle, ushort usLeftSpeed, ushort usRightSpeed); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_TriggerVibrationExtended", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_TriggerVibrationExtended(IntPtr instancePtr, InputHandle_t inputHandle, ushort usLeftSpeed, ushort usRightSpeed, ushort usLeftTriggerSpeed, ushort usRightTriggerSpeed); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_TriggerSimpleHapticEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_TriggerSimpleHapticEvent(IntPtr instancePtr, InputHandle_t inputHandle, EControllerHapticLocation eHapticLocation, byte nIntensity, char nGainDB, byte nOtherIntensity, char nOtherGainDB); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_SetLEDColor", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_SetLEDColor(IntPtr instancePtr, InputHandle_t inputHandle, byte nColorR, byte nColorG, byte nColorB, uint nFlags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_Legacy_TriggerHapticPulse", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_Legacy_TriggerHapticPulse(IntPtr instancePtr, InputHandle_t inputHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_Legacy_TriggerRepeatedHapticPulse", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_Legacy_TriggerRepeatedHapticPulse(IntPtr instancePtr, InputHandle_t inputHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec, ushort usOffMicroSec, ushort unRepeat, uint nFlags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_ShowBindingPanel", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInput_ShowBindingPanel(IntPtr instancePtr, InputHandle_t inputHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetInputTypeForHandle", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamInputType ISteamInput_GetInputTypeForHandle(IntPtr instancePtr, InputHandle_t inputHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetControllerForGamepadIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInput_GetControllerForGamepadIndex(IntPtr instancePtr, int nIndex); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetGamepadIndexForController", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamInput_GetGamepadIndexForController(IntPtr instancePtr, InputHandle_t ulinputHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetStringForXboxOrigin", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamInput_GetStringForXboxOrigin(IntPtr instancePtr, EXboxOrigin eOrigin); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetGlyphForXboxOrigin", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamInput_GetGlyphForXboxOrigin(IntPtr instancePtr, EXboxOrigin eOrigin); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetActionOriginFromXboxOrigin", CallingConvention = CallingConvention.Cdecl)] + public static extern EInputActionOrigin ISteamInput_GetActionOriginFromXboxOrigin(IntPtr instancePtr, InputHandle_t inputHandle, EXboxOrigin eOrigin); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_TranslateActionOrigin", CallingConvention = CallingConvention.Cdecl)] + public static extern EInputActionOrigin ISteamInput_TranslateActionOrigin(IntPtr instancePtr, ESteamInputType eDestinationInputType, EInputActionOrigin eSourceOrigin); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetDeviceBindingRevision", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInput_GetDeviceBindingRevision(IntPtr instancePtr, InputHandle_t inputHandle, out int pMajor, out int pMinor); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetRemotePlaySessionID", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamInput_GetRemotePlaySessionID(IntPtr instancePtr, InputHandle_t inputHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_GetSessionInputConfigurationSettings", CallingConvention = CallingConvention.Cdecl)] + public static extern ushort ISteamInput_GetSessionInputConfigurationSettings(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInput_SetDualSenseTriggerEffect", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInput_SetDualSenseTriggerEffect(IntPtr instancePtr, InputHandle_t inputHandle, IntPtr pParam); +#endregion +#region SteamInventory + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetResultStatus", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamInventory_GetResultStatus(IntPtr instancePtr, SteamInventoryResult_t resultHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetResultItems", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetResultItems(IntPtr instancePtr, SteamInventoryResult_t resultHandle, [In, Out] SteamItemDetails_t[] pOutItemsArray, ref uint punOutItemsArraySize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetResultItemProperty", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetResultItemProperty(IntPtr instancePtr, SteamInventoryResult_t resultHandle, uint unItemIndex, InteropHelp.UTF8StringHandle pchPropertyName, IntPtr pchValueBuffer, ref uint punValueBufferSizeOut); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetResultTimestamp", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamInventory_GetResultTimestamp(IntPtr instancePtr, SteamInventoryResult_t resultHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_CheckResultSteamID", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_CheckResultSteamID(IntPtr instancePtr, SteamInventoryResult_t resultHandle, CSteamID steamIDExpected); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_DestroyResult", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInventory_DestroyResult(IntPtr instancePtr, SteamInventoryResult_t resultHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetAllItems", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetAllItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetItemsByID", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetItemsByID(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, [In, Out] SteamItemInstanceID_t[] pInstanceIDs, uint unCountInstanceIDs); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_SerializeResult", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_SerializeResult(IntPtr instancePtr, SteamInventoryResult_t resultHandle, byte[] pOutBuffer, out uint punOutBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_DeserializeResult", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_DeserializeResult(IntPtr instancePtr, out SteamInventoryResult_t pOutResultHandle, byte[] pBuffer, uint unBufferSize, [MarshalAs(UnmanagedType.I1)] bool bRESERVED_MUST_BE_FALSE); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GenerateItems", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GenerateItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, [In, Out] SteamItemDef_t[] pArrayItemDefs, [In, Out] uint[] punArrayQuantity, uint unArrayLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GrantPromoItems", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GrantPromoItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_AddPromoItem", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_AddPromoItem(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, SteamItemDef_t itemDef); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_AddPromoItems", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_AddPromoItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, [In, Out] SteamItemDef_t[] pArrayItemDefs, uint unArrayLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_ConsumeItem", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_ConsumeItem(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemConsume, uint unQuantity); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_ExchangeItems", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_ExchangeItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, [In, Out] SteamItemDef_t[] pArrayGenerate, [In, Out] uint[] punArrayGenerateQuantity, uint unArrayGenerateLength, [In, Out] SteamItemInstanceID_t[] pArrayDestroy, [In, Out] uint[] punArrayDestroyQuantity, uint unArrayDestroyLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_TransferItemQuantity", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_TransferItemQuantity(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemIdSource, uint unQuantity, SteamItemInstanceID_t itemIdDest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_SendItemDropHeartbeat", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamInventory_SendItemDropHeartbeat(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_TriggerItemDrop", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_TriggerItemDrop(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, SteamItemDef_t dropListDefinition); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_TradeItems", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_TradeItems(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, CSteamID steamIDTradePartner, [In, Out] SteamItemInstanceID_t[] pArrayGive, [In, Out] uint[] pArrayGiveQuantity, uint nArrayGiveLength, [In, Out] SteamItemInstanceID_t[] pArrayGet, [In, Out] uint[] pArrayGetQuantity, uint nArrayGetLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_LoadItemDefinitions", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_LoadItemDefinitions(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetItemDefinitionIDs", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetItemDefinitionIDs(IntPtr instancePtr, [In, Out] SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetItemDefinitionProperty", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetItemDefinitionProperty(IntPtr instancePtr, SteamItemDef_t iDefinition, InteropHelp.UTF8StringHandle pchPropertyName, IntPtr pchValueBuffer, ref uint punValueBufferSizeOut); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_RequestEligiblePromoItemDefinitionsIDs", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInventory_RequestEligiblePromoItemDefinitionsIDs(IntPtr instancePtr, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetEligiblePromoItemDefinitionIDs", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetEligiblePromoItemDefinitionIDs(IntPtr instancePtr, CSteamID steamID, [In, Out] SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_StartPurchase", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInventory_StartPurchase(IntPtr instancePtr, [In, Out] SteamItemDef_t[] pArrayItemDefs, [In, Out] uint[] punArrayQuantity, uint unArrayLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_RequestPrices", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInventory_RequestPrices(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetNumItemsWithPrices", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamInventory_GetNumItemsWithPrices(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetItemsWithPrices", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetItemsWithPrices(IntPtr instancePtr, [In, Out] SteamItemDef_t[] pArrayItemDefs, [In, Out] ulong[] pCurrentPrices, [In, Out] ulong[] pBasePrices, uint unArrayLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_GetItemPrice", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_GetItemPrice(IntPtr instancePtr, SteamItemDef_t iDefinition, out ulong pCurrentPrice, out ulong pBasePrice); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_StartUpdateProperties", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamInventory_StartUpdateProperties(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_RemoveProperty", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_RemoveProperty(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_SetPropertyString", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_SetPropertyString(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName, InteropHelp.UTF8StringHandle pchPropertyValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_SetPropertyBool", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_SetPropertyBool(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_SetPropertyInt64", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_SetPropertyInt64(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName, long nValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_SetPropertyFloat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_SetPropertyFloat(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, InteropHelp.UTF8StringHandle pchPropertyName, float flValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_SubmitUpdateProperties", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_SubmitUpdateProperties(IntPtr instancePtr, SteamInventoryUpdateHandle_t handle, out SteamInventoryResult_t pResultHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamInventory_InspectItem", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamInventory_InspectItem(IntPtr instancePtr, out SteamInventoryResult_t pResultHandle, InteropHelp.UTF8StringHandle pchItemToken); +#endregion +#region SteamMatchmaking + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetFavoriteGameCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmaking_GetFavoriteGameCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetFavoriteGame", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_GetFavoriteGame(IntPtr instancePtr, int iGame, out AppId_t pnAppID, out uint pnIP, out ushort pnConnPort, out ushort pnQueryPort, out uint punFlags, out uint pRTime32LastPlayedOnServer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_AddFavoriteGame", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmaking_AddFavoriteGame(IntPtr instancePtr, AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags, uint rTime32LastPlayedOnServer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_RemoveFavoriteGame", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_RemoveFavoriteGame(IntPtr instancePtr, AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_RequestLobbyList", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamMatchmaking_RequestLobbyList(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_AddRequestLobbyListStringFilter", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_AddRequestLobbyListStringFilter(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKeyToMatch, InteropHelp.UTF8StringHandle pchValueToMatch, ELobbyComparison eComparisonType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_AddRequestLobbyListNumericalFilter", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_AddRequestLobbyListNumericalFilter(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKeyToMatch, int nValueToMatch, ELobbyComparison eComparisonType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_AddRequestLobbyListNearValueFilter", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_AddRequestLobbyListNearValueFilter(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKeyToMatch, int nValueToBeCloseTo); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_AddRequestLobbyListFilterSlotsAvailable", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_AddRequestLobbyListFilterSlotsAvailable(IntPtr instancePtr, int nSlotsAvailable); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_AddRequestLobbyListDistanceFilter", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_AddRequestLobbyListDistanceFilter(IntPtr instancePtr, ELobbyDistanceFilter eLobbyDistanceFilter); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_AddRequestLobbyListResultCountFilter", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_AddRequestLobbyListResultCountFilter(IntPtr instancePtr, int cMaxResults); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_AddRequestLobbyListCompatibleMembersFilter", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_AddRequestLobbyListCompatibleMembersFilter(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamMatchmaking_GetLobbyByIndex(IntPtr instancePtr, int iLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_CreateLobby", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamMatchmaking_CreateLobby(IntPtr instancePtr, ELobbyType eLobbyType, int cMaxMembers); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_JoinLobby", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamMatchmaking_JoinLobby(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_LeaveLobby", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_LeaveLobby(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_InviteUserToLobby", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_InviteUserToLobby(IntPtr instancePtr, CSteamID steamIDLobby, CSteamID steamIDInvitee); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetNumLobbyMembers", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmaking_GetNumLobbyMembers(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyMemberByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamMatchmaking_GetLobbyMemberByIndex(IntPtr instancePtr, CSteamID steamIDLobby, int iMember); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyData", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmaking_GetLobbyData(IntPtr instancePtr, CSteamID steamIDLobby, InteropHelp.UTF8StringHandle pchKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SetLobbyData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_SetLobbyData(IntPtr instancePtr, CSteamID steamIDLobby, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyDataCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmaking_GetLobbyDataCount(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyDataByIndex", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_GetLobbyDataByIndex(IntPtr instancePtr, CSteamID steamIDLobby, int iLobbyData, IntPtr pchKey, int cchKeyBufferSize, IntPtr pchValue, int cchValueBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_DeleteLobbyData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_DeleteLobbyData(IntPtr instancePtr, CSteamID steamIDLobby, InteropHelp.UTF8StringHandle pchKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyMemberData", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmaking_GetLobbyMemberData(IntPtr instancePtr, CSteamID steamIDLobby, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SetLobbyMemberData", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_SetLobbyMemberData(IntPtr instancePtr, CSteamID steamIDLobby, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SendLobbyChatMsg", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_SendLobbyChatMsg(IntPtr instancePtr, CSteamID steamIDLobby, byte[] pvMsgBody, int cubMsgBody); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyChatEntry", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmaking_GetLobbyChatEntry(IntPtr instancePtr, CSteamID steamIDLobby, int iChatID, out CSteamID pSteamIDUser, byte[] pvData, int cubData, out EChatEntryType peChatEntryType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_RequestLobbyData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_RequestLobbyData(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SetLobbyGameServer", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_SetLobbyGameServer(IntPtr instancePtr, CSteamID steamIDLobby, uint unGameServerIP, ushort unGameServerPort, CSteamID steamIDGameServer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyGameServer", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_GetLobbyGameServer(IntPtr instancePtr, CSteamID steamIDLobby, out uint punGameServerIP, out ushort punGameServerPort, out CSteamID psteamIDGameServer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SetLobbyMemberLimit", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_SetLobbyMemberLimit(IntPtr instancePtr, CSteamID steamIDLobby, int cMaxMembers); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyMemberLimit", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmaking_GetLobbyMemberLimit(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SetLobbyType", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_SetLobbyType(IntPtr instancePtr, CSteamID steamIDLobby, ELobbyType eLobbyType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SetLobbyJoinable", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_SetLobbyJoinable(IntPtr instancePtr, CSteamID steamIDLobby, [MarshalAs(UnmanagedType.I1)] bool bLobbyJoinable); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_GetLobbyOwner", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamMatchmaking_GetLobbyOwner(IntPtr instancePtr, CSteamID steamIDLobby); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SetLobbyOwner", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_SetLobbyOwner(IntPtr instancePtr, CSteamID steamIDLobby, CSteamID steamIDNewOwner); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_SetLinkedLobby", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmaking_SetLinkedLobby(IntPtr instancePtr, CSteamID steamIDLobby, CSteamID steamIDLobbyDependent); +#if _PS3 + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmaking_CheckForPSNGameBootInvite", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmaking_CheckForPSNGameBootInvite(IntPtr instancePtr, uint iGameBootAttributes); +#endif +#endregion +#region SteamMatchmakingServers + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestInternetServerList", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmakingServers_RequestInternetServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestLANServerList", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmakingServers_RequestLANServerList(IntPtr instancePtr, AppId_t iApp, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestFriendsServerList", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmakingServers_RequestFriendsServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestFavoritesServerList", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmakingServers_RequestFavoritesServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestHistoryServerList", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmakingServers_RequestHistoryServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestSpectatorServerList", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmakingServers_RequestSpectatorServerList(IntPtr instancePtr, AppId_t iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_ReleaseRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmakingServers_ReleaseRequest(IntPtr instancePtr, HServerListRequest hServerListRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_GetServerDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamMatchmakingServers_GetServerDetails(IntPtr instancePtr, HServerListRequest hRequest, int iServer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_CancelQuery", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmakingServers_CancelQuery(IntPtr instancePtr, HServerListRequest hRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RefreshQuery", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmakingServers_RefreshQuery(IntPtr instancePtr, HServerListRequest hRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_IsRefreshing", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMatchmakingServers_IsRefreshing(IntPtr instancePtr, HServerListRequest hRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_GetServerCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmakingServers_GetServerCount(IntPtr instancePtr, HServerListRequest hRequest); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RefreshServer", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmakingServers_RefreshServer(IntPtr instancePtr, HServerListRequest hRequest, int iServer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_PingServer", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmakingServers_PingServer(IntPtr instancePtr, uint unIP, ushort usPort, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_PlayerDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmakingServers_PlayerDetails(IntPtr instancePtr, uint unIP, ushort usPort, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_ServerRules", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamMatchmakingServers_ServerRules(IntPtr instancePtr, uint unIP, ushort usPort, IntPtr pRequestServersResponse); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_CancelServerQuery", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMatchmakingServers_CancelServerQuery(IntPtr instancePtr, HServerQuery hServerQuery); +#endregion +#region SteamGameSearch + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_AddGameSearchParams", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_AddGameSearchParams(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKeyToFind, InteropHelp.UTF8StringHandle pchValuesToFind); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_SearchForGameWithLobby", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_SearchForGameWithLobby(IntPtr instancePtr, CSteamID steamIDLobby, int nPlayerMin, int nPlayerMax); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_SearchForGameSolo", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_SearchForGameSolo(IntPtr instancePtr, int nPlayerMin, int nPlayerMax); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_AcceptGame", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_AcceptGame(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_DeclineGame", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_DeclineGame(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_RetrieveConnectionDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_RetrieveConnectionDetails(IntPtr instancePtr, CSteamID steamIDHost, IntPtr pchConnectionDetails, int cubConnectionDetails); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_EndGameSearch", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_EndGameSearch(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_SetGameHostParams", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_SetGameHostParams(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_SetConnectionDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_SetConnectionDetails(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchConnectionDetails, int cubConnectionDetails); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_RequestPlayersForGame", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_RequestPlayersForGame(IntPtr instancePtr, int nPlayerMin, int nPlayerMax, int nMaxTeamSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_HostConfirmGameStart", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_HostConfirmGameStart(IntPtr instancePtr, ulong ullUniqueGameID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_CancelRequestPlayersForGame", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_CancelRequestPlayersForGame(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_SubmitPlayerResult", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_SubmitPlayerResult(IntPtr instancePtr, ulong ullUniqueGameID, CSteamID steamIDPlayer, EPlayerResult_t EPlayerResult); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamGameSearch_EndGame", CallingConvention = CallingConvention.Cdecl)] + public static extern EGameSearchErrorCode_t ISteamGameSearch_EndGame(IntPtr instancePtr, ulong ullUniqueGameID); +#endregion +#region SteamParties + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_GetNumActiveBeacons", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamParties_GetNumActiveBeacons(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_GetBeaconByIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamParties_GetBeaconByIndex(IntPtr instancePtr, uint unIndex); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_GetBeaconDetails", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParties_GetBeaconDetails(IntPtr instancePtr, PartyBeaconID_t ulBeaconID, out CSteamID pSteamIDBeaconOwner, out SteamPartyBeaconLocation_t pLocation, IntPtr pchMetadata, int cchMetadata); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_JoinParty", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamParties_JoinParty(IntPtr instancePtr, PartyBeaconID_t ulBeaconID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_GetNumAvailableBeaconLocations", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParties_GetNumAvailableBeaconLocations(IntPtr instancePtr, out uint puNumLocations); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_GetAvailableBeaconLocations", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParties_GetAvailableBeaconLocations(IntPtr instancePtr, [In, Out] SteamPartyBeaconLocation_t[] pLocationList, uint uMaxNumLocations); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_CreateBeacon", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamParties_CreateBeacon(IntPtr instancePtr, uint unOpenSlots, ref SteamPartyBeaconLocation_t pBeaconLocation, InteropHelp.UTF8StringHandle pchConnectString, InteropHelp.UTF8StringHandle pchMetadata); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_OnReservationCompleted", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamParties_OnReservationCompleted(IntPtr instancePtr, PartyBeaconID_t ulBeacon, CSteamID steamIDUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_CancelReservation", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamParties_CancelReservation(IntPtr instancePtr, PartyBeaconID_t ulBeacon, CSteamID steamIDUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_ChangeNumOpenSlots", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamParties_ChangeNumOpenSlots(IntPtr instancePtr, PartyBeaconID_t ulBeacon, uint unOpenSlots); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_DestroyBeacon", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParties_DestroyBeacon(IntPtr instancePtr, PartyBeaconID_t ulBeacon); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParties_GetBeaconLocationData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParties_GetBeaconLocationData(IntPtr instancePtr, SteamPartyBeaconLocation_t BeaconLocation, ESteamPartyBeaconLocationData eData, IntPtr pchDataStringOut, int cchDataStringOut); +#endregion +#region SteamMusic + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_BIsEnabled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusic_BIsEnabled(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_BIsPlaying", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusic_BIsPlaying(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_GetPlaybackStatus", CallingConvention = CallingConvention.Cdecl)] + public static extern AudioPlayback_Status ISteamMusic_GetPlaybackStatus(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_Play", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMusic_Play(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_Pause", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMusic_Pause(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_PlayPrevious", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMusic_PlayPrevious(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_PlayNext", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMusic_PlayNext(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_SetVolume", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamMusic_SetVolume(IntPtr instancePtr, float flVolume); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusic_GetVolume", CallingConvention = CallingConvention.Cdecl)] + public static extern float ISteamMusic_GetVolume(IntPtr instancePtr); +#endregion +#region SteamMusicRemote + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_RegisterSteamMusicRemote", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_RegisterSteamMusicRemote(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_DeregisterSteamMusicRemote", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_DeregisterSteamMusicRemote(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_BIsCurrentMusicRemote", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_BIsCurrentMusicRemote(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_BActivationSuccess", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_BActivationSuccess(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_SetDisplayName", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_SetDisplayName(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchDisplayName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_SetPNGIcon_64x64", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_SetPNGIcon_64x64(IntPtr instancePtr, byte[] pvBuffer, uint cbBufferLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_EnablePlayPrevious", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_EnablePlayPrevious(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_EnablePlayNext", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_EnablePlayNext(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_EnableShuffled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_EnableShuffled(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_EnableLooped", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_EnableLooped(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_EnableQueue", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_EnableQueue(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_EnablePlaylists", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_EnablePlaylists(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_UpdatePlaybackStatus", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_UpdatePlaybackStatus(IntPtr instancePtr, AudioPlayback_Status nStatus); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_UpdateShuffled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_UpdateShuffled(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_UpdateLooped", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_UpdateLooped(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_UpdateVolume", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_UpdateVolume(IntPtr instancePtr, float flValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_CurrentEntryWillChange", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_CurrentEntryWillChange(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_CurrentEntryIsAvailable", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_CurrentEntryIsAvailable(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bAvailable); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_UpdateCurrentEntryText", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_UpdateCurrentEntryText(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchText); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_UpdateCurrentEntryElapsedSeconds", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_UpdateCurrentEntryElapsedSeconds(IntPtr instancePtr, int nValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_UpdateCurrentEntryCoverArt", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_UpdateCurrentEntryCoverArt(IntPtr instancePtr, byte[] pvBuffer, uint cbBufferLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_CurrentEntryDidChange", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_CurrentEntryDidChange(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_QueueWillChange", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_QueueWillChange(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_ResetQueueEntries", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_ResetQueueEntries(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_SetQueueEntry", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_SetQueueEntry(IntPtr instancePtr, int nID, int nPosition, InteropHelp.UTF8StringHandle pchEntryText); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_SetCurrentQueueEntry", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_SetCurrentQueueEntry(IntPtr instancePtr, int nID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_QueueDidChange", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_QueueDidChange(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_PlaylistWillChange", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_PlaylistWillChange(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_ResetPlaylistEntries", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_ResetPlaylistEntries(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_SetPlaylistEntry", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_SetPlaylistEntry(IntPtr instancePtr, int nID, int nPosition, InteropHelp.UTF8StringHandle pchEntryText); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_SetCurrentPlaylistEntry", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_SetCurrentPlaylistEntry(IntPtr instancePtr, int nID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamMusicRemote_PlaylistDidChange", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamMusicRemote_PlaylistDidChange(IntPtr instancePtr); +#endregion +#region SteamNetworking + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_SendP2PPacket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_SendP2PPacket(IntPtr instancePtr, CSteamID steamIDRemote, byte[] pubData, uint cubData, EP2PSend eP2PSendType, int nChannel); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_IsP2PPacketAvailable", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_IsP2PPacketAvailable(IntPtr instancePtr, out uint pcubMsgSize, int nChannel); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_ReadP2PPacket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_ReadP2PPacket(IntPtr instancePtr, byte[] pubDest, uint cubDest, out uint pcubMsgSize, out CSteamID psteamIDRemote, int nChannel); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_AcceptP2PSessionWithUser", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_AcceptP2PSessionWithUser(IntPtr instancePtr, CSteamID steamIDRemote); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_CloseP2PSessionWithUser", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_CloseP2PSessionWithUser(IntPtr instancePtr, CSteamID steamIDRemote); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_CloseP2PChannelWithUser", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_CloseP2PChannelWithUser(IntPtr instancePtr, CSteamID steamIDRemote, int nChannel); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_GetP2PSessionState", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_GetP2PSessionState(IntPtr instancePtr, CSteamID steamIDRemote, out P2PSessionState_t pConnectionState); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_AllowP2PPacketRelay", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_AllowP2PPacketRelay(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bAllow); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_CreateListenSocket", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworking_CreateListenSocket(IntPtr instancePtr, int nVirtualP2PPort, SteamIPAddress_t nIP, ushort nPort, [MarshalAs(UnmanagedType.I1)] bool bAllowUseOfPacketRelay); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_CreateP2PConnectionSocket", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworking_CreateP2PConnectionSocket(IntPtr instancePtr, CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, [MarshalAs(UnmanagedType.I1)] bool bAllowUseOfPacketRelay); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_CreateConnectionSocket", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworking_CreateConnectionSocket(IntPtr instancePtr, SteamIPAddress_t nIP, ushort nPort, int nTimeoutSec); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_DestroySocket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_DestroySocket(IntPtr instancePtr, SNetSocket_t hSocket, [MarshalAs(UnmanagedType.I1)] bool bNotifyRemoteEnd); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_DestroyListenSocket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_DestroyListenSocket(IntPtr instancePtr, SNetListenSocket_t hSocket, [MarshalAs(UnmanagedType.I1)] bool bNotifyRemoteEnd); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_SendDataOnSocket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_SendDataOnSocket(IntPtr instancePtr, SNetSocket_t hSocket, byte[] pubData, uint cubData, [MarshalAs(UnmanagedType.I1)] bool bReliable); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_IsDataAvailableOnSocket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_IsDataAvailableOnSocket(IntPtr instancePtr, SNetSocket_t hSocket, out uint pcubMsgSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_RetrieveDataFromSocket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_RetrieveDataFromSocket(IntPtr instancePtr, SNetSocket_t hSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_IsDataAvailable", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_IsDataAvailable(IntPtr instancePtr, SNetListenSocket_t hListenSocket, out uint pcubMsgSize, out SNetSocket_t phSocket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_RetrieveData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_RetrieveData(IntPtr instancePtr, SNetListenSocket_t hListenSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize, out SNetSocket_t phSocket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_GetSocketInfo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_GetSocketInfo(IntPtr instancePtr, SNetSocket_t hSocket, out CSteamID pSteamIDRemote, out int peSocketStatus, out SteamIPAddress_t punIPRemote, out ushort punPortRemote); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_GetListenSocketInfo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworking_GetListenSocketInfo(IntPtr instancePtr, SNetListenSocket_t hListenSocket, out SteamIPAddress_t pnIP, out ushort pnPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_GetSocketConnectionType", CallingConvention = CallingConvention.Cdecl)] + public static extern ESNetSocketConnectionType ISteamNetworking_GetSocketConnectionType(IntPtr instancePtr, SNetSocket_t hSocket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworking_GetMaxPacketSize", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworking_GetMaxPacketSize(IntPtr instancePtr, SNetSocket_t hSocket); +#endregion +#region SteamNetworkingMessages + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingMessages_SendMessageToUser", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingMessages_SendMessageToUser(IntPtr instancePtr, ref SteamNetworkingIdentity identityRemote, IntPtr pubData, uint cubData, int nSendFlags, int nRemoteChannel); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingMessages_ReceiveMessagesOnChannel", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingMessages_ReceiveMessagesOnChannel(IntPtr instancePtr, int nLocalChannel, [In, Out] IntPtr[] ppOutMessages, int nMaxMessages); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingMessages_AcceptSessionWithUser", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingMessages_AcceptSessionWithUser(IntPtr instancePtr, ref SteamNetworkingIdentity identityRemote); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingMessages_CloseSessionWithUser", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingMessages_CloseSessionWithUser(IntPtr instancePtr, ref SteamNetworkingIdentity identityRemote); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingMessages_CloseChannelWithUser", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingMessages_CloseChannelWithUser(IntPtr instancePtr, ref SteamNetworkingIdentity identityRemote, int nLocalChannel); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingMessages_GetSessionConnectionInfo", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingConnectionState ISteamNetworkingMessages_GetSessionConnectionInfo(IntPtr instancePtr, ref SteamNetworkingIdentity identityRemote, out SteamNetConnectionInfo_t pConnectionInfo, out SteamNetConnectionRealTimeStatus_t pQuickStatus); +#endregion +#region SteamNetworkingSockets + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CreateListenSocketIP", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_CreateListenSocketIP(IntPtr instancePtr, ref SteamNetworkingIPAddr localAddress, int nOptions, [In, Out] SteamNetworkingConfigValue_t[] pOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_ConnectByIPAddress(IntPtr instancePtr, ref SteamNetworkingIPAddr address, int nOptions, [In, Out] SteamNetworkingConfigValue_t[] pOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CreateListenSocketP2P", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_CreateListenSocketP2P(IntPtr instancePtr, int nLocalVirtualPort, int nOptions, [In, Out] SteamNetworkingConfigValue_t[] pOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ConnectP2P", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_ConnectP2P(IntPtr instancePtr, ref SteamNetworkingIdentity identityRemote, int nRemoteVirtualPort, int nOptions, [In, Out] SteamNetworkingConfigValue_t[] pOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_AcceptConnection", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingSockets_AcceptConnection(IntPtr instancePtr, HSteamNetConnection hConn); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CloseConnection", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_CloseConnection(IntPtr instancePtr, HSteamNetConnection hPeer, int nReason, InteropHelp.UTF8StringHandle pszDebug, [MarshalAs(UnmanagedType.I1)] bool bEnableLinger); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CloseListenSocket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_CloseListenSocket(IntPtr instancePtr, HSteamListenSocket hSocket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_SetConnectionUserData", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_SetConnectionUserData(IntPtr instancePtr, HSteamNetConnection hPeer, long nUserData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetConnectionUserData", CallingConvention = CallingConvention.Cdecl)] + public static extern long ISteamNetworkingSockets_GetConnectionUserData(IntPtr instancePtr, HSteamNetConnection hPeer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_SetConnectionName", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingSockets_SetConnectionName(IntPtr instancePtr, HSteamNetConnection hPeer, InteropHelp.UTF8StringHandle pszName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetConnectionName", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_GetConnectionName(IntPtr instancePtr, HSteamNetConnection hPeer, IntPtr pszName, int nMaxLen); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_SendMessageToConnection", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingSockets_SendMessageToConnection(IntPtr instancePtr, HSteamNetConnection hConn, IntPtr pData, uint cbData, int nSendFlags, out long pOutMessageNumber); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_SendMessages", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingSockets_SendMessages(IntPtr instancePtr, int nMessages, [In, Out] SteamNetworkingMessage_t[] pMessages, [In, Out] long[] pOutMessageNumberOrResult); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_FlushMessagesOnConnection", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingSockets_FlushMessagesOnConnection(IntPtr instancePtr, HSteamNetConnection hConn); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnConnection", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingSockets_ReceiveMessagesOnConnection(IntPtr instancePtr, HSteamNetConnection hConn, [In, Out] IntPtr[] ppOutMessages, int nMaxMessages); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetConnectionInfo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_GetConnectionInfo(IntPtr instancePtr, HSteamNetConnection hConn, out SteamNetConnectionInfo_t pInfo); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetConnectionRealTimeStatus", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingSockets_GetConnectionRealTimeStatus(IntPtr instancePtr, HSteamNetConnection hConn, ref SteamNetConnectionRealTimeStatus_t pStatus, int nLanes, ref SteamNetConnectionRealTimeLaneStatus_t pLanes); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetDetailedConnectionStatus", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingSockets_GetDetailedConnectionStatus(IntPtr instancePtr, HSteamNetConnection hConn, IntPtr pszBuf, int cbBuf); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetListenSocketAddress", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_GetListenSocketAddress(IntPtr instancePtr, HSteamListenSocket hSocket, out SteamNetworkingIPAddr address); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CreateSocketPair", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_CreateSocketPair(IntPtr instancePtr, out HSteamNetConnection pOutConnection1, out HSteamNetConnection pOutConnection2, [MarshalAs(UnmanagedType.I1)] bool bUseNetworkLoopback, ref SteamNetworkingIdentity pIdentity1, ref SteamNetworkingIdentity pIdentity2); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ConfigureConnectionLanes", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingSockets_ConfigureConnectionLanes(IntPtr instancePtr, HSteamNetConnection hConn, int nNumLanes, out int pLanePriorities, out ushort pLaneWeights); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetIdentity", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_GetIdentity(IntPtr instancePtr, out SteamNetworkingIdentity pIdentity); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_InitAuthentication", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingAvailability ISteamNetworkingSockets_InitAuthentication(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetAuthenticationStatus", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingAvailability ISteamNetworkingSockets_GetAuthenticationStatus(IntPtr instancePtr, out SteamNetAuthenticationStatus_t pDetails); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CreatePollGroup", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_CreatePollGroup(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_DestroyPollGroup", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_DestroyPollGroup(IntPtr instancePtr, HSteamNetPollGroup hPollGroup); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_SetConnectionPollGroup", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_SetConnectionPollGroup(IntPtr instancePtr, HSteamNetConnection hConn, HSteamNetPollGroup hPollGroup); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnPollGroup", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingSockets_ReceiveMessagesOnPollGroup(IntPtr instancePtr, HSteamNetPollGroup hPollGroup, [In, Out] IntPtr[] ppOutMessages, int nMaxMessages); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ReceivedRelayAuthTicket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_ReceivedRelayAuthTicket(IntPtr instancePtr, IntPtr pvTicket, int cbTicket, out SteamDatagramRelayAuthTicket pOutParsedTicket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_FindRelayAuthTicketForServer", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingSockets_FindRelayAuthTicketForServer(IntPtr instancePtr, ref SteamNetworkingIdentity identityGameServer, int nRemoteVirtualPort, out SteamDatagramRelayAuthTicket pOutParsedTicket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ConnectToHostedDedicatedServer", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_ConnectToHostedDedicatedServer(IntPtr instancePtr, ref SteamNetworkingIdentity identityTarget, int nRemoteVirtualPort, int nOptions, [In, Out] SteamNetworkingConfigValue_t[] pOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetHostedDedicatedServerPort", CallingConvention = CallingConvention.Cdecl)] + public static extern ushort ISteamNetworkingSockets_GetHostedDedicatedServerPort(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetHostedDedicatedServerPOPID", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_GetHostedDedicatedServerPOPID(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetHostedDedicatedServerAddress", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingSockets_GetHostedDedicatedServerAddress(IntPtr instancePtr, out SteamDatagramHostedAddress pRouting); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CreateHostedDedicatedServerListenSocket", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_CreateHostedDedicatedServerListenSocket(IntPtr instancePtr, int nLocalVirtualPort, int nOptions, [In, Out] SteamNetworkingConfigValue_t[] pOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetGameCoordinatorServerLogin", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingSockets_GetGameCoordinatorServerLogin(IntPtr instancePtr, IntPtr pLoginInfo, out int pcbSignedBlob, IntPtr pBlob); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ConnectP2PCustomSignaling", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_ConnectP2PCustomSignaling(IntPtr instancePtr, out ISteamNetworkingConnectionSignaling pSignaling, ref SteamNetworkingIdentity pPeerIdentity, int nRemoteVirtualPort, int nOptions, [In, Out] SteamNetworkingConfigValue_t[] pOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ReceivedP2PCustomSignal", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_ReceivedP2PCustomSignal(IntPtr instancePtr, IntPtr pMsg, int cbMsg, out ISteamNetworkingSignalingRecvContext pContext); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetCertificateRequest", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_GetCertificateRequest(IntPtr instancePtr, out int pcbBlob, IntPtr pBlob, out SteamNetworkingErrMsg errMsg); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_SetCertificate", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_SetCertificate(IntPtr instancePtr, IntPtr pCertificate, int cbCertificate, out SteamNetworkingErrMsg errMsg); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_ResetIdentity", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingSockets_ResetIdentity(IntPtr instancePtr, ref SteamNetworkingIdentity pIdentity); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_RunCallbacks", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingSockets_RunCallbacks(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_BeginAsyncRequestFakeIP", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingSockets_BeginAsyncRequestFakeIP(IntPtr instancePtr, int nNumPorts); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetFakeIP", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingSockets_GetFakeIP(IntPtr instancePtr, int idxFirstPort, out SteamNetworkingFakeIPResult_t pInfo); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CreateListenSocketP2PFakeIP", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamNetworkingSockets_CreateListenSocketP2PFakeIP(IntPtr instancePtr, int idxFakePort, int nOptions, [In, Out] SteamNetworkingConfigValue_t[] pOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_GetRemoteFakeIPForConnection", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingSockets_GetRemoteFakeIPForConnection(IntPtr instancePtr, HSteamNetConnection hConn, out SteamNetworkingIPAddr pOutAddr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingSockets_CreateFakeUDPPort", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamNetworkingSockets_CreateFakeUDPPort(IntPtr instancePtr, int idxFakeServerPort); +#endregion +#region SteamNetworkingUtils + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_AllocateMessage", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamNetworkingUtils_AllocateMessage(IntPtr instancePtr, int cbAllocateBuffer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_InitRelayNetworkAccess", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingUtils_InitRelayNetworkAccess(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetRelayNetworkStatus", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingAvailability ISteamNetworkingUtils_GetRelayNetworkStatus(IntPtr instancePtr, out SteamRelayNetworkStatus_t pDetails); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetLocalPingLocation", CallingConvention = CallingConvention.Cdecl)] + public static extern float ISteamNetworkingUtils_GetLocalPingLocation(IntPtr instancePtr, out SteamNetworkPingLocation_t result); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_EstimatePingTimeBetweenTwoLocations", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingUtils_EstimatePingTimeBetweenTwoLocations(IntPtr instancePtr, ref SteamNetworkPingLocation_t location1, ref SteamNetworkPingLocation_t location2); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_EstimatePingTimeFromLocalHost", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingUtils_EstimatePingTimeFromLocalHost(IntPtr instancePtr, ref SteamNetworkPingLocation_t remoteLocation); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_ConvertPingLocationToString", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingUtils_ConvertPingLocationToString(IntPtr instancePtr, ref SteamNetworkPingLocation_t location, IntPtr pszBuf, int cchBufSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_ParsePingLocationString", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingUtils_ParsePingLocationString(IntPtr instancePtr, InteropHelp.UTF8StringHandle pszString, out SteamNetworkPingLocation_t result); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_CheckPingDataUpToDate", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingUtils_CheckPingDataUpToDate(IntPtr instancePtr, float flMaxAgeSeconds); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetPingToDataCenter", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingUtils_GetPingToDataCenter(IntPtr instancePtr, SteamNetworkingPOPID popID, out SteamNetworkingPOPID pViaRelayPoP); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetDirectPingToPOP", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingUtils_GetDirectPingToPOP(IntPtr instancePtr, SteamNetworkingPOPID popID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetPOPCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingUtils_GetPOPCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetPOPList", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamNetworkingUtils_GetPOPList(IntPtr instancePtr, out SteamNetworkingPOPID list, int nListSz); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetLocalTimestamp", CallingConvention = CallingConvention.Cdecl)] + public static extern long ISteamNetworkingUtils_GetLocalTimestamp(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_SetDebugOutputFunction", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingUtils_SetDebugOutputFunction(IntPtr instancePtr, ESteamNetworkingSocketsDebugOutputType eDetailLevel, FSteamNetworkingSocketsDebugOutput pfnFunc); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_IsFakeIPv4", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingUtils_IsFakeIPv4(IntPtr instancePtr, uint nIPv4); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetIPv4FakeIPType", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingFakeIPType ISteamNetworkingUtils_GetIPv4FakeIPType(IntPtr instancePtr, uint nIPv4); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetRealIdentityForFakeIP", CallingConvention = CallingConvention.Cdecl)] + public static extern EResult ISteamNetworkingUtils_GetRealIdentityForFakeIP(IntPtr instancePtr, ref SteamNetworkingIPAddr fakeIP, out SteamNetworkingIdentity pOutRealIdentity); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_SetConfigValue", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingUtils_SetConfigValue(IntPtr instancePtr, ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigScope eScopeType, IntPtr scopeObj, ESteamNetworkingConfigDataType eDataType, IntPtr pArg); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetConfigValue", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingGetConfigValueResult ISteamNetworkingUtils_GetConfigValue(IntPtr instancePtr, ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigScope eScopeType, IntPtr scopeObj, out ESteamNetworkingConfigDataType pOutDataType, IntPtr pResult, ref ulong cbResult); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_GetConfigValueInfo", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamNetworkingUtils_GetConfigValueInfo(IntPtr instancePtr, ESteamNetworkingConfigValue eValue, out ESteamNetworkingConfigDataType pOutDataType, out ESteamNetworkingConfigScope pOutScope); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_IterateGenericEditableConfigValues", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingConfigValue ISteamNetworkingUtils_IterateGenericEditableConfigValues(IntPtr instancePtr, ESteamNetworkingConfigValue eCurrent, [MarshalAs(UnmanagedType.I1)] bool bEnumerateDevVars); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_SteamNetworkingIPAddr_ToString", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingUtils_SteamNetworkingIPAddr_ToString(IntPtr instancePtr, ref SteamNetworkingIPAddr addr, IntPtr buf, uint cbBuf, [MarshalAs(UnmanagedType.I1)] bool bWithPort); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_SteamNetworkingIPAddr_ParseString", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingUtils_SteamNetworkingIPAddr_ParseString(IntPtr instancePtr, out SteamNetworkingIPAddr pAddr, InteropHelp.UTF8StringHandle pszStr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_SteamNetworkingIPAddr_GetFakeIPType", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamNetworkingFakeIPType ISteamNetworkingUtils_SteamNetworkingIPAddr_GetFakeIPType(IntPtr instancePtr, ref SteamNetworkingIPAddr addr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_SteamNetworkingIdentity_ToString", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamNetworkingUtils_SteamNetworkingIdentity_ToString(IntPtr instancePtr, ref SteamNetworkingIdentity identity, IntPtr buf, uint cbBuf); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamNetworkingUtils_SteamNetworkingIdentity_ParseString", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamNetworkingUtils_SteamNetworkingIdentity_ParseString(IntPtr instancePtr, out SteamNetworkingIdentity pIdentity, InteropHelp.UTF8StringHandle pszStr); +#endregion +#region SteamParentalSettings + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParentalSettings_BIsParentalLockEnabled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParentalSettings_BIsParentalLockEnabled(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParentalSettings_BIsParentalLockLocked", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParentalSettings_BIsParentalLockLocked(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParentalSettings_BIsAppBlocked", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParentalSettings_BIsAppBlocked(IntPtr instancePtr, AppId_t nAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParentalSettings_BIsAppInBlockList", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParentalSettings_BIsAppInBlockList(IntPtr instancePtr, AppId_t nAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParentalSettings_BIsFeatureBlocked", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParentalSettings_BIsFeatureBlocked(IntPtr instancePtr, EParentalFeature eFeature); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamParentalSettings_BIsFeatureInBlockList", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamParentalSettings_BIsFeatureInBlockList(IntPtr instancePtr, EParentalFeature eFeature); +#endregion +#region SteamRemotePlay + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemotePlay_GetSessionCount", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamRemotePlay_GetSessionCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemotePlay_GetSessionID", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamRemotePlay_GetSessionID(IntPtr instancePtr, int iSessionIndex); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemotePlay_GetSessionSteamID", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemotePlay_GetSessionSteamID(IntPtr instancePtr, RemotePlaySessionID_t unSessionID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemotePlay_GetSessionClientName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamRemotePlay_GetSessionClientName(IntPtr instancePtr, RemotePlaySessionID_t unSessionID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemotePlay_GetSessionClientFormFactor", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamDeviceFormFactor ISteamRemotePlay_GetSessionClientFormFactor(IntPtr instancePtr, RemotePlaySessionID_t unSessionID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemotePlay_BGetSessionClientResolution", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemotePlay_BGetSessionClientResolution(IntPtr instancePtr, RemotePlaySessionID_t unSessionID, out int pnResolutionX, out int pnResolutionY); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemotePlay_BSendRemotePlayTogetherInvite", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemotePlay_BSendRemotePlayTogetherInvite(IntPtr instancePtr, CSteamID steamIDFriend); +#endregion +#region SteamRemoteStorage + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileWrite", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FileWrite(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, byte[] pvData, int cubData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileRead", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamRemoteStorage_FileRead(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, byte[] pvData, int cubDataToRead); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileWriteAsync", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_FileWriteAsync(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, byte[] pvData, uint cubData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileReadAsync", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_FileReadAsync(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, uint nOffset, uint cubToRead); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileReadAsyncComplete", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FileReadAsyncComplete(IntPtr instancePtr, SteamAPICall_t hReadCall, byte[] pvBuffer, uint cubToRead); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileForget", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FileForget(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileDelete", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FileDelete(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileShare", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_FileShare(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_SetSyncPlatforms", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_SetSyncPlatforms(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, ERemoteStoragePlatform eRemoteStoragePlatform); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileWriteStreamOpen", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_FileWriteStreamOpen(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileWriteStreamWriteChunk", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FileWriteStreamWriteChunk(IntPtr instancePtr, UGCFileWriteStreamHandle_t writeHandle, byte[] pvData, int cubData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileWriteStreamClose", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FileWriteStreamClose(IntPtr instancePtr, UGCFileWriteStreamHandle_t writeHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileWriteStreamCancel", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FileWriteStreamCancel(IntPtr instancePtr, UGCFileWriteStreamHandle_t writeHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FileExists", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FileExists(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_FilePersisted", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_FilePersisted(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetFileSize", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamRemoteStorage_GetFileSize(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetFileTimestamp", CallingConvention = CallingConvention.Cdecl)] + public static extern long ISteamRemoteStorage_GetFileTimestamp(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetSyncPlatforms", CallingConvention = CallingConvention.Cdecl)] + public static extern ERemoteStoragePlatform ISteamRemoteStorage_GetSyncPlatforms(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetFileCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamRemoteStorage_GetFileCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetFileNameAndSize", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamRemoteStorage_GetFileNameAndSize(IntPtr instancePtr, int iFile, out int pnFileSizeInBytes); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetQuota", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_GetQuota(IntPtr instancePtr, out ulong pnTotalBytes, out ulong puAvailableBytes); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_IsCloudEnabledForAccount", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_IsCloudEnabledForAccount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_IsCloudEnabledForApp", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_IsCloudEnabledForApp(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_SetCloudEnabledForApp", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamRemoteStorage_SetCloudEnabledForApp(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bEnabled); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UGCDownload", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_UGCDownload(IntPtr instancePtr, UGCHandle_t hContent, uint unPriority); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetUGCDownloadProgress", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_GetUGCDownloadProgress(IntPtr instancePtr, UGCHandle_t hContent, out int pnBytesDownloaded, out int pnBytesExpected); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetUGCDetails", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_GetUGCDetails(IntPtr instancePtr, UGCHandle_t hContent, out AppId_t pnAppID, out IntPtr ppchName, out int pnFileSizeInBytes, out CSteamID pSteamIDOwner); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UGCRead", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamRemoteStorage_UGCRead(IntPtr instancePtr, UGCHandle_t hContent, byte[] pvData, int cubDataToRead, uint cOffset, EUGCReadAction eAction); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetCachedUGCCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamRemoteStorage_GetCachedUGCCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetCachedUGCHandle", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_GetCachedUGCHandle(IntPtr instancePtr, int iCachedContent); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_PublishWorkshopFile", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_PublishWorkshopFile(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFile, InteropHelp.UTF8StringHandle pchPreviewFile, AppId_t nConsumerAppId, InteropHelp.UTF8StringHandle pchTitle, InteropHelp.UTF8StringHandle pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, IntPtr pTags, EWorkshopFileType eWorkshopFileType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_CreatePublishedFileUpdateRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_CreatePublishedFileUpdateRequest(IntPtr instancePtr, PublishedFileId_t unPublishedFileId); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UpdatePublishedFileFile", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_UpdatePublishedFileFile(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UpdatePublishedFilePreviewFile", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_UpdatePublishedFilePreviewFile(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchPreviewFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UpdatePublishedFileTitle", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_UpdatePublishedFileTitle(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchTitle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UpdatePublishedFileDescription", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_UpdatePublishedFileDescription(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchDescription); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UpdatePublishedFileVisibility", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_UpdatePublishedFileVisibility(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, ERemoteStoragePublishedFileVisibility eVisibility); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UpdatePublishedFileTags", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_UpdatePublishedFileTags(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, IntPtr pTags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_CommitPublishedFileUpdate", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_CommitPublishedFileUpdate(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetPublishedFileDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_GetPublishedFileDetails(IntPtr instancePtr, PublishedFileId_t unPublishedFileId, uint unMaxSecondsOld); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_DeletePublishedFile", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_DeletePublishedFile(IntPtr instancePtr, PublishedFileId_t unPublishedFileId); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_EnumerateUserPublishedFiles", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_EnumerateUserPublishedFiles(IntPtr instancePtr, uint unStartIndex); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_SubscribePublishedFile", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_SubscribePublishedFile(IntPtr instancePtr, PublishedFileId_t unPublishedFileId); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_EnumerateUserSubscribedFiles", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_EnumerateUserSubscribedFiles(IntPtr instancePtr, uint unStartIndex); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UnsubscribePublishedFile", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_UnsubscribePublishedFile(IntPtr instancePtr, PublishedFileId_t unPublishedFileId); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UpdatePublishedFileSetChangeDescription", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_UpdatePublishedFileSetChangeDescription(IntPtr instancePtr, PublishedFileUpdateHandle_t updateHandle, InteropHelp.UTF8StringHandle pchChangeDescription); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetPublishedItemVoteDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_GetPublishedItemVoteDetails(IntPtr instancePtr, PublishedFileId_t unPublishedFileId); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UpdateUserPublishedItemVote", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_UpdateUserPublishedItemVote(IntPtr instancePtr, PublishedFileId_t unPublishedFileId, [MarshalAs(UnmanagedType.I1)] bool bVoteUp); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetUserPublishedItemVoteDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_GetUserPublishedItemVoteDetails(IntPtr instancePtr, PublishedFileId_t unPublishedFileId); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_EnumerateUserSharedWorkshopFiles", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_EnumerateUserSharedWorkshopFiles(IntPtr instancePtr, CSteamID steamId, uint unStartIndex, IntPtr pRequiredTags, IntPtr pExcludedTags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_PublishVideo", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_PublishVideo(IntPtr instancePtr, EWorkshopVideoProvider eVideoProvider, InteropHelp.UTF8StringHandle pchVideoAccount, InteropHelp.UTF8StringHandle pchVideoIdentifier, InteropHelp.UTF8StringHandle pchPreviewFile, AppId_t nConsumerAppId, InteropHelp.UTF8StringHandle pchTitle, InteropHelp.UTF8StringHandle pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, IntPtr pTags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_SetUserPublishedFileAction", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_SetUserPublishedFileAction(IntPtr instancePtr, PublishedFileId_t unPublishedFileId, EWorkshopFileAction eAction); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_EnumeratePublishedFilesByUserAction", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_EnumeratePublishedFilesByUserAction(IntPtr instancePtr, EWorkshopFileAction eAction, uint unStartIndex); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_EnumeratePublishedWorkshopFiles", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_EnumeratePublishedWorkshopFiles(IntPtr instancePtr, EWorkshopEnumerationType eEnumerationType, uint unStartIndex, uint unCount, uint unDays, IntPtr pTags, IntPtr pUserTags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_UGCDownloadToLocation", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamRemoteStorage_UGCDownloadToLocation(IntPtr instancePtr, UGCHandle_t hContent, InteropHelp.UTF8StringHandle pchLocation, uint unPriority); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetLocalFileChangeCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamRemoteStorage_GetLocalFileChangeCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_GetLocalFileChange", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamRemoteStorage_GetLocalFileChange(IntPtr instancePtr, int iFile, out ERemoteStorageLocalFileChange pEChangeType, out ERemoteStorageFilePathType pEFilePathType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_BeginFileWriteBatch", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_BeginFileWriteBatch(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamRemoteStorage_EndFileWriteBatch", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamRemoteStorage_EndFileWriteBatch(IntPtr instancePtr); +#endregion +#region SteamScreenshots + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_WriteScreenshot", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamScreenshots_WriteScreenshot(IntPtr instancePtr, byte[] pubRGB, uint cubRGB, int nWidth, int nHeight); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_AddScreenshotToLibrary", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamScreenshots_AddScreenshotToLibrary(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchFilename, InteropHelp.UTF8StringHandle pchThumbnailFilename, int nWidth, int nHeight); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_TriggerScreenshot", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamScreenshots_TriggerScreenshot(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_HookScreenshots", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamScreenshots_HookScreenshots(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bHook); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_SetLocation", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamScreenshots_SetLocation(IntPtr instancePtr, ScreenshotHandle hScreenshot, InteropHelp.UTF8StringHandle pchLocation); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_TagUser", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamScreenshots_TagUser(IntPtr instancePtr, ScreenshotHandle hScreenshot, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_TagPublishedFile", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamScreenshots_TagPublishedFile(IntPtr instancePtr, ScreenshotHandle hScreenshot, PublishedFileId_t unPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_IsScreenshotsHooked", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamScreenshots_IsScreenshotsHooked(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamScreenshots_AddVRScreenshotToLibrary", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamScreenshots_AddVRScreenshotToLibrary(IntPtr instancePtr, EVRScreenshotType eType, InteropHelp.UTF8StringHandle pchFilename, InteropHelp.UTF8StringHandle pchVRFilename); +#endregion +#region SteamUGC + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_CreateQueryUserUGCRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_CreateQueryUserUGCRequest(IntPtr instancePtr, AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_CreateQueryAllUGCRequestPage", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_CreateQueryAllUGCRequestPage(IntPtr instancePtr, EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_CreateQueryAllUGCRequestCursor", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_CreateQueryAllUGCRequestCursor(IntPtr instancePtr, EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, InteropHelp.UTF8StringHandle pchCursor); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_CreateQueryUGCDetailsRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_CreateQueryUGCDetailsRequest(IntPtr instancePtr, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SendQueryUGCRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_SendQueryUGCRequest(IntPtr instancePtr, UGCQueryHandle_t handle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCResult", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCResult(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, out SteamUGCDetails_t pDetails); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCNumTags", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUGC_GetQueryUGCNumTags(IntPtr instancePtr, UGCQueryHandle_t handle, uint index); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCTag", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCTag(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, uint indexTag, IntPtr pchValue, uint cchValueSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCTagDisplayName", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCTagDisplayName(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, uint indexTag, IntPtr pchValue, uint cchValueSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCPreviewURL", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCPreviewURL(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, IntPtr pchURL, uint cchURLSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCMetadata", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCMetadata(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, IntPtr pchMetadata, uint cchMetadatasize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCChildren", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCChildren(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCStatistic", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCStatistic(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, EItemStatistic eStatType, out ulong pStatValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCNumAdditionalPreviews", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUGC_GetQueryUGCNumAdditionalPreviews(IntPtr instancePtr, UGCQueryHandle_t handle, uint index); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCAdditionalPreview", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCAdditionalPreview(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, uint previewIndex, IntPtr pchURLOrVideoID, uint cchURLSize, IntPtr pchOriginalFileName, uint cchOriginalFileNameSize, out EItemPreviewType pPreviewType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCNumKeyValueTags", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUGC_GetQueryUGCNumKeyValueTags(IntPtr instancePtr, UGCQueryHandle_t handle, uint index); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCKeyValueTag", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryUGCKeyValueTag(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, uint keyValueTagIndex, IntPtr pchKey, uint cchKeySize, IntPtr pchValue, uint cchValueSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryFirstUGCKeyValueTag", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetQueryFirstUGCKeyValueTag(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, InteropHelp.UTF8StringHandle pchKey, IntPtr pchValue, uint cchValueSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetQueryUGCContentDescriptors", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUGC_GetQueryUGCContentDescriptors(IntPtr instancePtr, UGCQueryHandle_t handle, uint index, out EUGCContentDescriptorID pvecDescriptors, uint cMaxEntries); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_ReleaseQueryUGCRequest", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_ReleaseQueryUGCRequest(IntPtr instancePtr, UGCQueryHandle_t handle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddRequiredTag", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_AddRequiredTag(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pTagName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddRequiredTagGroup", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_AddRequiredTagGroup(IntPtr instancePtr, UGCQueryHandle_t handle, IntPtr pTagGroups); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddExcludedTag", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_AddExcludedTag(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pTagName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetReturnOnlyIDs", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetReturnOnlyIDs(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnOnlyIDs); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetReturnKeyValueTags", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetReturnKeyValueTags(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnKeyValueTags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetReturnLongDescription", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetReturnLongDescription(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnLongDescription); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetReturnMetadata", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetReturnMetadata(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnMetadata); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetReturnChildren", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetReturnChildren(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnChildren); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetReturnAdditionalPreviews", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetReturnAdditionalPreviews(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnAdditionalPreviews); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetReturnTotalOnly", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetReturnTotalOnly(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bReturnTotalOnly); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetReturnPlaytimeStats", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetReturnPlaytimeStats(IntPtr instancePtr, UGCQueryHandle_t handle, uint unDays); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetLanguage", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetLanguage(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pchLanguage); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetAllowCachedResponse", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetAllowCachedResponse(IntPtr instancePtr, UGCQueryHandle_t handle, uint unMaxAgeSeconds); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetCloudFileNameFilter", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetCloudFileNameFilter(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pMatchCloudFileName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetMatchAnyTag", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetMatchAnyTag(IntPtr instancePtr, UGCQueryHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bMatchAnyTag); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetSearchText", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetSearchText(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pSearchText); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetRankedByTrendDays", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetRankedByTrendDays(IntPtr instancePtr, UGCQueryHandle_t handle, uint unDays); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetTimeCreatedDateRange", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetTimeCreatedDateRange(IntPtr instancePtr, UGCQueryHandle_t handle, uint rtStart, uint rtEnd); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetTimeUpdatedDateRange", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetTimeUpdatedDateRange(IntPtr instancePtr, UGCQueryHandle_t handle, uint rtStart, uint rtEnd); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddRequiredKeyValueTag", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_AddRequiredKeyValueTag(IntPtr instancePtr, UGCQueryHandle_t handle, InteropHelp.UTF8StringHandle pKey, InteropHelp.UTF8StringHandle pValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_RequestUGCDetails", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_RequestUGCDetails(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, uint unMaxAgeSeconds); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_CreateItem", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_CreateItem(IntPtr instancePtr, AppId_t nConsumerAppId, EWorkshopFileType eFileType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_StartItemUpdate", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_StartItemUpdate(IntPtr instancePtr, AppId_t nConsumerAppId, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetItemTitle", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetItemTitle(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchTitle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetItemDescription", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetItemDescription(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchDescription); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetItemUpdateLanguage", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetItemUpdateLanguage(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchLanguage); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetItemMetadata", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetItemMetadata(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchMetaData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetItemVisibility", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetItemVisibility(IntPtr instancePtr, UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility eVisibility); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetItemTags", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetItemTags(IntPtr instancePtr, UGCUpdateHandle_t updateHandle, IntPtr pTags); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetItemContent", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetItemContent(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pszContentFolder); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetItemPreview", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetItemPreview(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pszPreviewFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetAllowLegacyUpload", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_SetAllowLegacyUpload(IntPtr instancePtr, UGCUpdateHandle_t handle, [MarshalAs(UnmanagedType.I1)] bool bAllowLegacyUpload); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_RemoveAllItemKeyValueTags", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_RemoveAllItemKeyValueTags(IntPtr instancePtr, UGCUpdateHandle_t handle); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_RemoveItemKeyValueTags", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_RemoveItemKeyValueTags(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddItemKeyValueTag", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_AddItemKeyValueTag(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchKey, InteropHelp.UTF8StringHandle pchValue); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddItemPreviewFile", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_AddItemPreviewFile(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pszPreviewFile, EItemPreviewType type); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddItemPreviewVideo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_AddItemPreviewVideo(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pszVideoID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_UpdateItemPreviewFile", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_UpdateItemPreviewFile(IntPtr instancePtr, UGCUpdateHandle_t handle, uint index, InteropHelp.UTF8StringHandle pszPreviewFile); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_UpdateItemPreviewVideo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_UpdateItemPreviewVideo(IntPtr instancePtr, UGCUpdateHandle_t handle, uint index, InteropHelp.UTF8StringHandle pszVideoID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_RemoveItemPreview", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_RemoveItemPreview(IntPtr instancePtr, UGCUpdateHandle_t handle, uint index); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddContentDescriptor", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_AddContentDescriptor(IntPtr instancePtr, UGCUpdateHandle_t handle, EUGCContentDescriptorID descid); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_RemoveContentDescriptor", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_RemoveContentDescriptor(IntPtr instancePtr, UGCUpdateHandle_t handle, EUGCContentDescriptorID descid); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SubmitItemUpdate", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_SubmitItemUpdate(IntPtr instancePtr, UGCUpdateHandle_t handle, InteropHelp.UTF8StringHandle pchChangeNote); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetItemUpdateProgress", CallingConvention = CallingConvention.Cdecl)] + public static extern EItemUpdateStatus ISteamUGC_GetItemUpdateProgress(IntPtr instancePtr, UGCUpdateHandle_t handle, out ulong punBytesProcessed, out ulong punBytesTotal); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SetUserItemVote", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_SetUserItemVote(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, [MarshalAs(UnmanagedType.I1)] bool bVoteUp); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetUserItemVote", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_GetUserItemVote(IntPtr instancePtr, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddItemToFavorites", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_AddItemToFavorites(IntPtr instancePtr, AppId_t nAppId, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_RemoveItemFromFavorites", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_RemoveItemFromFavorites(IntPtr instancePtr, AppId_t nAppId, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SubscribeItem", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_SubscribeItem(IntPtr instancePtr, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_UnsubscribeItem", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_UnsubscribeItem(IntPtr instancePtr, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetNumSubscribedItems", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUGC_GetNumSubscribedItems(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetSubscribedItems", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUGC_GetSubscribedItems(IntPtr instancePtr, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetItemState", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUGC_GetItemState(IntPtr instancePtr, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetItemInstallInfo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetItemInstallInfo(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, out ulong punSizeOnDisk, IntPtr pchFolder, uint cchFolderSize, out uint punTimeStamp); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetItemDownloadInfo", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_GetItemDownloadInfo(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, out ulong punBytesDownloaded, out ulong punBytesTotal); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_DownloadItem", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_DownloadItem(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, [MarshalAs(UnmanagedType.I1)] bool bHighPriority); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_BInitWorkshopForGameServer", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_BInitWorkshopForGameServer(IntPtr instancePtr, DepotId_t unWorkshopDepotID, InteropHelp.UTF8StringHandle pszFolder); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_SuspendDownloads", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUGC_SuspendDownloads(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bSuspend); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_StartPlaytimeTracking", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_StartPlaytimeTracking(IntPtr instancePtr, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_StopPlaytimeTracking", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_StopPlaytimeTracking(IntPtr instancePtr, [In, Out] PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_StopPlaytimeTrackingForAllItems", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_StopPlaytimeTrackingForAllItems(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddDependency", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_AddDependency(IntPtr instancePtr, PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_RemoveDependency", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_RemoveDependency(IntPtr instancePtr, PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_AddAppDependency", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_AddAppDependency(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, AppId_t nAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_RemoveAppDependency", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_RemoveAppDependency(IntPtr instancePtr, PublishedFileId_t nPublishedFileID, AppId_t nAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetAppDependencies", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_GetAppDependencies(IntPtr instancePtr, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_DeleteItem", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_DeleteItem(IntPtr instancePtr, PublishedFileId_t nPublishedFileID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_ShowWorkshopEULA", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUGC_ShowWorkshopEULA(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUGC_GetWorkshopEULAStatus", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUGC_GetWorkshopEULAStatus(IntPtr instancePtr); +#endregion +#region SteamUser + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetHSteamUser", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUser_GetHSteamUser(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_BLoggedOn", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_BLoggedOn(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetSteamID", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUser_GetSteamID(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_InitiateGameConnection_DEPRECATED", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUser_InitiateGameConnection_DEPRECATED(IntPtr instancePtr, byte[] pAuthBlob, int cbMaxAuthBlob, CSteamID steamIDGameServer, uint unIPServer, ushort usPortServer, [MarshalAs(UnmanagedType.I1)] bool bSecure); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_TerminateGameConnection_DEPRECATED", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUser_TerminateGameConnection_DEPRECATED(IntPtr instancePtr, uint unIPServer, ushort usPortServer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_TrackAppUsageEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUser_TrackAppUsageEvent(IntPtr instancePtr, CGameID gameID, int eAppUsageEvent, InteropHelp.UTF8StringHandle pchExtraInfo); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetUserDataFolder", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_GetUserDataFolder(IntPtr instancePtr, IntPtr pchBuffer, int cubBuffer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_StartVoiceRecording", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUser_StartVoiceRecording(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_StopVoiceRecording", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUser_StopVoiceRecording(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetAvailableVoice", CallingConvention = CallingConvention.Cdecl)] + public static extern EVoiceResult ISteamUser_GetAvailableVoice(IntPtr instancePtr, out uint pcbCompressed, IntPtr pcbUncompressed_Deprecated, uint nUncompressedVoiceDesiredSampleRate_Deprecated); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetVoice", CallingConvention = CallingConvention.Cdecl)] + public static extern EVoiceResult ISteamUser_GetVoice(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bWantCompressed, byte[] pDestBuffer, uint cbDestBufferSize, out uint nBytesWritten, [MarshalAs(UnmanagedType.I1)] bool bWantUncompressed_Deprecated, IntPtr pUncompressedDestBuffer_Deprecated, uint cbUncompressedDestBufferSize_Deprecated, IntPtr nUncompressBytesWritten_Deprecated, uint nUncompressedVoiceDesiredSampleRate_Deprecated); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_DecompressVoice", CallingConvention = CallingConvention.Cdecl)] + public static extern EVoiceResult ISteamUser_DecompressVoice(IntPtr instancePtr, byte[] pCompressed, uint cbCompressed, byte[] pDestBuffer, uint cbDestBufferSize, out uint nBytesWritten, uint nDesiredSampleRate); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetVoiceOptimalSampleRate", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUser_GetVoiceOptimalSampleRate(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetAuthSessionTicket", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUser_GetAuthSessionTicket(IntPtr instancePtr, byte[] pTicket, int cbMaxTicket, out uint pcbTicket, ref SteamNetworkingIdentity pSteamNetworkingIdentity); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetAuthTicketForWebApi", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUser_GetAuthTicketForWebApi(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchIdentity); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_BeginAuthSession", CallingConvention = CallingConvention.Cdecl)] + public static extern EBeginAuthSessionResult ISteamUser_BeginAuthSession(IntPtr instancePtr, byte[] pAuthTicket, int cbAuthTicket, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_EndAuthSession", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUser_EndAuthSession(IntPtr instancePtr, CSteamID steamID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_CancelAuthTicket", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUser_CancelAuthTicket(IntPtr instancePtr, HAuthTicket hAuthTicket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_UserHasLicenseForApp", CallingConvention = CallingConvention.Cdecl)] + public static extern EUserHasLicenseForAppResult ISteamUser_UserHasLicenseForApp(IntPtr instancePtr, CSteamID steamID, AppId_t appID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_BIsBehindNAT", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_BIsBehindNAT(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_AdvertiseGame", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUser_AdvertiseGame(IntPtr instancePtr, CSteamID steamIDGameServer, uint unIPServer, ushort usPortServer); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_RequestEncryptedAppTicket", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUser_RequestEncryptedAppTicket(IntPtr instancePtr, byte[] pDataToInclude, int cbDataToInclude); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetEncryptedAppTicket", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_GetEncryptedAppTicket(IntPtr instancePtr, byte[] pTicket, int cbMaxTicket, out uint pcbTicket); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetGameBadgeLevel", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUser_GetGameBadgeLevel(IntPtr instancePtr, int nSeries, [MarshalAs(UnmanagedType.I1)] bool bFoil); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetPlayerSteamLevel", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUser_GetPlayerSteamLevel(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_RequestStoreAuthURL", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUser_RequestStoreAuthURL(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchRedirectURL); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_BIsPhoneVerified", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_BIsPhoneVerified(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_BIsTwoFactorEnabled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_BIsTwoFactorEnabled(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_BIsPhoneIdentifying", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_BIsPhoneIdentifying(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_BIsPhoneRequiringVerification", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_BIsPhoneRequiringVerification(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetMarketEligibility", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUser_GetMarketEligibility(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_GetDurationControl", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUser_GetDurationControl(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUser_BSetDurationControlOnlineState", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUser_BSetDurationControlOnlineState(IntPtr instancePtr, EDurationControlOnlineState eNewState); +#endregion +#region SteamUserStats + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_RequestCurrentStats", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_RequestCurrentStats(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetStatInt32", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetStatInt32(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out int pData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetStatFloat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetStatFloat(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out float pData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_SetStatInt32", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_SetStatInt32(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, int nData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_SetStatFloat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_SetStatFloat(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, float fData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_UpdateAvgRateStat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_UpdateAvgRateStat(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, float flCountThisSession, double dSessionLength); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetAchievement", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetAchievement(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_SetAchievement", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_SetAchievement(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_ClearAchievement", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_ClearAchievement(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetAchievementAndUnlockTime", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetAchievementAndUnlockTime(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved, out uint punUnlockTime); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_StoreStats", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_StoreStats(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetAchievementIcon", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUserStats_GetAchievementIcon(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamUserStats_GetAchievementDisplayAttribute(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, InteropHelp.UTF8StringHandle pchKey); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_IndicateAchievementProgress", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_IndicateAchievementProgress(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, uint nCurProgress, uint nMaxProgress); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetNumAchievements", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUserStats_GetNumAchievements(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetAchievementName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamUserStats_GetAchievementName(IntPtr instancePtr, uint iAchievement); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_RequestUserStats", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_RequestUserStats(IntPtr instancePtr, CSteamID steamIDUser); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetUserStatInt32", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetUserStatInt32(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out int pData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetUserStatFloat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetUserStatFloat(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out float pData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetUserAchievement", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetUserAchievement(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetUserAchievementAndUnlockTime", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetUserAchievementAndUnlockTime(IntPtr instancePtr, CSteamID steamIDUser, InteropHelp.UTF8StringHandle pchName, out bool pbAchieved, out uint punUnlockTime); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_ResetAllStats", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_ResetAllStats(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bAchievementsToo); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_FindOrCreateLeaderboard", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_FindOrCreateLeaderboard(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchLeaderboardName, ELeaderboardSortMethod eLeaderboardSortMethod, ELeaderboardDisplayType eLeaderboardDisplayType); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_FindLeaderboard", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_FindLeaderboard(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchLeaderboardName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetLeaderboardName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamUserStats_GetLeaderboardName(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetLeaderboardEntryCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUserStats_GetLeaderboardEntryCount(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetLeaderboardSortMethod", CallingConvention = CallingConvention.Cdecl)] + public static extern ELeaderboardSortMethod ISteamUserStats_GetLeaderboardSortMethod(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetLeaderboardDisplayType", CallingConvention = CallingConvention.Cdecl)] + public static extern ELeaderboardDisplayType ISteamUserStats_GetLeaderboardDisplayType(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_DownloadLeaderboardEntries", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_DownloadLeaderboardEntries(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard, ELeaderboardDataRequest eLeaderboardDataRequest, int nRangeStart, int nRangeEnd); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_DownloadLeaderboardEntriesForUsers", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_DownloadLeaderboardEntriesForUsers(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard, [In, Out] CSteamID[] prgUsers, int cUsers); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetDownloadedLeaderboardEntry", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetDownloadedLeaderboardEntry(IntPtr instancePtr, SteamLeaderboardEntries_t hSteamLeaderboardEntries, int index, out LeaderboardEntry_t pLeaderboardEntry, [In, Out] int[] pDetails, int cDetailsMax); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_UploadLeaderboardScore", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_UploadLeaderboardScore(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard, ELeaderboardUploadScoreMethod eLeaderboardUploadScoreMethod, int nScore, [In, Out] int[] pScoreDetails, int cScoreDetailsCount); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_AttachLeaderboardUGC", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_AttachLeaderboardUGC(IntPtr instancePtr, SteamLeaderboard_t hSteamLeaderboard, UGCHandle_t hUGC); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetNumberOfCurrentPlayers", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_GetNumberOfCurrentPlayers(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_RequestGlobalAchievementPercentages", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_RequestGlobalAchievementPercentages(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetMostAchievedAchievementInfo", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUserStats_GetMostAchievedAchievementInfo(IntPtr instancePtr, IntPtr pchName, uint unNameBufLen, out float pflPercent, out bool pbAchieved); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetNextMostAchievedAchievementInfo", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUserStats_GetNextMostAchievedAchievementInfo(IntPtr instancePtr, int iIteratorPrevious, IntPtr pchName, uint unNameBufLen, out float pflPercent, out bool pbAchieved); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetAchievementAchievedPercent", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetAchievementAchievedPercent(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out float pflPercent); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_RequestGlobalStats", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUserStats_RequestGlobalStats(IntPtr instancePtr, int nHistoryDays); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetGlobalStatInt64", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetGlobalStatInt64(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchStatName, out long pData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetGlobalStatDouble", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetGlobalStatDouble(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchStatName, out double pData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetGlobalStatHistoryInt64", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUserStats_GetGlobalStatHistoryInt64(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchStatName, [In, Out] long[] pData, uint cubData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetGlobalStatHistoryDouble", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUserStats_GetGlobalStatHistoryDouble(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchStatName, [In, Out] double[] pData, uint cubData); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetAchievementProgressLimitsInt32", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetAchievementProgressLimitsInt32(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out int pnMinProgress, out int pnMaxProgress); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUserStats_GetAchievementProgressLimitsFloat", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUserStats_GetAchievementProgressLimitsFloat(IntPtr instancePtr, InteropHelp.UTF8StringHandle pchName, out float pfMinProgress, out float pfMaxProgress); +#endregion +#region SteamUtils + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetSecondsSinceAppActive", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUtils_GetSecondsSinceAppActive(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetSecondsSinceComputerActive", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUtils_GetSecondsSinceComputerActive(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetConnectedUniverse", CallingConvention = CallingConvention.Cdecl)] + public static extern EUniverse ISteamUtils_GetConnectedUniverse(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetServerRealTime", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUtils_GetServerRealTime(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetIPCountry", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamUtils_GetIPCountry(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetImageSize", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_GetImageSize(IntPtr instancePtr, int iImage, out uint pnWidth, out uint pnHeight); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetImageRGBA", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_GetImageRGBA(IntPtr instancePtr, int iImage, byte[] pubDest, int nDestBufferSize); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetCurrentBatteryPower", CallingConvention = CallingConvention.Cdecl)] + public static extern byte ISteamUtils_GetCurrentBatteryPower(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetAppID", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUtils_GetAppID(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_SetOverlayNotificationPosition", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUtils_SetOverlayNotificationPosition(IntPtr instancePtr, ENotificationPosition eNotificationPosition); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_IsAPICallCompleted", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_IsAPICallCompleted(IntPtr instancePtr, SteamAPICall_t hSteamAPICall, out bool pbFailed); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetAPICallFailureReason", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamAPICallFailure ISteamUtils_GetAPICallFailureReason(IntPtr instancePtr, SteamAPICall_t hSteamAPICall); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetAPICallResult", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_GetAPICallResult(IntPtr instancePtr, SteamAPICall_t hSteamAPICall, IntPtr pCallback, int cubCallback, int iCallbackExpected, out bool pbFailed); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetIPCCallCount", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUtils_GetIPCCallCount(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_SetWarningMessageHook", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUtils_SetWarningMessageHook(IntPtr instancePtr, SteamAPIWarningMessageHook_t pFunction); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_IsOverlayEnabled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_IsOverlayEnabled(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_BOverlayNeedsPresent", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_BOverlayNeedsPresent(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_CheckFileSignature", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ISteamUtils_CheckFileSignature(IntPtr instancePtr, InteropHelp.UTF8StringHandle szFileName); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_ShowGamepadTextInput", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_ShowGamepadTextInput(IntPtr instancePtr, EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, InteropHelp.UTF8StringHandle pchDescription, uint unCharMax, InteropHelp.UTF8StringHandle pchExistingText); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetEnteredGamepadTextLength", CallingConvention = CallingConvention.Cdecl)] + public static extern uint ISteamUtils_GetEnteredGamepadTextLength(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetEnteredGamepadTextInput", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_GetEnteredGamepadTextInput(IntPtr instancePtr, IntPtr pchText, uint cchText); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetSteamUILanguage", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ISteamUtils_GetSteamUILanguage(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_IsSteamRunningInVR", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_IsSteamRunningInVR(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_SetOverlayNotificationInset", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUtils_SetOverlayNotificationInset(IntPtr instancePtr, int nHorizontalInset, int nVerticalInset); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_IsSteamInBigPictureMode", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_IsSteamInBigPictureMode(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_StartVRDashboard", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUtils_StartVRDashboard(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_IsVRHeadsetStreamingEnabled", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_IsVRHeadsetStreamingEnabled(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_SetVRHeadsetStreamingEnabled", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUtils_SetVRHeadsetStreamingEnabled(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bEnabled); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_IsSteamChinaLauncher", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_IsSteamChinaLauncher(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_InitFilterText", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_InitFilterText(IntPtr instancePtr, uint unFilterOptions); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_FilterText", CallingConvention = CallingConvention.Cdecl)] + public static extern int ISteamUtils_FilterText(IntPtr instancePtr, ETextFilteringContext eContext, CSteamID sourceSteamID, InteropHelp.UTF8StringHandle pchInputMessage, IntPtr pchOutFilteredText, uint nByteSizeOutFilteredText); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_GetIPv6ConnectivityState", CallingConvention = CallingConvention.Cdecl)] + public static extern ESteamIPv6ConnectivityState ISteamUtils_GetIPv6ConnectivityState(IntPtr instancePtr, ESteamIPv6ConnectivityProtocol eProtocol); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_IsSteamRunningOnSteamDeck", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_IsSteamRunningOnSteamDeck(IntPtr instancePtr); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_ShowFloatingGamepadTextInput", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_ShowFloatingGamepadTextInput(IntPtr instancePtr, EFloatingGamepadTextInputMode eKeyboardMode, int nTextFieldXPosition, int nTextFieldYPosition, int nTextFieldWidth, int nTextFieldHeight); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_SetGameLauncherMode", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamUtils_SetGameLauncherMode(IntPtr instancePtr, [MarshalAs(UnmanagedType.I1)] bool bLauncherMode); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamUtils_DismissFloatingGamepadTextInput", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamUtils_DismissFloatingGamepadTextInput(IntPtr instancePtr); +#endregion +#region SteamVideo + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamVideo_GetVideoURL", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamVideo_GetVideoURL(IntPtr instancePtr, AppId_t unVideoAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamVideo_IsBroadcasting", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamVideo_IsBroadcasting(IntPtr instancePtr, out int pnNumViewers); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamVideo_GetOPFSettings", CallingConvention = CallingConvention.Cdecl)] + public static extern void ISteamVideo_GetOPFSettings(IntPtr instancePtr, AppId_t unVideoAppID); + + [DllImport(NativeLibraryName, EntryPoint = "SteamAPI_ISteamVideo_GetOPFStringForApp", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool ISteamVideo_GetOPFStringForApp(IntPtr instancePtr, AppId_t unVideoAppID, IntPtr pchBuffer, ref int pnBufferSize); +#endregion + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs.meta new file mode 100644 index 0000000..bca9941 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 34b11825d034447449147528ae7c6201 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamCallbacks.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamCallbacks.cs new file mode 100644 index 0000000..d26a33f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamCallbacks.cs @@ -0,0 +1,2939 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + // callbacks + //--------------------------------------------------------------------------------- + // Purpose: Sent when a new app is installed (not downloaded yet) + //--------------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamAppListCallbacks + 1)] + public struct SteamAppInstalled_t { + public const int k_iCallback = Constants.k_iSteamAppListCallbacks + 1; + public AppId_t m_nAppID; // ID of the app that installs + public int m_iInstallFolderIndex; // library folder the app is installed + } + + //--------------------------------------------------------------------------------- + // Purpose: Sent when an app is uninstalled + //--------------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamAppListCallbacks + 2)] + public struct SteamAppUninstalled_t { + public const int k_iCallback = Constants.k_iSteamAppListCallbacks + 2; + public AppId_t m_nAppID; // ID of the app that installs + public int m_iInstallFolderIndex; // library folder the app was installed + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: posted after the user gains ownership of DLC & that DLC is installed + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamAppsCallbacks + 5)] + public struct DlcInstalled_t { + public const int k_iCallback = Constants.k_iSteamAppsCallbacks + 5; + public AppId_t m_nAppID; // AppID of the DLC + } + + //--------------------------------------------------------------------------------- + // Purpose: posted after the user gains executes a Steam URL with command line or query parameters + // such as steam://run///-commandline/?param1=value1¶m2=value2¶m3=value3 etc + // while the game is already running. The new params can be queried + // with GetLaunchQueryParam and GetLaunchCommandLine + //--------------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamAppsCallbacks + 14)] + public struct NewUrlLaunchParameters_t { + public const int k_iCallback = Constants.k_iSteamAppsCallbacks + 14; + } + + //----------------------------------------------------------------------------- + // Purpose: response to RequestAppProofOfPurchaseKey/RequestAllProofOfPurchaseKeys + // for supporting third-party CD keys, or other proof-of-purchase systems. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamAppsCallbacks + 21)] + public struct AppProofOfPurchaseKeyResponse_t { + public const int k_iCallback = Constants.k_iSteamAppsCallbacks + 21; + public EResult m_eResult; + public uint m_nAppID; + public uint m_cchKeyLength; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cubAppProofOfPurchaseKeyMax)] + private byte[] m_rgchKey_; + public string m_rgchKey + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchKey_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchKey_, Constants.k_cubAppProofOfPurchaseKeyMax); } + } + } + + //----------------------------------------------------------------------------- + // Purpose: response to GetFileDetails + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamAppsCallbacks + 23)] + public struct FileDetailsResult_t { + public const int k_iCallback = Constants.k_iSteamAppsCallbacks + 23; + public EResult m_eResult; + public ulong m_ulFileSize; // original file size in bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + public byte[] m_FileSHA; // original file SHA1 hash + public uint m_unFlags; // + } + + //----------------------------------------------------------------------------- + // Purpose: called for games in Timed Trial mode + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamAppsCallbacks + 30)] + public struct TimedTrialStatus_t { + public const int k_iCallback = Constants.k_iSteamAppsCallbacks + 30; + public AppId_t m_unAppID; // appID + [MarshalAs(UnmanagedType.I1)] + public bool m_bIsOffline; // if true, time allowed / played refers to offline time, not total time + public uint m_unSecondsAllowed; // how many seconds the app can be played in total + public uint m_unSecondsPlayed; // how many seconds the app was already played + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: called when a friends' status changes + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 4)] + public struct PersonaStateChange_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 4; + + public ulong m_ulSteamID; // steamID of the friend who changed + public EPersonaChange m_nChangeFlags; // what's changed + } + + //----------------------------------------------------------------------------- + // Purpose: posted when game overlay activates or deactivates + // the game can use this to be pause or resume single player games + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 31)] + public struct GameOverlayActivated_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 31; + public byte m_bActive; // true if it's just been activated, false otherwise + [MarshalAs(UnmanagedType.I1)] + public bool m_bUserInitiated; // true if the user asked for the overlay to be activated/deactivated + public AppId_t m_nAppID; // the appID of the game (should always be the current game) + } + + //----------------------------------------------------------------------------- + // Purpose: called when the user tries to join a different game server from their friends list + // game client should attempt to connect to specified server when this is received + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 32)] + public struct GameServerChangeRequested_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 32; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + private byte[] m_rgchServer_; + public string m_rgchServer // server address ("127.0.0.1:27015", "tf2.valvesoftware.com") + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchServer_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchServer_, 64); } + } + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + private byte[] m_rgchPassword_; + public string m_rgchPassword // server password, if any + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchPassword_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchPassword_, 64); } + } + } + + //----------------------------------------------------------------------------- + // Purpose: called when the user tries to join a lobby from their friends list + // game client should attempt to connect to specified lobby when this is received + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 33)] + public struct GameLobbyJoinRequested_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 33; + public CSteamID m_steamIDLobby; + + // The friend they did the join via (will be invalid if not directly via a friend) + // + // On PS3, the friend will be invalid if this was triggered by a PSN invite via the XMB, but + // the account type will be console user so you can tell at least that this was from a PSN friend + // rather than a Steam friend. + public CSteamID m_steamIDFriend; + } + + //----------------------------------------------------------------------------- + // Purpose: called when an avatar is loaded in from a previous GetLargeFriendAvatar() call + // if the image wasn't already available + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 34)] + public struct AvatarImageLoaded_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 34; + public CSteamID m_steamID; // steamid the avatar has been loaded for + public int m_iImage; // the image index of the now loaded image + public int m_iWide; // width of the loaded image + public int m_iTall; // height of the loaded image + } + + //----------------------------------------------------------------------------- + // Purpose: marks the return of a request officer list call + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 35)] + public struct ClanOfficerListResponse_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 35; + public CSteamID m_steamIDClan; + public int m_cOfficers; + public byte m_bSuccess; + } + + //----------------------------------------------------------------------------- + // Purpose: callback indicating updated data about friends rich presence information + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 36)] + public struct FriendRichPresenceUpdate_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 36; + public CSteamID m_steamIDFriend; // friend who's rich presence has changed + public AppId_t m_nAppID; // the appID of the game (should always be the current game) + } + + //----------------------------------------------------------------------------- + // Purpose: called when the user tries to join a game from their friends list + // rich presence will have been set with the "connect" key which is set here + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 37)] + public struct GameRichPresenceJoinRequested_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 37; + public CSteamID m_steamIDFriend; // the friend they did the join via (will be invalid if not directly via a friend) + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchMaxRichPresenceValueLength)] + private byte[] m_rgchConnect_; + public string m_rgchConnect + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchConnect_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchConnect_, Constants.k_cchMaxRichPresenceValueLength); } + } + } + + //----------------------------------------------------------------------------- + // Purpose: a chat message has been received for a clan chat the game has joined + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 38)] + public struct GameConnectedClanChatMsg_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 38; + public CSteamID m_steamIDClanChat; + public CSteamID m_steamIDUser; + public int m_iMessageID; + } + + //----------------------------------------------------------------------------- + // Purpose: a user has joined a clan chat + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 39)] + public struct GameConnectedChatJoin_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 39; + public CSteamID m_steamIDClanChat; + public CSteamID m_steamIDUser; + } + + //----------------------------------------------------------------------------- + // Purpose: a user has left the chat we're in + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 40)] + public struct GameConnectedChatLeave_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 40; + public CSteamID m_steamIDClanChat; + public CSteamID m_steamIDUser; + [MarshalAs(UnmanagedType.I1)] + public bool m_bKicked; // true if admin kicked + [MarshalAs(UnmanagedType.I1)] + public bool m_bDropped; // true if Steam connection dropped + } + + //----------------------------------------------------------------------------- + // Purpose: a DownloadClanActivityCounts() call has finished + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 41)] + public struct DownloadClanActivityCountsResult_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 41; + [MarshalAs(UnmanagedType.I1)] + public bool m_bSuccess; + } + + //----------------------------------------------------------------------------- + // Purpose: a JoinClanChatRoom() call has finished + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 42)] + public struct JoinClanChatRoomCompletionResult_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 42; + public CSteamID m_steamIDClanChat; + public EChatRoomEnterResponse m_eChatRoomEnterResponse; + } + + //----------------------------------------------------------------------------- + // Purpose: a chat message has been received from a user + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 43)] + public struct GameConnectedFriendChatMsg_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 43; + public CSteamID m_steamIDUser; + public int m_iMessageID; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 44)] + public struct FriendsGetFollowerCount_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 44; + public EResult m_eResult; + public CSteamID m_steamID; + public int m_nCount; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 45)] + public struct FriendsIsFollowing_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 45; + public EResult m_eResult; + public CSteamID m_steamID; + [MarshalAs(UnmanagedType.I1)] + public bool m_bIsFollowing; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 46)] + public struct FriendsEnumerateFollowingList_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 46; + public EResult m_eResult; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cEnumerateFollowersMax)] + public CSteamID[] m_rgSteamID; + public int m_nResultsReturned; + public int m_nTotalResultCount; + } + + //----------------------------------------------------------------------------- + // Purpose: reports the result of an attempt to change the user's persona name + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 47)] + public struct SetPersonaNameResponse_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 47; + + [MarshalAs(UnmanagedType.I1)] + public bool m_bSuccess; // true if name change succeeded completely. + [MarshalAs(UnmanagedType.I1)] + public bool m_bLocalSuccess; // true if name change was retained locally. (We might not have been able to communicate with Steam) + public EResult m_result; // detailed result code + } + + //----------------------------------------------------------------------------- + // Purpose: Invoked when the status of unread messages changes + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 48)] + public struct UnreadChatMessagesChanged_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 48; + } + + //----------------------------------------------------------------------------- + // Purpose: Dispatched when an overlay browser instance is navigated to a protocol/scheme registered by RegisterProtocolInOverlayBrowser() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 49)] + public struct OverlayBrowserProtocolNavigation_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 49; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] + private byte[] rgchURI_; + public string rgchURI + { + get { return InteropHelp.ByteArrayToStringUTF8(rgchURI_); } + set { InteropHelp.StringToByteArrayUTF8(value, rgchURI_, 1024); } + } + } + + //----------------------------------------------------------------------------- + // Purpose: A user's equipped profile items have changed + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 50)] + public struct EquippedProfileItemsChanged_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 50; + public CSteamID m_steamID; + } + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 51)] + public struct EquippedProfileItems_t { + public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 51; + public EResult m_eResult; + public CSteamID m_steamID; + [MarshalAs(UnmanagedType.I1)] + public bool m_bHasAnimatedAvatar; + [MarshalAs(UnmanagedType.I1)] + public bool m_bHasAvatarFrame; + [MarshalAs(UnmanagedType.I1)] + public bool m_bHasProfileModifier; + [MarshalAs(UnmanagedType.I1)] + public bool m_bHasProfileBackground; + [MarshalAs(UnmanagedType.I1)] + public bool m_bHasMiniProfileBackground; + } + + // callbacks + // callback notification - A new message is available for reading from the message queue + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameCoordinatorCallbacks + 1)] + public struct GCMessageAvailable_t { + public const int k_iCallback = Constants.k_iSteamGameCoordinatorCallbacks + 1; + public uint m_nMessageSize; + } + + // callback notification - A message failed to make it to the GC. It may be down temporarily + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamGameCoordinatorCallbacks + 2)] + public struct GCMessageFailed_t { + public const int k_iCallback = Constants.k_iSteamGameCoordinatorCallbacks + 2; + } + + // callbacks + // client has been approved to connect to this game server + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 1)] + public struct GSClientApprove_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 1; + public CSteamID m_SteamID; // SteamID of approved player + public CSteamID m_OwnerSteamID; // SteamID of original owner for game license + } + + // client has been denied to connection to this game server + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 2)] + public struct GSClientDeny_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 2; + public CSteamID m_SteamID; + public EDenyReason m_eDenyReason; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + private byte[] m_rgchOptionalText_; + public string m_rgchOptionalText + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchOptionalText_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchOptionalText_, 128); } + } + } + + // request the game server should kick the user + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 3)] + public struct GSClientKick_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 3; + public CSteamID m_SteamID; + public EDenyReason m_eDenyReason; + } + + // NOTE: callback values 4 and 5 are skipped because they are used for old deprecated callbacks, + // do not reuse them here. + // client achievement info + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 6)] + public struct GSClientAchievementStatus_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 6; + public ulong m_SteamID; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + private byte[] m_pchAchievement_; + public string m_pchAchievement + { + get { return InteropHelp.ByteArrayToStringUTF8(m_pchAchievement_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_pchAchievement_, 128); } + } + [MarshalAs(UnmanagedType.I1)] + public bool m_bUnlocked; + } + + // received when the game server requests to be displayed as secure (VAC protected) + // m_bSecure is true if the game server should display itself as secure to users, false otherwise + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 15)] + public struct GSPolicyResponse_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 15; + public byte m_bSecure; + } + + // GS gameplay stats info + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 7)] + public struct GSGameplayStats_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 7; + public EResult m_eResult; // Result of the call + public int m_nRank; // Overall rank of the server (0-based) + public uint m_unTotalConnects; // Total number of clients who have ever connected to the server + public uint m_unTotalMinutesPlayed; // Total number of minutes ever played on the server + } + + // send as a reply to RequestUserGroupStatus() + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 8)] + public struct GSClientGroupStatus_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 8; + public CSteamID m_SteamIDUser; + public CSteamID m_SteamIDGroup; + [MarshalAs(UnmanagedType.I1)] + public bool m_bMember; + [MarshalAs(UnmanagedType.I1)] + public bool m_bOfficer; + } + + // Sent as a reply to GetServerReputation() + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 9)] + public struct GSReputation_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 9; + public EResult m_eResult; // Result of the call; + public uint m_unReputationScore; // The reputation score for the game server + [MarshalAs(UnmanagedType.I1)] + public bool m_bBanned; // True if the server is banned from the Steam + // master servers + + // The following members are only filled out if m_bBanned is true. They will all + // be set to zero otherwise. Master server bans are by IP so it is possible to be + // banned even when the score is good high if there is a bad server on another port. + // This information can be used to determine which server is bad. + + public uint m_unBannedIP; // The IP of the banned server + public ushort m_usBannedPort; // The port of the banned server + public ulong m_ulBannedGameID; // The game ID the banned server is serving + public uint m_unBanExpires; // Time the ban expires, expressed in the Unix epoch (seconds since 1/1/1970) + } + + // Sent as a reply to AssociateWithClan() + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 10)] + public struct AssociateWithClanResult_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 10; + public EResult m_eResult; // Result of the call; + } + + // Sent as a reply to ComputeNewPlayerCompatibility() + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameServerCallbacks + 11)] + public struct ComputeNewPlayerCompatibilityResult_t { + public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 11; + public EResult m_eResult; // Result of the call; + public int m_cPlayersThatDontLikeCandidate; + public int m_cPlayersThatCandidateDoesntLike; + public int m_cClanPlayersThatDontLikeCandidate; + public CSteamID m_SteamIDCandidate; + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: called when the latests stats and achievements have been received + // from the server + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamGameServerStatsCallbacks)] + public struct GSStatsReceived_t { + public const int k_iCallback = Constants.k_iSteamGameServerStatsCallbacks; + public EResult m_eResult; // Success / error fetching the stats + public CSteamID m_steamIDUser; // The user for whom the stats are retrieved for + } + + //----------------------------------------------------------------------------- + // Purpose: result of a request to store the user stats for a game + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamGameServerStatsCallbacks + 1)] + public struct GSStatsStored_t { + public const int k_iCallback = Constants.k_iSteamGameServerStatsCallbacks + 1; + public EResult m_eResult; // success / error + public CSteamID m_steamIDUser; // The user for whom the stats were stored + } + + //----------------------------------------------------------------------------- + // Purpose: Callback indicating that a user's stats have been unloaded. + // Call RequestUserStats again to access stats for this user + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 8)] + public struct GSStatsUnloaded_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 8; + public CSteamID m_steamIDUser; // User whose stats have been unloaded + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: The browser is ready for use + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 1)] + public struct HTML_BrowserReady_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 1; + public HHTMLBrowser unBrowserHandle; // this browser is now fully created and ready to navigate to pages + } + + //----------------------------------------------------------------------------- + // Purpose: the browser has a pending paint + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 2)] + public struct HTML_NeedsPaint_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 2; + public HHTMLBrowser unBrowserHandle; // the browser that needs the paint + public IntPtr pBGRA; // a pointer to the B8G8R8A8 data for this surface, valid until SteamAPI_RunCallbacks is next called + public uint unWide; // the total width of the pBGRA texture + public uint unTall; // the total height of the pBGRA texture + public uint unUpdateX; // the offset in X for the damage rect for this update + public uint unUpdateY; // the offset in Y for the damage rect for this update + public uint unUpdateWide; // the width of the damage rect for this update + public uint unUpdateTall; // the height of the damage rect for this update + public uint unScrollX; // the page scroll the browser was at when this texture was rendered + public uint unScrollY; // the page scroll the browser was at when this texture was rendered + public float flPageScale; // the page scale factor on this page when rendered + public uint unPageSerial; // incremented on each new page load, you can use this to reject draws while navigating to new pages + } + + //----------------------------------------------------------------------------- + // Purpose: The browser wanted to navigate to a new page + // NOTE - you MUST call AllowStartRequest in response to this callback + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 3)] + public struct HTML_StartRequest_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 3; + public HHTMLBrowser unBrowserHandle; // the handle of the surface navigating + public string pchURL; // the url they wish to navigate to + public string pchTarget; // the html link target type (i.e _blank, _self, _parent, _top ) + public string pchPostData; // any posted data for the request + [MarshalAs(UnmanagedType.I1)] + public bool bIsRedirect; // true if this was a http/html redirect from the last load request + } + + //----------------------------------------------------------------------------- + // Purpose: The browser has been requested to close due to user interaction (usually from a javascript window.close() call) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 4)] + public struct HTML_CloseBrowser_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 4; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + } + + //----------------------------------------------------------------------------- + // Purpose: the browser is navigating to a new url + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 5)] + public struct HTML_URLChanged_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 5; + public HHTMLBrowser unBrowserHandle; // the handle of the surface navigating + public string pchURL; // the url they wish to navigate to + public string pchPostData; // any posted data for the request + [MarshalAs(UnmanagedType.I1)] + public bool bIsRedirect; // true if this was a http/html redirect from the last load request + public string pchPageTitle; // the title of the page + [MarshalAs(UnmanagedType.I1)] + public bool bNewNavigation; // true if this was from a fresh tab and not a click on an existing page + } + + //----------------------------------------------------------------------------- + // Purpose: A page is finished loading + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 6)] + public struct HTML_FinishedRequest_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 6; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchURL; // + public string pchPageTitle; // + } + + //----------------------------------------------------------------------------- + // Purpose: a request to load this url in a new tab + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 7)] + public struct HTML_OpenLinkInNewTab_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 7; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchURL; // + } + + //----------------------------------------------------------------------------- + // Purpose: the page has a new title now + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 8)] + public struct HTML_ChangedTitle_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 8; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchTitle; // + } + + //----------------------------------------------------------------------------- + // Purpose: results from a search + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 9)] + public struct HTML_SearchResults_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 9; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public uint unResults; // + public uint unCurrentMatch; // + } + + //----------------------------------------------------------------------------- + // Purpose: page history status changed on the ability to go backwards and forward + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 10)] + public struct HTML_CanGoBackAndForward_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 10; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + [MarshalAs(UnmanagedType.I1)] + public bool bCanGoBack; // + [MarshalAs(UnmanagedType.I1)] + public bool bCanGoForward; // + } + + //----------------------------------------------------------------------------- + // Purpose: details on the visibility and size of the horizontal scrollbar + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 11)] + public struct HTML_HorizontalScroll_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 11; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public uint unScrollMax; // + public uint unScrollCurrent; // + public float flPageScale; // + [MarshalAs(UnmanagedType.I1)] + public bool bVisible; // + public uint unPageSize; // + } + + //----------------------------------------------------------------------------- + // Purpose: details on the visibility and size of the vertical scrollbar + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 12)] + public struct HTML_VerticalScroll_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 12; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public uint unScrollMax; // + public uint unScrollCurrent; // + public float flPageScale; // + [MarshalAs(UnmanagedType.I1)] + public bool bVisible; // + public uint unPageSize; // + } + + //----------------------------------------------------------------------------- + // Purpose: response to GetLinkAtPosition call + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 13)] + public struct HTML_LinkAtPosition_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 13; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public uint x; // NOTE - Not currently set + public uint y; // NOTE - Not currently set + public string pchURL; // + [MarshalAs(UnmanagedType.I1)] + public bool bInput; // + [MarshalAs(UnmanagedType.I1)] + public bool bLiveLink; // + } + + //----------------------------------------------------------------------------- + // Purpose: show a Javascript alert dialog, call JSDialogResponse + // when the user dismisses this dialog (or right away to ignore it) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 14)] + public struct HTML_JSAlert_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 14; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchMessage; // + } + + //----------------------------------------------------------------------------- + // Purpose: show a Javascript confirmation dialog, call JSDialogResponse + // when the user dismisses this dialog (or right away to ignore it) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 15)] + public struct HTML_JSConfirm_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 15; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchMessage; // + } + + //----------------------------------------------------------------------------- + // Purpose: when received show a file open dialog + // then call FileLoadDialogResponse with the file(s) the user selected. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 16)] + public struct HTML_FileOpenDialog_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 16; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchTitle; // + public string pchInitialFile; // + } + + //----------------------------------------------------------------------------- + // Purpose: a new html window is being created. + // + // IMPORTANT NOTE: at this time, the API does not allow you to acknowledge or + // render the contents of this new window, so the new window is always destroyed + // immediately. The URL and other parameters of the new window are passed here + // to give your application the opportunity to call CreateBrowser and set up + // a new browser in response to the attempted popup, if you wish to do so. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 21)] + public struct HTML_NewWindow_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 21; + public HHTMLBrowser unBrowserHandle; // the handle of the current surface + public string pchURL; // the page to load + public uint unX; // the x pos into the page to display the popup + public uint unY; // the y pos into the page to display the popup + public uint unWide; // the total width of the pBGRA texture + public uint unTall; // the total height of the pBGRA texture + public HHTMLBrowser unNewWindow_BrowserHandle_IGNORE; + } + + //----------------------------------------------------------------------------- + // Purpose: change the cursor to display + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 22)] + public struct HTML_SetCursor_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 22; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public uint eMouseCursor; // the EMouseCursor to display + } + + //----------------------------------------------------------------------------- + // Purpose: informational message from the browser + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 23)] + public struct HTML_StatusText_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 23; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchMsg; // the EMouseCursor to display + } + + //----------------------------------------------------------------------------- + // Purpose: show a tooltip + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 24)] + public struct HTML_ShowToolTip_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 24; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchMsg; // the EMouseCursor to display + } + + //----------------------------------------------------------------------------- + // Purpose: update the text of an existing tooltip + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 25)] + public struct HTML_UpdateToolTip_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 25; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + public string pchMsg; // the EMouseCursor to display + } + + //----------------------------------------------------------------------------- + // Purpose: hide the tooltip you are showing + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 26)] + public struct HTML_HideToolTip_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 26; + public HHTMLBrowser unBrowserHandle; // the handle of the surface + } + + //----------------------------------------------------------------------------- + // Purpose: The browser has restarted due to an internal failure, use this new handle value + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTMLSurfaceCallbacks + 27)] + public struct HTML_BrowserRestarted_t { + public const int k_iCallback = Constants.k_iSteamHTMLSurfaceCallbacks + 27; + public HHTMLBrowser unBrowserHandle; // this is the new browser handle after the restart + public HHTMLBrowser unOldBrowserHandle; // the handle for the browser before the restart, if your handle was this then switch to using unBrowserHandle for API calls + } + + // callbacks + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTTPCallbacks + 1)] + public struct HTTPRequestCompleted_t { + public const int k_iCallback = Constants.k_iSteamHTTPCallbacks + 1; + + // Handle value for the request that has completed. + public HTTPRequestHandle m_hRequest; + + // Context value that the user defined on the request that this callback is associated with, 0 if + // no context value was set. + public ulong m_ulContextValue; + + // This will be true if we actually got any sort of response from the server (even an error). + // It will be false if we failed due to an internal error or client side network failure. + [MarshalAs(UnmanagedType.I1)] + public bool m_bRequestSuccessful; + + // Will be the HTTP status code value returned by the server, k_EHTTPStatusCode200OK is the normal + // OK response, if you get something else you probably need to treat it as a failure. + public EHTTPStatusCode m_eStatusCode; + + public uint m_unBodySize; // Same as GetHTTPResponseBodySize() + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTTPCallbacks + 2)] + public struct HTTPRequestHeadersReceived_t { + public const int k_iCallback = Constants.k_iSteamHTTPCallbacks + 2; + + // Handle value for the request that has received headers. + public HTTPRequestHandle m_hRequest; + + // Context value that the user defined on the request that this callback is associated with, 0 if + // no context value was set. + public ulong m_ulContextValue; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamHTTPCallbacks + 3)] + public struct HTTPRequestDataReceived_t { + public const int k_iCallback = Constants.k_iSteamHTTPCallbacks + 3; + + // Handle value for the request that has received data. + public HTTPRequestHandle m_hRequest; + + // Context value that the user defined on the request that this callback is associated with, 0 if + // no context value was set. + public ulong m_ulContextValue; + + + // Offset to provide to GetHTTPStreamingResponseBodyData to get this chunk of data + public uint m_cOffset; + + // Size to provide to GetHTTPStreamingResponseBodyData to get this chunk of data + public uint m_cBytesReceived; + } + + //----------------------------------------------------------------------------- + // Purpose: called when a new controller has been connected, will fire once + // per controller if multiple new controllers connect in the same frame + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamControllerCallbacks + 1)] + public struct SteamInputDeviceConnected_t { + public const int k_iCallback = Constants.k_iSteamControllerCallbacks + 1; + public InputHandle_t m_ulConnectedDeviceHandle; // Handle for device + } + + //----------------------------------------------------------------------------- + // Purpose: called when a new controller has been connected, will fire once + // per controller if multiple new controllers connect in the same frame + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamControllerCallbacks + 2)] + public struct SteamInputDeviceDisconnected_t { + public const int k_iCallback = Constants.k_iSteamControllerCallbacks + 2; + public InputHandle_t m_ulDisconnectedDeviceHandle; // Handle for device + } + + //----------------------------------------------------------------------------- + // Purpose: called when a controller configuration has been loaded, will fire once + // per controller per focus change for Steam Input enabled controllers + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamControllerCallbacks + 3)] + public struct SteamInputConfigurationLoaded_t { + public const int k_iCallback = Constants.k_iSteamControllerCallbacks + 3; + public AppId_t m_unAppID; + public InputHandle_t m_ulDeviceHandle; // Handle for device + public CSteamID m_ulMappingCreator; // May differ from local user when using + // an unmodified community or official config + public uint m_unMajorRevision; // Binding revision from In-game Action File. + // Same value as queried by GetDeviceBindingRevision + public uint m_unMinorRevision; + [MarshalAs(UnmanagedType.I1)] + public bool m_bUsesSteamInputAPI; // Does the configuration contain any Analog/Digital actions? + [MarshalAs(UnmanagedType.I1)] + public bool m_bUsesGamepadAPI; // Does the configuration contain any Xinput bindings? + } + + //----------------------------------------------------------------------------- + // Purpose: called when controller gamepad slots change - on Linux/macOS these + // slots are shared for all running apps. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamControllerCallbacks + 4)] + public struct SteamInputGamepadSlotChange_t { + public const int k_iCallback = Constants.k_iSteamControllerCallbacks + 4; + public AppId_t m_unAppID; + public InputHandle_t m_ulDeviceHandle; // Handle for device + public ESteamInputType m_eDeviceType; // Type of device + public int m_nOldGamepadSlot; // Previous GamepadSlot - can be -1 controller doesn't uses gamepad bindings + public int m_nNewGamepadSlot; // New Gamepad Slot - can be -1 controller doesn't uses gamepad bindings + } + + // SteamInventoryResultReady_t callbacks are fired whenever asynchronous + // results transition from "Pending" to "OK" or an error state. There will + // always be exactly one callback per handle. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamInventoryCallbacks + 0)] + public struct SteamInventoryResultReady_t { + public const int k_iCallback = Constants.k_iSteamInventoryCallbacks + 0; + public SteamInventoryResult_t m_handle; + public EResult m_result; + } + + // SteamInventoryFullUpdate_t callbacks are triggered when GetAllItems + // successfully returns a result which is newer / fresher than the last + // known result. (It will not trigger if the inventory hasn't changed, + // or if results from two overlapping calls are reversed in flight and + // the earlier result is already known to be stale/out-of-date.) + // The normal ResultReady callback will still be triggered immediately + // afterwards; this is an additional notification for your convenience. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamInventoryCallbacks + 1)] + public struct SteamInventoryFullUpdate_t { + public const int k_iCallback = Constants.k_iSteamInventoryCallbacks + 1; + public SteamInventoryResult_t m_handle; + } + + // A SteamInventoryDefinitionUpdate_t callback is triggered whenever + // item definitions have been updated, which could be in response to + // LoadItemDefinitions() or any other async request which required + // a definition update in order to process results from the server. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamInventoryCallbacks + 2)] + public struct SteamInventoryDefinitionUpdate_t { + public const int k_iCallback = Constants.k_iSteamInventoryCallbacks + 2; + } + + // Returned + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamInventoryCallbacks + 3)] + public struct SteamInventoryEligiblePromoItemDefIDs_t { + public const int k_iCallback = Constants.k_iSteamInventoryCallbacks + 3; + public EResult m_result; + public CSteamID m_steamID; + public int m_numEligiblePromoItemDefs; + [MarshalAs(UnmanagedType.I1)] + public bool m_bCachedData; // indicates that the data was retrieved from the cache and not the server + } + + // Triggered from StartPurchase call + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamInventoryCallbacks + 4)] + public struct SteamInventoryStartPurchaseResult_t { + public const int k_iCallback = Constants.k_iSteamInventoryCallbacks + 4; + public EResult m_result; + public ulong m_ulOrderID; + public ulong m_ulTransID; + } + + // Triggered from RequestPrices + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamInventoryCallbacks + 5)] + public struct SteamInventoryRequestPricesResult_t { + public const int k_iCallback = Constants.k_iSteamInventoryCallbacks + 5; + public EResult m_result; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + private byte[] m_rgchCurrency_; + public string m_rgchCurrency + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchCurrency_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchCurrency_, 4); } + } + } + + //----------------------------------------------------------------------------- + // Callbacks for ISteamMatchmaking (which go through the regular Steam callback registration system) + //----------------------------------------------------------------------------- + // Purpose: a server was added/removed from the favorites list, you should refresh now + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 2)] + public struct FavoritesListChanged_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 2; + public uint m_nIP; // an IP of 0 means reload the whole list, any other value means just one server + public uint m_nQueryPort; + public uint m_nConnPort; + public uint m_nAppID; + public uint m_nFlags; + [MarshalAs(UnmanagedType.I1)] + public bool m_bAdd; // true if this is adding the entry, otherwise it is a remove + public AccountID_t m_unAccountId; + } + + //----------------------------------------------------------------------------- + // Purpose: Someone has invited you to join a Lobby + // normally you don't need to do anything with this, since + // the Steam UI will also display a ' has invited you to the lobby, join?' dialog + // + // if the user outside a game chooses to join, your game will be launched with the parameter "+connect_lobby <64-bit lobby id>", + // or with the callback GameLobbyJoinRequested_t if they're already in-game + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 3)] + public struct LobbyInvite_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 3; + + public ulong m_ulSteamIDUser; // Steam ID of the person making the invite + public ulong m_ulSteamIDLobby; // Steam ID of the Lobby + public ulong m_ulGameID; // GameID of the Lobby + } + + //----------------------------------------------------------------------------- + // Purpose: Sent on entering a lobby, or on failing to enter + // m_EChatRoomEnterResponse will be set to k_EChatRoomEnterResponseSuccess on success, + // or a higher value on failure (see enum EChatRoomEnterResponse) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 4)] + public struct LobbyEnter_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 4; + + public ulong m_ulSteamIDLobby; // SteamID of the Lobby you have entered + public uint m_rgfChatPermissions; // Permissions of the current user + [MarshalAs(UnmanagedType.I1)] + public bool m_bLocked; // If true, then only invited users may join + public uint m_EChatRoomEnterResponse; // EChatRoomEnterResponse + } + + //----------------------------------------------------------------------------- + // Purpose: The lobby metadata has changed + // if m_ulSteamIDMember is the steamID of a lobby member, use GetLobbyMemberData() to access per-user details + // if m_ulSteamIDMember == m_ulSteamIDLobby, use GetLobbyData() to access lobby metadata + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 5)] + public struct LobbyDataUpdate_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 5; + + public ulong m_ulSteamIDLobby; // steamID of the Lobby + public ulong m_ulSteamIDMember; // steamID of the member whose data changed, or the room itself + public byte m_bSuccess; // true if we lobby data was successfully changed; + // will only be false if RequestLobbyData() was called on a lobby that no longer exists + } + + //----------------------------------------------------------------------------- + // Purpose: The lobby chat room state has changed + // this is usually sent when a user has joined or left the lobby + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 6)] + public struct LobbyChatUpdate_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 6; + + public ulong m_ulSteamIDLobby; // Lobby ID + public ulong m_ulSteamIDUserChanged; // user who's status in the lobby just changed - can be recipient + public ulong m_ulSteamIDMakingChange; // Chat member who made the change (different from SteamIDUserChange if kicking, muting, etc.) + // for example, if one user kicks another from the lobby, this will be set to the id of the user who initiated the kick + public uint m_rgfChatMemberStateChange; // bitfield of EChatMemberStateChange values + } + + //----------------------------------------------------------------------------- + // Purpose: A chat message for this lobby has been sent + // use GetLobbyChatEntry( m_iChatID ) to retrieve the contents of this message + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 7)] + public struct LobbyChatMsg_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 7; + + public ulong m_ulSteamIDLobby; // the lobby id this is in + public ulong m_ulSteamIDUser; // steamID of the user who has sent this message + public byte m_eChatEntryType; // type of message + public uint m_iChatID; // index of the chat entry to lookup + } + + //----------------------------------------------------------------------------- + // Purpose: A game created a game for all the members of the lobby to join, + // as triggered by a SetLobbyGameServer() + // it's up to the individual clients to take action on this; the usual + // game behavior is to leave the lobby and connect to the specified game server + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 9)] + public struct LobbyGameCreated_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 9; + + public ulong m_ulSteamIDLobby; // the lobby we were in + public ulong m_ulSteamIDGameServer; // the new game server that has been created or found for the lobby members + public uint m_unIP; // IP & Port of the game server (if any) + public ushort m_usPort; + } + + //----------------------------------------------------------------------------- + // Purpose: Number of matching lobbies found + // iterate the returned lobbies with GetLobbyByIndex(), from values 0 to m_nLobbiesMatching-1 + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 10)] + public struct LobbyMatchList_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 10; + public uint m_nLobbiesMatching; // Number of lobbies that matched search criteria and we have SteamIDs for + } + + //----------------------------------------------------------------------------- + // Purpose: posted if a user is forcefully removed from a lobby + // can occur if a user loses connection to Steam + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 12)] + public struct LobbyKicked_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 12; + public ulong m_ulSteamIDLobby; // Lobby + public ulong m_ulSteamIDAdmin; // User who kicked you - possibly the ID of the lobby itself + public byte m_bKickedDueToDisconnect; // true if you were kicked from the lobby due to the user losing connection to Steam (currently always true) + } + + //----------------------------------------------------------------------------- + // Purpose: Result of our request to create a Lobby + // m_eResult == k_EResultOK on success + // at this point, the lobby has been joined and is ready for use + // a LobbyEnter_t callback will also be received (since the local user is joining their own lobby) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 13)] + public struct LobbyCreated_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 13; + + public EResult m_eResult; // k_EResultOK - the lobby was successfully created + // k_EResultNoConnection - your Steam client doesn't have a connection to the back-end + // k_EResultTimeout - you the message to the Steam servers, but it didn't respond + // k_EResultFail - the server responded, but with an unknown internal error + // k_EResultAccessDenied - your game isn't set to allow lobbies, or your client does haven't rights to play the game + // k_EResultLimitExceeded - your game client has created too many lobbies + + public ulong m_ulSteamIDLobby; // chat room, zero if failed + } + + //----------------------------------------------------------------------------- + // Purpose: Result of our request to create a Lobby + // m_eResult == k_EResultOK on success + // at this point, the lobby has been joined and is ready for use + // a LobbyEnter_t callback will also be received (since the local user is joining their own lobby) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMatchmakingCallbacks + 16)] + public struct FavoritesListAccountsUpdated_t { + public const int k_iCallback = Constants.k_iSteamMatchmakingCallbacks + 16; + + public EResult m_eResult; + } + + //----------------------------------------------------------------------------- + // Callbacks for ISteamGameSearch (which go through the regular Steam callback registration system) + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 1)] + public struct SearchForGameProgressCallback_t { + public const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 1; + + public ulong m_ullSearchID; // all future callbacks referencing this search will include this Search ID + + public EResult m_eResult; // if search has started this result will be k_EResultOK, any other value indicates search has failed to start or has terminated + public CSteamID m_lobbyID; // lobby ID if lobby search, invalid steamID otherwise + public CSteamID m_steamIDEndedSearch; // if search was terminated, steamID that terminated search + + public int m_nSecondsRemainingEstimate; + public int m_cPlayersSearching; + } + + // notification to all players searching that a game has been found + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 2)] + public struct SearchForGameResultCallback_t { + public const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 2; + + public ulong m_ullSearchID; + + public EResult m_eResult; // if game/host was lost this will be an error value + + // if m_bGameFound is true the following are non-zero + public int m_nCountPlayersInGame; + public int m_nCountAcceptedGame; + // if m_steamIDHost is valid the host has started the game + public CSteamID m_steamIDHost; + [MarshalAs(UnmanagedType.I1)] + public bool m_bFinalCallback; + } + + //----------------------------------------------------------------------------- + // ISteamGameSearch : Game Host API callbacks + // callback from RequestPlayersForGame when the matchmaking service has started or ended search + // callback will also follow a call from CancelRequestPlayersForGame - m_bSearchInProgress will be false + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 11)] + public struct RequestPlayersForGameProgressCallback_t { + public const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 11; + + public EResult m_eResult; // m_ullSearchID will be non-zero if this is k_EResultOK + public ulong m_ullSearchID; // all future callbacks referencing this search will include this Search ID + } + + // callback from RequestPlayersForGame + // one of these will be sent per player + // followed by additional callbacks when players accept or decline the game + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 12)] + public struct RequestPlayersForGameResultCallback_t { + public const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 12; + + public EResult m_eResult; // m_ullSearchID will be non-zero if this is k_EResultOK + public ulong m_ullSearchID; + + public CSteamID m_SteamIDPlayerFound; // player steamID + public CSteamID m_SteamIDLobby; // if the player is in a lobby, the lobby ID + public PlayerAcceptState_t m_ePlayerAcceptState; + public int m_nPlayerIndex; + public int m_nTotalPlayersFound; // expect this many callbacks at minimum + public int m_nTotalPlayersAcceptedGame; + public int m_nSuggestedTeamIndex; + public ulong m_ullUniqueGameID; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 13)] + public struct RequestPlayersForGameFinalResultCallback_t { + public const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 13; + + public EResult m_eResult; + public ulong m_ullSearchID; + public ulong m_ullUniqueGameID; + } + + // this callback confirms that results were received by the matchmaking service for this player + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 14)] + public struct SubmitPlayerResultResultCallback_t { + public const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 14; + + public EResult m_eResult; + public ulong ullUniqueGameID; + public CSteamID steamIDPlayer; + } + + // this callback confirms that the game is recorded as complete on the matchmaking service + // the next call to RequestPlayersForGame will generate a new unique game ID + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamGameSearchCallbacks + 15)] + public struct EndGameResultCallback_t { + public const int k_iCallback = Constants.k_iSteamGameSearchCallbacks + 15; + + public EResult m_eResult; + public ulong ullUniqueGameID; + } + + // Steam has responded to the user request to join a party via the given Beacon ID. + // If successful, the connect string contains game-specific instructions to connect + // to the game with that party. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 1)] + public struct JoinPartyCallback_t { + public const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 1; + + public EResult m_eResult; + public PartyBeaconID_t m_ulBeaconID; + public CSteamID m_SteamIDBeaconOwner; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + private byte[] m_rgchConnectString_; + public string m_rgchConnectString + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchConnectString_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchConnectString_, 256); } + } + } + + // Response to CreateBeacon request. If successful, the beacon ID is provided. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 2)] + public struct CreateBeaconCallback_t { + public const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 2; + + public EResult m_eResult; + public PartyBeaconID_t m_ulBeaconID; + } + + // Someone has used the beacon to join your party - they are in-flight now + // and we've reserved one of the open slots for them. + // You should confirm when they join your party by calling OnReservationCompleted(). + // Otherwise, Steam may timeout their reservation eventually. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 3)] + public struct ReservationNotificationCallback_t { + public const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 3; + + public PartyBeaconID_t m_ulBeaconID; + public CSteamID m_steamIDJoiner; + } + + // Response to ChangeNumOpenSlots call + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 4)] + public struct ChangeNumOpenSlotsCallback_t { + public const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 4; + + public EResult m_eResult; + } + + // The list of possible Party beacon locations has changed + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 5)] + public struct AvailableBeaconLocationsUpdated_t { + public const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 5; + } + + // The list of active beacons may have changed + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamPartiesCallbacks + 6)] + public struct ActiveBeaconsUpdated_t { + public const int k_iCallback = Constants.k_iSteamPartiesCallbacks + 6; + } + + // callbacks + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicCallbacks + 1)] + public struct PlaybackStatusHasChanged_t { + public const int k_iCallback = Constants.k_iSteamMusicCallbacks + 1; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMusicCallbacks + 2)] + public struct VolumeHasChanged_t { + public const int k_iCallback = Constants.k_iSteamMusicCallbacks + 2; + public float m_flNewVolume; + } + + // callbacks + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 1)] + public struct MusicPlayerRemoteWillActivate_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 1; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 2)] + public struct MusicPlayerRemoteWillDeactivate_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 2; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 3)] + public struct MusicPlayerRemoteToFront_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 3; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 4)] + public struct MusicPlayerWillQuit_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 4; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 5)] + public struct MusicPlayerWantsPlay_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 5; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 6)] + public struct MusicPlayerWantsPause_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 6; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 7)] + public struct MusicPlayerWantsPlayPrevious_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 7; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 8)] + public struct MusicPlayerWantsPlayNext_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 8; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 9)] + public struct MusicPlayerWantsShuffled_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 9; + [MarshalAs(UnmanagedType.I1)] + public bool m_bShuffled; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 10)] + public struct MusicPlayerWantsLooped_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 10; + [MarshalAs(UnmanagedType.I1)] + public bool m_bLooped; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMusicCallbacks + 11)] + public struct MusicPlayerWantsVolume_t { + public const int k_iCallback = Constants.k_iSteamMusicCallbacks + 11; + public float m_flNewVolume; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMusicCallbacks + 12)] + public struct MusicPlayerSelectsQueueEntry_t { + public const int k_iCallback = Constants.k_iSteamMusicCallbacks + 12; + public int nID; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMusicCallbacks + 13)] + public struct MusicPlayerSelectsPlaylistEntry_t { + public const int k_iCallback = Constants.k_iSteamMusicCallbacks + 13; + public int nID; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamMusicRemoteCallbacks + 14)] + public struct MusicPlayerWantsPlayingRepeatStatus_t { + public const int k_iCallback = Constants.k_iSteamMusicRemoteCallbacks + 14; + public int m_nPlayingRepeatStatus; + } + + // callbacks + // callback notification - a user wants to talk to us over the P2P channel via the SendP2PPacket() API + // in response, a call to AcceptP2PPacketsFromUser() needs to be made, if you want to talk with them + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamNetworkingCallbacks + 2)] + public struct P2PSessionRequest_t { + public const int k_iCallback = Constants.k_iSteamNetworkingCallbacks + 2; + public CSteamID m_steamIDRemote; // user who wants to talk to us + } + + // callback notification - packets can't get through to the specified user via the SendP2PPacket() API + // all packets queued packets unsent at this point will be dropped + // further attempts to send will retry making the connection (but will be dropped if we fail again) + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [CallbackIdentity(Constants.k_iSteamNetworkingCallbacks + 3)] + public struct P2PSessionConnectFail_t { + public const int k_iCallback = Constants.k_iSteamNetworkingCallbacks + 3; + public CSteamID m_steamIDRemote; // user we were sending packets to + public byte m_eP2PSessionError; // EP2PSessionError indicating why we're having trouble + } + + // callback notification - status of a socket has changed + // used as part of the CreateListenSocket() / CreateP2PConnectionSocket() + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamNetworkingCallbacks + 1)] + public struct SocketStatusCallback_t { + public const int k_iCallback = Constants.k_iSteamNetworkingCallbacks + 1; + public SNetSocket_t m_hSocket; // the socket used to send/receive data to the remote host + public SNetListenSocket_t m_hListenSocket; // this is the server socket that we were listening on; NULL if this was an outgoing connection + public CSteamID m_steamIDRemote; // remote steamID we have connected to, if it has one + public int m_eSNetSocketState; // socket state, ESNetSocketState + } + + // + // Callbacks + // + /// Posted when a remote host is sending us a message, and we do not already have a session with them + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamNetworkingMessagesCallbacks + 1)] + public struct SteamNetworkingMessagesSessionRequest_t { + public const int k_iCallback = Constants.k_iSteamNetworkingMessagesCallbacks + 1; + public SteamNetworkingIdentity m_identityRemote; // user who wants to talk to us + } + + /// Posted when we fail to establish a connection, or we detect that communications + /// have been disrupted it an unusual way. There is no notification when a peer proactively + /// closes the session. ("Closed by peer" is not a concept of UDP-style communications, and + /// SteamNetworkingMessages is primarily intended to make porting UDP code easy.) + /// + /// Remember: callbacks are asynchronous. See notes on SendMessageToUser, + /// and k_nSteamNetworkingSend_AutoRestartBrokenSession in particular. + /// + /// Also, if a session times out due to inactivity, no callbacks will be posted. The only + /// way to detect that this is happening is that querying the session state may return + /// none, connecting, and findingroute again. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamNetworkingMessagesCallbacks + 2)] + public struct SteamNetworkingMessagesSessionFailed_t { + public const int k_iCallback = Constants.k_iSteamNetworkingMessagesCallbacks + 2; + + /// Detailed info about the session that failed. + /// SteamNetConnectionInfo_t::m_identityRemote indicates who this session + /// was with. + public SteamNetConnectionInfo_t m_info; + } + + /// Callback struct used to notify when a connection has changed state + /// This callback is posted whenever a connection is created, destroyed, or changes state. + /// The m_info field will contain a complete description of the connection at the time the + /// change occurred and the callback was posted. In particular, m_eState will have the + /// new connection state. + /// + /// You will usually need to listen for this callback to know when: + /// - A new connection arrives on a listen socket. + /// m_info.m_hListenSocket will be set, m_eOldState = k_ESteamNetworkingConnectionState_None, + /// and m_info.m_eState = k_ESteamNetworkingConnectionState_Connecting. + /// See ISteamNetworkigSockets::AcceptConnection. + /// - A connection you initiated has been accepted by the remote host. + /// m_eOldState = k_ESteamNetworkingConnectionState_Connecting, and + /// m_info.m_eState = k_ESteamNetworkingConnectionState_Connected. + /// Some connections might transition to k_ESteamNetworkingConnectionState_FindingRoute first. + /// - A connection has been actively rejected or closed by the remote host. + /// m_eOldState = k_ESteamNetworkingConnectionState_Connecting or k_ESteamNetworkingConnectionState_Connected, + /// and m_info.m_eState = k_ESteamNetworkingConnectionState_ClosedByPeer. m_info.m_eEndReason + /// and m_info.m_szEndDebug will have for more details. + /// NOTE: upon receiving this callback, you must still destroy the connection using + /// ISteamNetworkingSockets::CloseConnection to free up local resources. (The details + /// passed to the function are not used in this case, since the connection is already closed.) + /// - A problem was detected with the connection, and it has been closed by the local host. + /// The most common failure is timeout, but other configuration or authentication failures + /// can cause this. m_eOldState = k_ESteamNetworkingConnectionState_Connecting or + /// k_ESteamNetworkingConnectionState_Connected, and m_info.m_eState = k_ESteamNetworkingConnectionState_ProblemDetectedLocally. + /// m_info.m_eEndReason and m_info.m_szEndDebug will have for more details. + /// NOTE: upon receiving this callback, you must still destroy the connection using + /// ISteamNetworkingSockets::CloseConnection to free up local resources. (The details + /// passed to the function are not used in this case, since the connection is already closed.) + /// + /// Remember that callbacks are posted to a queue, and networking connections can + /// change at any time. It is possible that the connection has already changed + /// state by the time you process this callback. + /// + /// Also note that callbacks will be posted when connections are created and destroyed by your own API calls. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamNetworkingSocketsCallbacks + 1)] + public struct SteamNetConnectionStatusChangedCallback_t { + public const int k_iCallback = Constants.k_iSteamNetworkingSocketsCallbacks + 1; + + /// Connection handle + public HSteamNetConnection m_hConn; + + /// Full connection info + public SteamNetConnectionInfo_t m_info; + + /// Previous state. (Current state is in m_info.m_eState) + public ESteamNetworkingConnectionState m_eOldState; + } + + /// A struct used to describe our readiness to participate in authenticated, + /// encrypted communication. In order to do this we need: + /// + /// - The list of trusted CA certificates that might be relevant for this + /// app. + /// - A valid certificate issued by a CA. + /// + /// This callback is posted whenever the state of our readiness changes. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamNetworkingSocketsCallbacks + 2)] + public struct SteamNetAuthenticationStatus_t { + public const int k_iCallback = Constants.k_iSteamNetworkingSocketsCallbacks + 2; + + /// Status + public ESteamNetworkingAvailability m_eAvail; + + /// Non-localized English language status. For diagnostic/debugging + /// purposes only. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + private byte[] m_debugMsg_; + public string m_debugMsg + { + get { return InteropHelp.ByteArrayToStringUTF8(m_debugMsg_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_debugMsg_, 256); } + } + } + + /// A struct used to describe our readiness to use the relay network. + /// To do this we first need to fetch the network configuration, + /// which describes what POPs are available. + [CallbackIdentity(Constants.k_iSteamNetworkingUtilsCallbacks + 1)] + public struct SteamRelayNetworkStatus_t { + public const int k_iCallback = Constants.k_iSteamNetworkingUtilsCallbacks + 1; + + /// Summary status. When this is "current", initialization has + /// completed. Anything else means you are not ready yet, or + /// there is a significant problem. + public ESteamNetworkingAvailability m_eAvail; + + /// Nonzero if latency measurement is in progress (or pending, + /// awaiting a prerequisite). + public int m_bPingMeasurementInProgress; + + /// Status obtaining the network config. This is a prerequisite + /// for relay network access. + /// + /// Failure to obtain the network config almost always indicates + /// a problem with the local internet connection. + public ESteamNetworkingAvailability m_eAvailNetworkConfig; + + /// Current ability to communicate with ANY relay. Note that + /// the complete failure to communicate with any relays almost + /// always indicates a problem with the local Internet connection. + /// (However, just because you can reach a single relay doesn't + /// mean that the local connection is in perfect health.) + public ESteamNetworkingAvailability m_eAvailAnyRelay; + + /// Non-localized English language status. For diagnostic/debugging + /// purposes only. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + private byte[] m_debugMsg_; + public string m_debugMsg + { + get { return InteropHelp.ByteArrayToStringUTF8(m_debugMsg_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_debugMsg_, 256); } + } + } + + //----------------------------------------------------------------------------- + // Purpose: Callback for querying UGC + //----------------------------------------------------------------------------- + [CallbackIdentity(Constants.k_ISteamParentalSettingsCallbacks + 1)] + public struct SteamParentalSettingsChanged_t { + public const int k_iCallback = Constants.k_ISteamParentalSettingsCallbacks + 1; + } + + // callbacks + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemotePlayCallbacks + 1)] + public struct SteamRemotePlaySessionConnected_t { + public const int k_iCallback = Constants.k_iSteamRemotePlayCallbacks + 1; + public RemotePlaySessionID_t m_unSessionID; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemotePlayCallbacks + 2)] + public struct SteamRemotePlaySessionDisconnected_t { + public const int k_iCallback = Constants.k_iSteamRemotePlayCallbacks + 2; + public RemotePlaySessionID_t m_unSessionID; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemotePlayCallbacks + 3)] + public struct SteamRemotePlayTogetherGuestInvite_t { + public const int k_iCallback = Constants.k_iSteamRemotePlayCallbacks + 3; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] + private byte[] m_szConnectURL_; + public string m_szConnectURL + { + get { return InteropHelp.ByteArrayToStringUTF8(m_szConnectURL_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_szConnectURL_, 1024); } + } + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: The result of a call to FileShare() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 7)] + public struct RemoteStorageFileShareResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 7; + public EResult m_eResult; // The result of the operation + public UGCHandle_t m_hFile; // The handle that can be shared with users and features + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchFilenameMax)] + private byte[] m_rgchFilename_; + public string m_rgchFilename // The name of the file that was shared + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchFilename_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchFilename_, Constants.k_cchFilenameMax); } + } + } + + // k_iSteamRemoteStorageCallbacks + 8 is deprecated! Do not reuse + //----------------------------------------------------------------------------- + // Purpose: The result of a call to PublishFile() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 9)] + public struct RemoteStoragePublishFileResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 9; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; + [MarshalAs(UnmanagedType.I1)] + public bool m_bUserNeedsToAcceptWorkshopLegalAgreement; + } + + // k_iSteamRemoteStorageCallbacks + 10 is deprecated! Do not reuse + //----------------------------------------------------------------------------- + // Purpose: The result of a call to DeletePublishedFile() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 11)] + public struct RemoteStorageDeletePublishedFileResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 11; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to EnumerateUserPublishedFiles() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 12)] + public struct RemoteStorageEnumerateUserPublishedFilesResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 12; + public EResult m_eResult; // The result of the operation. + public int m_nResultsReturned; + public int m_nTotalResultCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)] + public PublishedFileId_t[] m_rgPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to SubscribePublishedFile() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 13)] + public struct RemoteStorageSubscribePublishedFileResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 13; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to EnumerateSubscribePublishedFiles() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 14)] + public struct RemoteStorageEnumerateUserSubscribedFilesResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 14; + public EResult m_eResult; // The result of the operation. + public int m_nResultsReturned; + public int m_nTotalResultCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)] + public PublishedFileId_t[] m_rgPublishedFileId; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)] + public uint[] m_rgRTimeSubscribed; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to UnsubscribePublishedFile() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 15)] + public struct RemoteStorageUnsubscribePublishedFileResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 15; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to CommitPublishedFileUpdate() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 16)] + public struct RemoteStorageUpdatePublishedFileResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 16; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; + [MarshalAs(UnmanagedType.I1)] + public bool m_bUserNeedsToAcceptWorkshopLegalAgreement; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to UGCDownload() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 17)] + public struct RemoteStorageDownloadUGCResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 17; + public EResult m_eResult; // The result of the operation. + public UGCHandle_t m_hFile; // The handle to the file that was attempted to be downloaded. + public AppId_t m_nAppID; // ID of the app that created this file. + public int m_nSizeInBytes; // The size of the file that was downloaded, in bytes. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchFilenameMax)] + private byte[] m_pchFileName_; + public string m_pchFileName // The name of the file that was downloaded. + { + get { return InteropHelp.ByteArrayToStringUTF8(m_pchFileName_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_pchFileName_, Constants.k_cchFilenameMax); } + } + public ulong m_ulSteamIDOwner; // Steam ID of the user who created this content. + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to GetPublishedFileDetails() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 18)] + public struct RemoteStorageGetPublishedFileDetailsResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 18; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; + public AppId_t m_nCreatorAppID; // ID of the app that created this file. + public AppId_t m_nConsumerAppID; // ID of the app that will consume this file. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedDocumentTitleMax)] + private byte[] m_rgchTitle_; + public string m_rgchTitle // title of document + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchTitle_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchTitle_, Constants.k_cchPublishedDocumentTitleMax); } + } + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedDocumentDescriptionMax)] + private byte[] m_rgchDescription_; + public string m_rgchDescription // description of document + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchDescription_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchDescription_, Constants.k_cchPublishedDocumentDescriptionMax); } + } + public UGCHandle_t m_hFile; // The handle of the primary file + public UGCHandle_t m_hPreviewFile; // The handle of the preview file + public ulong m_ulSteamIDOwner; // Steam ID of the user who created this content. + public uint m_rtimeCreated; // time when the published file was created + public uint m_rtimeUpdated; // time when the published file was last updated + public ERemoteStoragePublishedFileVisibility m_eVisibility; + [MarshalAs(UnmanagedType.I1)] + public bool m_bBanned; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchTagListMax)] + private byte[] m_rgchTags_; + public string m_rgchTags // comma separated list of all tags associated with this file + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchTags_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchTags_, Constants.k_cchTagListMax); } + } + [MarshalAs(UnmanagedType.I1)] + public bool m_bTagsTruncated; // whether the list of tags was too long to be returned in the provided buffer + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchFilenameMax)] + private byte[] m_pchFileName_; + public string m_pchFileName // The name of the primary file + { + get { return InteropHelp.ByteArrayToStringUTF8(m_pchFileName_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_pchFileName_, Constants.k_cchFilenameMax); } + } + public int m_nFileSize; // Size of the primary file + public int m_nPreviewFileSize; // Size of the preview file + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedFileURLMax)] + private byte[] m_rgchURL_; + public string m_rgchURL // URL (for a video or a website) + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchURL_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchURL_, Constants.k_cchPublishedFileURLMax); } + } + public EWorkshopFileType m_eFileType; // Type of the file + [MarshalAs(UnmanagedType.I1)] + public bool m_bAcceptedForUse; // developer has specifically flagged this item as accepted in the Workshop + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 19)] + public struct RemoteStorageEnumerateWorkshopFilesResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 19; + public EResult m_eResult; + public int m_nResultsReturned; + public int m_nTotalResultCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)] + public PublishedFileId_t[] m_rgPublishedFileId; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)] + public float[] m_rgScore; + public AppId_t m_nAppId; + public uint m_unStartIndex; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of GetPublishedItemVoteDetails + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 20)] + public struct RemoteStorageGetPublishedItemVoteDetailsResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 20; + public EResult m_eResult; + public PublishedFileId_t m_unPublishedFileId; + public int m_nVotesFor; + public int m_nVotesAgainst; + public int m_nReports; + public float m_fScore; + } + + //----------------------------------------------------------------------------- + // Purpose: User subscribed to a file for the app (from within the app or on the web) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 21)] + public struct RemoteStoragePublishedFileSubscribed_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 21; + public PublishedFileId_t m_nPublishedFileId; // The published file id + public AppId_t m_nAppID; // ID of the app that will consume this file. + } + + //----------------------------------------------------------------------------- + // Purpose: User unsubscribed from a file for the app (from within the app or on the web) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 22)] + public struct RemoteStoragePublishedFileUnsubscribed_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 22; + public PublishedFileId_t m_nPublishedFileId; // The published file id + public AppId_t m_nAppID; // ID of the app that will consume this file. + } + + //----------------------------------------------------------------------------- + // Purpose: Published file that a user owns was deleted (from within the app or the web) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 23)] + public struct RemoteStoragePublishedFileDeleted_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 23; + public PublishedFileId_t m_nPublishedFileId; // The published file id + public AppId_t m_nAppID; // ID of the app that will consume this file. + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to UpdateUserPublishedItemVote() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 24)] + public struct RemoteStorageUpdateUserPublishedItemVoteResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 24; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; // The published file id + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to GetUserPublishedItemVoteDetails() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 25)] + public struct RemoteStorageUserVoteDetails_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 25; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; // The published file id + public EWorkshopVote m_eVote; // what the user voted + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 26)] + public struct RemoteStorageEnumerateUserSharedWorkshopFilesResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 26; + public EResult m_eResult; // The result of the operation. + public int m_nResultsReturned; + public int m_nTotalResultCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)] + public PublishedFileId_t[] m_rgPublishedFileId; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 27)] + public struct RemoteStorageSetUserPublishedFileActionResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 27; + public EResult m_eResult; // The result of the operation. + public PublishedFileId_t m_nPublishedFileId; // The published file id + public EWorkshopFileAction m_eAction; // the action that was attempted + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 28)] + public struct RemoteStorageEnumeratePublishedFilesByUserActionResult_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 28; + public EResult m_eResult; // The result of the operation. + public EWorkshopFileAction m_eAction; // the action that was filtered on + public int m_nResultsReturned; + public int m_nTotalResultCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)] + public PublishedFileId_t[] m_rgPublishedFileId; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_unEnumeratePublishedFilesMaxResults)] + public uint[] m_rgRTimeUpdated; + } + + //----------------------------------------------------------------------------- + // Purpose: Called periodically while a PublishWorkshopFile is in progress + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 29)] + public struct RemoteStoragePublishFileProgress_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 29; + public double m_dPercentFile; + [MarshalAs(UnmanagedType.I1)] + public bool m_bPreview; + } + + //----------------------------------------------------------------------------- + // Purpose: Called when the content for a published file is updated + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 30)] + public struct RemoteStoragePublishedFileUpdated_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 30; + public PublishedFileId_t m_nPublishedFileId; // The published file id + public AppId_t m_nAppID; // ID of the app that will consume this file. + public ulong m_ulUnused; // not used anymore + } + + //----------------------------------------------------------------------------- + // Purpose: Called when a FileWriteAsync completes + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 31)] + public struct RemoteStorageFileWriteAsyncComplete_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 31; + public EResult m_eResult; // result + } + + //----------------------------------------------------------------------------- + // Purpose: Called when a FileReadAsync completes + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 32)] + public struct RemoteStorageFileReadAsyncComplete_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 32; + public SteamAPICall_t m_hFileReadAsync; // call handle of the async read which was made + public EResult m_eResult; // result + public uint m_nOffset; // offset in the file this read was at + public uint m_cubRead; // amount read - will the <= the amount requested + } + + //----------------------------------------------------------------------------- + // Purpose: one or more files for this app have changed locally after syncing + // to remote session changes + // Note: only posted if this happens DURING the local app session + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamRemoteStorageCallbacks + 33)] + public struct RemoteStorageLocalFileChange_t { + public const int k_iCallback = Constants.k_iSteamRemoteStorageCallbacks + 33; + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: Screenshot successfully written or otherwise added to the library + // and can now be tagged + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamScreenshotsCallbacks + 1)] + public struct ScreenshotReady_t { + public const int k_iCallback = Constants.k_iSteamScreenshotsCallbacks + 1; + public ScreenshotHandle m_hLocal; + public EResult m_eResult; + } + + //----------------------------------------------------------------------------- + // Purpose: Screenshot has been requested by the user. Only sent if + // HookScreenshots() has been called, in which case Steam will not take + // the screenshot itself. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamScreenshotsCallbacks + 2)] + public struct ScreenshotRequested_t { + public const int k_iCallback = Constants.k_iSteamScreenshotsCallbacks + 2; + } + + //----------------------------------------------------------------------------- + // Purpose: Callback for querying UGC + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 1)] + public struct SteamUGCQueryCompleted_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 1; + public UGCQueryHandle_t m_handle; + public EResult m_eResult; + public uint m_unNumResultsReturned; + public uint m_unTotalMatchingResults; + [MarshalAs(UnmanagedType.I1)] + public bool m_bCachedData; // indicates whether this data was retrieved from the local on-disk cache + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedFileURLMax)] + private byte[] m_rgchNextCursor_; + public string m_rgchNextCursor // If a paging cursor was used, then this will be the next cursor to get the next result set. + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchNextCursor_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchNextCursor_, Constants.k_cchPublishedFileURLMax); } + } + } + + //----------------------------------------------------------------------------- + // Purpose: Callback for requesting details on one piece of UGC + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 2)] + public struct SteamUGCRequestUGCDetailsResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 2; + public SteamUGCDetails_t m_details; + [MarshalAs(UnmanagedType.I1)] + public bool m_bCachedData; // indicates whether this data was retrieved from the local on-disk cache + } + + //----------------------------------------------------------------------------- + // Purpose: result for ISteamUGC::CreateItem() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 3)] + public struct CreateItemResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 3; + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; // new item got this UGC PublishFileID + [MarshalAs(UnmanagedType.I1)] + public bool m_bUserNeedsToAcceptWorkshopLegalAgreement; + } + + //----------------------------------------------------------------------------- + // Purpose: result for ISteamUGC::SubmitItemUpdate() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 4)] + public struct SubmitItemUpdateResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 4; + public EResult m_eResult; + [MarshalAs(UnmanagedType.I1)] + public bool m_bUserNeedsToAcceptWorkshopLegalAgreement; + public PublishedFileId_t m_nPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: a Workshop item has been installed or updated + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 5)] + public struct ItemInstalled_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 5; + public AppId_t m_unAppID; + public PublishedFileId_t m_nPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: result of DownloadItem(), existing item files can be accessed again + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 6)] + public struct DownloadItemResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 6; + public AppId_t m_unAppID; + public PublishedFileId_t m_nPublishedFileId; + public EResult m_eResult; + } + + //----------------------------------------------------------------------------- + // Purpose: result of AddItemToFavorites() or RemoveItemFromFavorites() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 7)] + public struct UserFavoriteItemsListChanged_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 7; + public PublishedFileId_t m_nPublishedFileId; + public EResult m_eResult; + [MarshalAs(UnmanagedType.I1)] + public bool m_bWasAddRequest; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to SetUserItemVote() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 8)] + public struct SetUserItemVoteResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 8; + public PublishedFileId_t m_nPublishedFileId; + public EResult m_eResult; + [MarshalAs(UnmanagedType.I1)] + public bool m_bVoteUp; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to GetUserItemVote() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 9)] + public struct GetUserItemVoteResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 9; + public PublishedFileId_t m_nPublishedFileId; + public EResult m_eResult; + [MarshalAs(UnmanagedType.I1)] + public bool m_bVotedUp; + [MarshalAs(UnmanagedType.I1)] + public bool m_bVotedDown; + [MarshalAs(UnmanagedType.I1)] + public bool m_bVoteSkipped; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to StartPlaytimeTracking() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 10)] + public struct StartPlaytimeTrackingResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 10; + public EResult m_eResult; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to StopPlaytimeTracking() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 11)] + public struct StopPlaytimeTrackingResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 11; + public EResult m_eResult; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to AddDependency + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 12)] + public struct AddUGCDependencyResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 12; + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + public PublishedFileId_t m_nChildPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to RemoveDependency + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 13)] + public struct RemoveUGCDependencyResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 13; + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + public PublishedFileId_t m_nChildPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to AddAppDependency + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 14)] + public struct AddAppDependencyResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 14; + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + public AppId_t m_nAppID; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to RemoveAppDependency + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 15)] + public struct RemoveAppDependencyResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 15; + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + public AppId_t m_nAppID; + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to GetAppDependencies. Callback may be called + // multiple times until all app dependencies have been returned. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 16)] + public struct GetAppDependenciesResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 16; + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public AppId_t[] m_rgAppIDs; + public uint m_nNumAppDependencies; // number returned in this struct + public uint m_nTotalNumAppDependencies; // total found + } + + //----------------------------------------------------------------------------- + // Purpose: The result of a call to DeleteItem + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 17)] + public struct DeleteItemResult_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 17; + public EResult m_eResult; + public PublishedFileId_t m_nPublishedFileId; + } + + //----------------------------------------------------------------------------- + // Purpose: signal that the list of subscribed items changed + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 18)] + public struct UserSubscribedItemsListChanged_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 18; + public AppId_t m_nAppID; + } + + //----------------------------------------------------------------------------- + // Purpose: Status of the user's acceptable/rejection of the app's specific Workshop EULA + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUGCCallbacks + 20)] + public struct WorkshopEULAStatus_t { + public const int k_iCallback = Constants.k_iSteamUGCCallbacks + 20; + public EResult m_eResult; + public AppId_t m_nAppID; + public uint m_unVersion; + public RTime32 m_rtAction; + [MarshalAs(UnmanagedType.I1)] + public bool m_bAccepted; + [MarshalAs(UnmanagedType.I1)] + public bool m_bNeedsAction; + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: Called when an authenticated connection to the Steam back-end has been established. + // This means the Steam client now has a working connection to the Steam servers. + // Usually this will have occurred before the game has launched, and should + // only be seen if the user has dropped connection due to a networking issue + // or a Steam server update. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 1)] + public struct SteamServersConnected_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 1; + } + + //----------------------------------------------------------------------------- + // Purpose: called when a connection attempt has failed + // this will occur periodically if the Steam client is not connected, + // and has failed in it's retry to establish a connection + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 2)] + public struct SteamServerConnectFailure_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 2; + public EResult m_eResult; + [MarshalAs(UnmanagedType.I1)] + public bool m_bStillRetrying; + } + + //----------------------------------------------------------------------------- + // Purpose: called if the client has lost connection to the Steam servers + // real-time services will be disabled until a matching SteamServersConnected_t has been posted + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 3)] + public struct SteamServersDisconnected_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 3; + public EResult m_eResult; + } + + //----------------------------------------------------------------------------- + // Purpose: Sent by the Steam server to the client telling it to disconnect from the specified game server, + // which it may be in the process of or already connected to. + // The game client should immediately disconnect upon receiving this message. + // This can usually occur if the user doesn't have rights to play on the game server. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 13)] + public struct ClientGameServerDeny_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 13; + + public uint m_uAppID; + public uint m_unGameServerIP; + public ushort m_usGameServerPort; + public ushort m_bSecure; + public uint m_uReason; + } + + //----------------------------------------------------------------------------- + // Purpose: called when the callback system for this client is in an error state (and has flushed pending callbacks) + // When getting this message the client should disconnect from Steam, reset any stored Steam state and reconnect. + // This usually occurs in the rare event the Steam client has some kind of fatal error. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 17)] + public struct IPCFailure_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 17; + public byte m_eFailureType; + } + + //----------------------------------------------------------------------------- + // Purpose: Signaled whenever licenses change + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 25)] + public struct LicensesUpdated_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 25; + } + + //----------------------------------------------------------------------------- + // callback for BeginAuthSession + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = 4)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 43)] + public struct ValidateAuthTicketResponse_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 43; + public CSteamID m_SteamID; + public EAuthSessionResponse m_eAuthSessionResponse; + public CSteamID m_OwnerSteamID; // different from m_SteamID if borrowed + } + + //----------------------------------------------------------------------------- + // Purpose: called when a user has responded to a microtransaction authorization request + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 52)] + public struct MicroTxnAuthorizationResponse_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 52; + + public uint m_unAppID; // AppID for this microtransaction + public ulong m_ulOrderID; // OrderID provided for the microtransaction + public byte m_bAuthorized; // if user authorized transaction + } + + //----------------------------------------------------------------------------- + // Purpose: Result from RequestEncryptedAppTicket + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 54)] + public struct EncryptedAppTicketResponse_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 54; + + public EResult m_eResult; + } + + //----------------------------------------------------------------------------- + // callback for GetAuthSessionTicket + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 63)] + public struct GetAuthSessionTicketResponse_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 63; + public HAuthTicket m_hAuthTicket; + public EResult m_eResult; + } + + //----------------------------------------------------------------------------- + // Purpose: sent to your game in response to a steam://gamewebcallback/ command + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 64)] + public struct GameWebCallback_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 64; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + private byte[] m_szURL_; + public string m_szURL + { + get { return InteropHelp.ByteArrayToStringUTF8(m_szURL_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_szURL_, 256); } + } + } + + //----------------------------------------------------------------------------- + // Purpose: sent to your game in response to ISteamUser::RequestStoreAuthURL + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 65)] + public struct StoreAuthURLResponse_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 65; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] + private byte[] m_szURL_; + public string m_szURL + { + get { return InteropHelp.ByteArrayToStringUTF8(m_szURL_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_szURL_, 512); } + } + } + + //----------------------------------------------------------------------------- + // Purpose: sent in response to ISteamUser::GetMarketEligibility + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 66)] + public struct MarketEligibilityResponse_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 66; + [MarshalAs(UnmanagedType.I1)] + public bool m_bAllowed; + public EMarketNotAllowedReasonFlags m_eNotAllowedReason; + public RTime32 m_rtAllowedAtTime; + + public int m_cdaySteamGuardRequiredDays; // The number of days any user is required to have had Steam Guard before they can use the market + public int m_cdayNewDeviceCooldown; // The number of days after initial device authorization a user must wait before using the market on that device + } + + //----------------------------------------------------------------------------- + // Purpose: sent for games with enabled anti indulgence / duration control, for + // enabled users. Lets the game know whether the user can keep playing or + // whether the game should exit, and returns info about remaining gameplay time. + // + // This callback is fired asynchronously in response to timers triggering. + // It is also fired in response to calls to GetDurationControl(). + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 67)] + public struct DurationControl_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 67; + + public EResult m_eResult; // result of call (always k_EResultOK for asynchronous timer-based notifications) + public AppId_t m_appid; // appid generating playtime + + [MarshalAs(UnmanagedType.I1)] + public bool m_bApplicable; // is duration control applicable to user + game combination + public int m_csecsLast5h; // playtime since most recent 5 hour gap in playtime, only counting up to regulatory limit of playtime, in seconds + + public EDurationControlProgress m_progress; // recommended progress (either everything is fine, or please exit game) + public EDurationControlNotification m_notification; // notification to show, if any (always k_EDurationControlNotification_None for API calls) + + public int m_csecsToday; // playtime on current calendar day + public int m_csecsRemaining; // playtime remaining until the user hits a regulatory limit + } + + //----------------------------------------------------------------------------- + // callback for GetTicketForWebApi + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserCallbacks + 68)] + public struct GetTicketForWebApiResponse_t { + public const int k_iCallback = Constants.k_iSteamUserCallbacks + 68; + public HAuthTicket m_hAuthTicket; + public EResult m_eResult; + public int m_cubTicket; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_nCubTicketMaxLength)] + public byte[] m_rgubTicket; + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: called when the latests stats and achievements have been received + // from the server + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Explicit, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 1)] + public struct UserStatsReceived_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 1; + [FieldOffset(0)] + public ulong m_nGameID; // Game these stats are for + [FieldOffset(8)] + public EResult m_eResult; // Success / error fetching the stats + [FieldOffset(12)] + public CSteamID m_steamIDUser; // The user for whom the stats are retrieved for + } + + //----------------------------------------------------------------------------- + // Purpose: result of a request to store the user stats for a game + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 2)] + public struct UserStatsStored_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 2; + public ulong m_nGameID; // Game these stats are for + public EResult m_eResult; // success / error + } + + //----------------------------------------------------------------------------- + // Purpose: result of a request to store the achievements for a game, or an + // "indicate progress" call. If both m_nCurProgress and m_nMaxProgress + // are zero, that means the achievement has been fully unlocked. + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 3)] + public struct UserAchievementStored_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 3; + + public ulong m_nGameID; // Game this is for + [MarshalAs(UnmanagedType.I1)] + public bool m_bGroupAchievement; // if this is a "group" achievement + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchStatNameMax)] + private byte[] m_rgchAchievementName_; + public string m_rgchAchievementName // name of the achievement + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchAchievementName_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchAchievementName_, Constants.k_cchStatNameMax); } + } + public uint m_nCurProgress; // current progress towards the achievement + public uint m_nMaxProgress; // "out of" this many + } + + //----------------------------------------------------------------------------- + // Purpose: call result for finding a leaderboard, returned as a result of FindOrCreateLeaderboard() or FindLeaderboard() + // use CCallResult<> to map this async result to a member function + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 4)] + public struct LeaderboardFindResult_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 4; + public SteamLeaderboard_t m_hSteamLeaderboard; // handle to the leaderboard serarched for, 0 if no leaderboard found + public byte m_bLeaderboardFound; // 0 if no leaderboard found + } + + //----------------------------------------------------------------------------- + // Purpose: call result indicating scores for a leaderboard have been downloaded and are ready to be retrieved, returned as a result of DownloadLeaderboardEntries() + // use CCallResult<> to map this async result to a member function + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 5)] + public struct LeaderboardScoresDownloaded_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 5; + public SteamLeaderboard_t m_hSteamLeaderboard; + public SteamLeaderboardEntries_t m_hSteamLeaderboardEntries; // the handle to pass into GetDownloadedLeaderboardEntries() + public int m_cEntryCount; // the number of entries downloaded + } + + //----------------------------------------------------------------------------- + // Purpose: call result indicating scores has been uploaded, returned as a result of UploadLeaderboardScore() + // use CCallResult<> to map this async result to a member function + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 6)] + public struct LeaderboardScoreUploaded_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 6; + public byte m_bSuccess; // 1 if the call was successful + public SteamLeaderboard_t m_hSteamLeaderboard; // the leaderboard handle that was + public int m_nScore; // the score that was attempted to set + public byte m_bScoreChanged; // true if the score in the leaderboard change, false if the existing score was better + public int m_nGlobalRankNew; // the new global rank of the user in this leaderboard + public int m_nGlobalRankPrevious; // the previous global rank of the user in this leaderboard; 0 if the user had no existing entry in the leaderboard + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 7)] + public struct NumberOfCurrentPlayers_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 7; + public byte m_bSuccess; // 1 if the call was successful + public int m_cPlayers; // Number of players currently playing + } + + //----------------------------------------------------------------------------- + // Purpose: Callback indicating that a user's stats have been unloaded. + // Call RequestUserStats again to access stats for this user + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 8)] + public struct UserStatsUnloaded_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 8; + public CSteamID m_steamIDUser; // User whose stats have been unloaded + } + + //----------------------------------------------------------------------------- + // Purpose: Callback indicating that an achievement icon has been fetched + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 9)] + public struct UserAchievementIconFetched_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 9; + + public CGameID m_nGameID; // Game this is for + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchStatNameMax)] + private byte[] m_rgchAchievementName_; + public string m_rgchAchievementName // name of the achievement + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchAchievementName_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchAchievementName_, Constants.k_cchStatNameMax); } + } + [MarshalAs(UnmanagedType.I1)] + public bool m_bAchieved; // Is the icon for the achieved or not achieved version? + public int m_nIconHandle; // Handle to the image, which can be used in SteamUtils()->GetImageRGBA(), 0 means no image is set for the achievement + } + + //----------------------------------------------------------------------------- + // Purpose: Callback indicating that global achievement percentages are fetched + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 10)] + public struct GlobalAchievementPercentagesReady_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 10; + + public ulong m_nGameID; // Game this is for + public EResult m_eResult; // Result of the operation + } + + //----------------------------------------------------------------------------- + // Purpose: call result indicating UGC has been uploaded, returned as a result of SetLeaderboardUGC() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 11)] + public struct LeaderboardUGCSet_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 11; + public EResult m_eResult; // The result of the operation + public SteamLeaderboard_t m_hSteamLeaderboard; // the leaderboard handle that was + } + + //----------------------------------------------------------------------------- + // Purpose: callback indicating global stats have been received. + // Returned as a result of RequestGlobalStats() + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUserStatsCallbacks + 12)] + public struct GlobalStatsReceived_t { + public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 12; + public ulong m_nGameID; // Game global stats were requested for + public EResult m_eResult; // The result of the request + } + + // callbacks + //----------------------------------------------------------------------------- + // Purpose: The country of the user changed + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 1)] + public struct IPCountry_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 1; + } + + //----------------------------------------------------------------------------- + // Purpose: Fired when running on a laptop and less than 10 minutes of battery is left, fires then every minute + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 2)] + public struct LowBatteryPower_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 2; + public byte m_nMinutesBatteryLeft; + } + + //----------------------------------------------------------------------------- + // Purpose: called when a SteamAsyncCall_t has completed (or failed) + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 3)] + public struct SteamAPICallCompleted_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 3; + public SteamAPICall_t m_hAsyncCall; + public int m_iCallback; + public uint m_cubParam; + } + + //----------------------------------------------------------------------------- + // called when Steam wants to shutdown + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 4)] + public struct SteamShutdown_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 4; + } + + //----------------------------------------------------------------------------- + // callback for CheckFileSignature + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 5)] + public struct CheckFileSignature_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 5; + public ECheckFileSignature m_eCheckFileSignature; + } + + // k_iSteamUtilsCallbacks + 13 is taken + //----------------------------------------------------------------------------- + // Full Screen gamepad text input has been closed + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 14)] + public struct GamepadTextInputDismissed_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 14; + [MarshalAs(UnmanagedType.I1)] + public bool m_bSubmitted; // true if user entered & accepted text (Call ISteamUtils::GetEnteredGamepadTextInput() for text), false if canceled input + public uint m_unSubmittedText; + public AppId_t m_unAppID; + } + + // k_iSteamUtilsCallbacks + 15 through 35 are taken + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 36)] + public struct AppResumingFromSuspend_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 36; + } + + // k_iSteamUtilsCallbacks + 37 is taken + //----------------------------------------------------------------------------- + // The floating on-screen keyboard has been closed + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value, Size = 1)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 38)] + public struct FloatingGamepadTextInputDismissed_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 38; + } + + //----------------------------------------------------------------------------- + // The text filtering dictionary has changed + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamUtilsCallbacks + 39)] + public struct FilterTextDictionaryChanged_t { + public const int k_iCallback = Constants.k_iSteamUtilsCallbacks + 39; + public int m_eLanguage; // One of ELanguage, or k_LegallyRequiredFiltering + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamVideoCallbacks + 11)] + public struct GetVideoURLResult_t { + public const int k_iCallback = Constants.k_iSteamVideoCallbacks + 11; + public EResult m_eResult; + public AppId_t m_unVideoAppID; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + private byte[] m_rgchURL_; + public string m_rgchURL + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchURL_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchURL_, 256); } + } + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamVideoCallbacks + 24)] + public struct GetOPFSettingsResult_t { + public const int k_iCallback = Constants.k_iSteamVideoCallbacks + 24; + public EResult m_eResult; + public AppId_t m_unVideoAppID; + } + + /// Callback struct used to notify when a connection has changed state + /// A struct used to describe a "fake IP" we have been assigned to + /// use as an identifier. This callback is posted when + /// ISteamNetworkingSoockets::BeginAsyncRequestFakeIP completes. + /// See also ISteamNetworkingSockets::GetFakeIP + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + [CallbackIdentity(Constants.k_iSteamNetworkingSocketsCallbacks + 3)] + public struct SteamNetworkingFakeIPResult_t { + public const int k_iCallback = Constants.k_iSteamNetworkingSocketsCallbacks + 3; + + /// Status/result of the allocation request. Possible failure values are: + /// - k_EResultBusy - you called GetFakeIP but the request has not completed. + /// - k_EResultInvalidParam - you called GetFakeIP with an invalid port index + /// - k_EResultLimitExceeded - You asked for too many ports, or made an + /// additional request after one had already succeeded + /// - k_EResultNoMatch - GetFakeIP was called, but no request has been made + /// + /// Note that, with the exception of k_EResultBusy (if you are polling), + /// it is highly recommended to treat all failures as fatal. + public EResult m_eResult; + + /// Local identity of the ISteamNetworkingSockets object that made + /// this request and is assigned the IP. This is needed in the callback + /// in the case where there are multiple ISteamNetworkingSockets objects. + /// (E.g. one for the user, and another for the local gameserver). + public SteamNetworkingIdentity m_identity; + + /// Fake IPv4 IP address that we have been assigned. NOTE: this + /// IP address is not exclusively ours! Steam tries to avoid sharing + /// IP addresses, but this may not always be possible. The IP address + /// may be currently in use by another host, but with different port(s). + /// The exact same IP:port address may have been used previously. + /// Steam tries to avoid reusing ports until they have not been in use for + /// some time, but this may not always be possible. + public uint m_unIP; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_nMaxReturnPorts)] + public ushort[] m_unPorts; + } + +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamCallbacks.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamCallbacks.cs.meta new file mode 100644 index 0000000..4acb852 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamCallbacks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 80afdfc414f63f049bdfae509faaadf7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamConstants.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamConstants.cs new file mode 100644 index 0000000..c125936 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamConstants.cs @@ -0,0 +1,330 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class Constants { + public const string STEAMAPPLIST_INTERFACE_VERSION = "STEAMAPPLIST_INTERFACE_VERSION001"; + public const string STEAMAPPS_INTERFACE_VERSION = "STEAMAPPS_INTERFACE_VERSION008"; + public const string STEAMAPPTICKET_INTERFACE_VERSION = "STEAMAPPTICKET_INTERFACE_VERSION001"; + public const string STEAMCLIENT_INTERFACE_VERSION = "SteamClient020"; + public const string STEAMFRIENDS_INTERFACE_VERSION = "SteamFriends017"; + public const string STEAMGAMECOORDINATOR_INTERFACE_VERSION = "SteamGameCoordinator001"; + public const string STEAMGAMESERVER_INTERFACE_VERSION = "SteamGameServer015"; + public const string STEAMGAMESERVERSTATS_INTERFACE_VERSION = "SteamGameServerStats001"; + public const string STEAMHTMLSURFACE_INTERFACE_VERSION = "STEAMHTMLSURFACE_INTERFACE_VERSION_005"; + public const string STEAMHTTP_INTERFACE_VERSION = "STEAMHTTP_INTERFACE_VERSION003"; + public const string STEAMINPUT_INTERFACE_VERSION = "SteamInput006"; + public const string STEAMINVENTORY_INTERFACE_VERSION = "STEAMINVENTORY_INTERFACE_V003"; + public const string STEAMMATCHMAKING_INTERFACE_VERSION = "SteamMatchMaking009"; + public const string STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION = "SteamMatchMakingServers002"; + public const string STEAMGAMESEARCH_INTERFACE_VERSION = "SteamMatchGameSearch001"; + public const string STEAMPARTIES_INTERFACE_VERSION = "SteamParties002"; + public const string STEAMMUSIC_INTERFACE_VERSION = "STEAMMUSIC_INTERFACE_VERSION001"; + public const string STEAMMUSICREMOTE_INTERFACE_VERSION = "STEAMMUSICREMOTE_INTERFACE_VERSION001"; + public const string STEAMNETWORKING_INTERFACE_VERSION = "SteamNetworking006"; + public const string STEAMNETWORKINGMESSAGES_INTERFACE_VERSION = "SteamNetworkingMessages002"; + // Silence some warnings + public const string STEAMNETWORKINGSOCKETS_INTERFACE_VERSION = "SteamNetworkingSockets012"; + // Silence some warnings + public const string STEAMNETWORKINGUTILS_INTERFACE_VERSION = "SteamNetworkingUtils004"; + public const string STEAMPARENTALSETTINGS_INTERFACE_VERSION = "STEAMPARENTALSETTINGS_INTERFACE_VERSION001"; + public const string STEAMREMOTEPLAY_INTERFACE_VERSION = "STEAMREMOTEPLAY_INTERFACE_VERSION001"; + public const string STEAMREMOTESTORAGE_INTERFACE_VERSION = "STEAMREMOTESTORAGE_INTERFACE_VERSION016"; + public const string STEAMSCREENSHOTS_INTERFACE_VERSION = "STEAMSCREENSHOTS_INTERFACE_VERSION003"; + public const string STEAMUGC_INTERFACE_VERSION = "STEAMUGC_INTERFACE_VERSION017"; + public const string STEAMUSER_INTERFACE_VERSION = "SteamUser023"; + public const string STEAMUSERSTATS_INTERFACE_VERSION = "STEAMUSERSTATS_INTERFACE_VERSION012"; + public const string STEAMUTILS_INTERFACE_VERSION = "SteamUtils010"; + public const string STEAMVIDEO_INTERFACE_VERSION = "STEAMVIDEO_INTERFACE_V002"; + public const int k_cubAppProofOfPurchaseKeyMax = 240; // max supported length of a legacy cd key + // maximum length of friend group name (not including terminating nul!) + public const int k_cchMaxFriendsGroupName = 64; + // maximum number of groups a single user is allowed + public const int k_cFriendsGroupLimit = 100; + public const int k_cEnumerateFollowersMax = 50; + // maximum number of characters in a user's name. Two flavors; one for UTF-8 and one for UTF-16. + // The UTF-8 version has to be very generous to accomodate characters that get large when encoded + // in UTF-8. + public const int k_cchPersonaNameMax = 128; + public const int k_cwchPersonaNameMax = 32; + // size limit on chat room or member metadata + public const int k_cubChatMetadataMax = 8192; + // size limits on Rich Presence data + public const int k_cchMaxRichPresenceKeys = 30; + public const int k_cchMaxRichPresenceKeyLength = 64; + public const int k_cchMaxRichPresenceValueLength = 256; + // game server flags + public const int k_unFavoriteFlagNone = 0x00; + public const int k_unFavoriteFlagFavorite = 0x01; // this game favorite entry is for the favorites list + public const int k_unFavoriteFlagHistory = 0x02; // this game favorite entry is for the history list + //----------------------------------------------------------------------------- + // Purpose: Defines the largest allowed file size. Cloud files cannot be written + // in a single chunk over 100MB (and cannot be over 200MB total.) + //----------------------------------------------------------------------------- + public const int k_unMaxCloudFileChunkSize = 100 * 1024 * 1024; + public const int k_cchPublishedDocumentTitleMax = 128 + 1; + public const int k_cchPublishedDocumentDescriptionMax = 8000; + public const int k_cchPublishedDocumentChangeDescriptionMax = 8000; + public const int k_unEnumeratePublishedFilesMaxResults = 50; + public const int k_cchTagListMax = 1024 + 1; + public const int k_cchFilenameMax = 260; + public const int k_cchPublishedFileURLMax = 256; + public const int k_nScreenshotMaxTaggedUsers = 32; + public const int k_nScreenshotMaxTaggedPublishedFiles = 32; + public const int k_cubUFSTagTypeMax = 255; + public const int k_cubUFSTagValueMax = 255; + // Required with of a thumbnail provided to AddScreenshotToLibrary. If you do not provide a thumbnail + // one will be generated. + public const int k_ScreenshotThumbWidth = 200; + public const int kNumUGCResultsPerPage = 50; + public const int k_cchDeveloperMetadataMax = 5000; + public const int k_nCubTicketMaxLength = 2560; + // size limit on stat or achievement name (UTF-8 encoded) + public const int k_cchStatNameMax = 128; + // maximum number of bytes for a leaderboard name (UTF-8 encoded) + public const int k_cchLeaderboardNameMax = 128; + // maximum number of details int32's storable for a single leaderboard entry + public const int k_cLeaderboardDetailsMax = 64; + // + // Max size (in bytes of UTF-8 data, not in characters) of server fields, including null terminator. + // WARNING: These cannot be changed easily, without breaking clients using old interfaces. + // + public const int k_cbMaxGameServerGameDir = 32; + public const int k_cbMaxGameServerMapName = 32; + public const int k_cbMaxGameServerGameDescription = 64; + public const int k_cbMaxGameServerName = 64; + public const int k_cbMaxGameServerTags = 128; + public const int k_cbMaxGameServerGameData = 2048; + // Forward declare types + //----------------------------------------------------------------------------- + // Purpose: Base values for callback identifiers, each callback must + // have a unique ID. + //----------------------------------------------------------------------------- + public const int k_iSteamUserCallbacks = 100; + public const int k_iSteamGameServerCallbacks = 200; + public const int k_iSteamFriendsCallbacks = 300; + public const int k_iSteamBillingCallbacks = 400; + public const int k_iSteamMatchmakingCallbacks = 500; + public const int k_iSteamContentServerCallbacks = 600; + public const int k_iSteamUtilsCallbacks = 700; + public const int k_iSteamAppsCallbacks = 1000; + public const int k_iSteamUserStatsCallbacks = 1100; + public const int k_iSteamNetworkingCallbacks = 1200; + public const int k_iSteamNetworkingSocketsCallbacks = 1220; + public const int k_iSteamNetworkingMessagesCallbacks = 1250; + public const int k_iSteamNetworkingUtilsCallbacks = 1280; + public const int k_iSteamRemoteStorageCallbacks = 1300; + public const int k_iSteamGameServerItemsCallbacks = 1500; + public const int k_iSteamGameCoordinatorCallbacks = 1700; + public const int k_iSteamGameServerStatsCallbacks = 1800; + public const int k_iSteam2AsyncCallbacks = 1900; + public const int k_iSteamGameStatsCallbacks = 2000; + public const int k_iSteamHTTPCallbacks = 2100; + public const int k_iSteamScreenshotsCallbacks = 2300; + // NOTE: 2500-2599 are reserved + public const int k_iSteamStreamLauncherCallbacks = 2600; + public const int k_iSteamControllerCallbacks = 2800; + public const int k_iSteamUGCCallbacks = 3400; + public const int k_iSteamStreamClientCallbacks = 3500; + public const int k_iSteamAppListCallbacks = 3900; + public const int k_iSteamMusicCallbacks = 4000; + public const int k_iSteamMusicRemoteCallbacks = 4100; + public const int k_iSteamGameNotificationCallbacks = 4400; + public const int k_iSteamHTMLSurfaceCallbacks = 4500; + public const int k_iSteamVideoCallbacks = 4600; + public const int k_iSteamInventoryCallbacks = 4700; + public const int k_ISteamParentalSettingsCallbacks = 5000; + public const int k_iSteamGameSearchCallbacks = 5200; + public const int k_iSteamPartiesCallbacks = 5300; + public const int k_iSteamSTARCallbacks = 5500; + public const int k_iSteamRemotePlayCallbacks = 5700; + public const int k_iSteamChatCallbacks = 5900; + /// Pass to SteamGameServer_Init to indicate that the same UDP port will be used for game traffic + /// UDP queries for server browser pings and LAN discovery. In this case, Steam will not open up a + /// socket to handle server browser queries, and you must use ISteamGameServer::HandleIncomingPacket + /// and ISteamGameServer::GetNextOutgoingPacket to handle packets related to server discovery on your socket. + public const ushort STEAMGAMESERVER_QUERY_PORT_SHARED = 0xffff; + public const int k_unSteamAccountIDMask = -1; + public const int k_unSteamAccountInstanceMask = 0x000FFFFF; + public const int k_unSteamUserDefaultInstance = 1; // fixed instance for all individual users + public const int k_cchGameExtraInfoMax = 64; + public const int k_nSteamEncryptedAppTicketSymmetricKeyLen = 32; + /// Port number(s) assigned to us. Only the first entries will contain + /// nonzero values. Entries corresponding to ports beyond what was + /// allocated for you will be zero. + /// + /// (NOTE: At the time of this writing, the maximum number of ports you may + /// request is 4.) + public const int k_nMaxReturnPorts = 8; + /// Max length of diagnostic error message + public const int k_cchMaxSteamNetworkingErrMsg = 1024; + /// Max length, in bytes (including null terminator) of the reason string + /// when a connection is closed. + public const int k_cchSteamNetworkingMaxConnectionCloseReason = 128; + /// Max length, in bytes (include null terminator) of debug description + /// of a connection. + public const int k_cchSteamNetworkingMaxConnectionDescription = 128; + /// Max length of the app's part of the description + public const int k_cchSteamNetworkingMaxConnectionAppName = 32; + public const int k_nSteamNetworkConnectionInfoFlags_Unauthenticated = 1; // We don't have a certificate for the remote host. + public const int k_nSteamNetworkConnectionInfoFlags_Unencrypted = 2; // Information is being sent out over a wire unencrypted (by this library) + public const int k_nSteamNetworkConnectionInfoFlags_LoopbackBuffers = 4; // Internal loopback buffers. Won't be true for localhost. (You can check the address to determine that.) This implies k_nSteamNetworkConnectionInfoFlags_FastLAN + public const int k_nSteamNetworkConnectionInfoFlags_Fast = 8; // The connection is "fast" and "reliable". Either internal/localhost (check the address to find out), or the peer is on the same LAN. (Probably. It's based on the address and the ping time, this is actually hard to determine unambiguously). + public const int k_nSteamNetworkConnectionInfoFlags_Relayed = 16; // The connection is relayed somehow (SDR or TURN). + public const int k_nSteamNetworkConnectionInfoFlags_DualWifi = 32; // We're taking advantage of dual-wifi multi-path + // + // Network messages + // + /// Max size of a single message that we can SEND. + /// Note: We might be wiling to receive larger messages, + /// and our peer might, too. + public const int k_cbMaxSteamNetworkingSocketsMessageSizeSend = 512 * 1024; + // + // Flags used to set options for message sending + // + // Send the message unreliably. Can be lost. Messages *can* be larger than a + // single MTU (UDP packet), but there is no retransmission, so if any piece + // of the message is lost, the entire message will be dropped. + // + // The sending API does have some knowledge of the underlying connection, so + // if there is no NAT-traversal accomplished or there is a recognized adjustment + // happening on the connection, the packet will be batched until the connection + // is open again. + // + // Migration note: This is not exactly the same as k_EP2PSendUnreliable! You + // probably want k_ESteamNetworkingSendType_UnreliableNoNagle + public const int k_nSteamNetworkingSend_Unreliable = 0; + // Disable Nagle's algorithm. + // By default, Nagle's algorithm is applied to all outbound messages. This means + // that the message will NOT be sent immediately, in case further messages are + // sent soon after you send this, which can be grouped together. Any time there + // is enough buffered data to fill a packet, the packets will be pushed out immediately, + // but partially-full packets not be sent until the Nagle timer expires. See + // ISteamNetworkingSockets::FlushMessagesOnConnection, ISteamNetworkingMessages::FlushMessagesToUser + // + // NOTE: Don't just send every message without Nagle because you want packets to get there + // quicker. Make sure you understand the problem that Nagle is solving before disabling it. + // If you are sending small messages, often many at the same time, then it is very likely that + // it will be more efficient to leave Nagle enabled. A typical proper use of this flag is + // when you are sending what you know will be the last message sent for a while (e.g. the last + // in the server simulation tick to a particular client), and you use this flag to flush all + // messages. + public const int k_nSteamNetworkingSend_NoNagle = 1; + // Send a message unreliably, bypassing Nagle's algorithm for this message and any messages + // currently pending on the Nagle timer. This is equivalent to using k_ESteamNetworkingSend_Unreliable + // and then immediately flushing the messages using ISteamNetworkingSockets::FlushMessagesOnConnection + // or ISteamNetworkingMessages::FlushMessagesToUser. (But using this flag is more efficient since you + // only make one API call.) + public const int k_nSteamNetworkingSend_UnreliableNoNagle = k_nSteamNetworkingSend_Unreliable|k_nSteamNetworkingSend_NoNagle; + // If the message cannot be sent very soon (because the connection is still doing some initial + // handshaking, route negotiations, etc), then just drop it. This is only applicable for unreliable + // messages. Using this flag on reliable messages is invalid. + public const int k_nSteamNetworkingSend_NoDelay = 4; + // Send an unreliable message, but if it cannot be sent relatively quickly, just drop it instead of queuing it. + // This is useful for messages that are not useful if they are excessively delayed, such as voice data. + // NOTE: The Nagle algorithm is not used, and if the message is not dropped, any messages waiting on the + // Nagle timer are immediately flushed. + // + // A message will be dropped under the following circumstances: + // - the connection is not fully connected. (E.g. the "Connecting" or "FindingRoute" states) + // - there is a sufficiently large number of messages queued up already such that the current message + // will not be placed on the wire in the next ~200ms or so. + // + // If a message is dropped for these reasons, k_EResultIgnored will be returned. + public const int k_nSteamNetworkingSend_UnreliableNoDelay = k_nSteamNetworkingSend_Unreliable|k_nSteamNetworkingSend_NoDelay|k_nSteamNetworkingSend_NoNagle; + // Reliable message send. Can send up to k_cbMaxSteamNetworkingSocketsMessageSizeSend bytes in a single message. + // Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for + // efficient sends of large chunks of data. + // + // The Nagle algorithm is used. See notes on k_ESteamNetworkingSendType_Unreliable for more details. + // See k_ESteamNetworkingSendType_ReliableNoNagle, ISteamNetworkingSockets::FlushMessagesOnConnection, + // ISteamNetworkingMessages::FlushMessagesToUser + // + // Migration note: This is NOT the same as k_EP2PSendReliable, it's more like k_EP2PSendReliableWithBuffering + public const int k_nSteamNetworkingSend_Reliable = 8; + // Send a message reliably, but bypass Nagle's algorithm. + // + // Migration note: This is equivalent to k_EP2PSendReliable + public const int k_nSteamNetworkingSend_ReliableNoNagle = k_nSteamNetworkingSend_Reliable|k_nSteamNetworkingSend_NoNagle; + // By default, message sending is queued, and the work of encryption and talking to + // the operating system sockets, etc is done on a service thread. This is usually a + // a performance win when messages are sent from the "main thread". However, if this + // flag is set, and data is ready to be sent immediately (either from this message + // or earlier queued data), then that work will be done in the current thread, before + // the current call returns. If data is not ready to be sent (due to rate limiting + // or Nagle), then this flag has no effect. + // + // This is an advanced flag used to control performance at a very low level. For + // most applications running on modern hardware with more than one CPU core, doing + // the work of sending on a service thread will yield the best performance. Only + // use this flag if you have a really good reason and understand what you are doing. + // Otherwise you will probably just make performance worse. + public const int k_nSteamNetworkingSend_UseCurrentThread = 16; + // When sending a message using ISteamNetworkingMessages, automatically re-establish + // a broken session, without returning k_EResultNoConnection. Without this flag, + // if you attempt to send a message, and the session was proactively closed by the + // peer, or an error occurred that disrupted communications, then you must close the + // session using ISteamNetworkingMessages::CloseSessionWithUser before attempting to + // send another message. (Or you can simply add this flag and retry.) In this way, + // the disruption cannot go unnoticed, and a more clear order of events can be + // ascertained. This is especially important when reliable messages are used, since + // if the connection is disrupted, some of those messages will not have been delivered, + // and it is in general not possible to know which. Although a + // SteamNetworkingMessagesSessionFailed_t callback will be posted when an error occurs + // to notify you that a failure has happened, callbacks are asynchronous, so it is not + // possible to tell exactly when it happened. And because the primary purpose of + // ISteamNetworkingMessages is to be like UDP, there is no notification when a peer closes + // the session. + // + // If you are not using any reliable messages (e.g. you are using ISteamNetworkingMessages + // exactly as a transport replacement for UDP-style datagrams only), you may not need to + // know when an underlying connection fails, and so you may not need this notification. + public const int k_nSteamNetworkingSend_AutoRestartBrokenSession = 32; + /// Max possible length of a ping location, in string format. This is + /// an extremely conservative worst case value which leaves room for future + /// syntax enhancements. Most strings in practice are a lot shorter. + /// If you are storing many of these, you will very likely benefit from + /// using dynamic memory. + public const int k_cchMaxSteamNetworkingPingLocationString = 1024; + /// Special values that are returned by some functions that return a ping. + public const int k_nSteamNetworkingPing_Failed = -1; + public const int k_nSteamNetworkingPing_Unknown = -2; + // Bitmask of types to share + public const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Default = -1; // Special value - use user defaults + public const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Disable = 0; // Do not do any ICE work at all or share any IP addresses with peer + public const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Relay = 1; // Relayed connection via TURN server. + public const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Private = 2; // host addresses that appear to be link-local or RFC1918 addresses + public const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Public = 4; // STUN reflexive addresses, or host address that isn't a "private" address + public const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_All = 0x7fffffff; + public const ulong k_ulPartyBeaconIdInvalid = 0; + public const int INVALID_HTTPREQUEST_HANDLE = 0; + public const int STEAM_INPUT_MAX_COUNT = 16; + public const int STEAM_INPUT_MAX_ANALOG_ACTIONS = 24; + public const int STEAM_INPUT_MAX_DIGITAL_ACTIONS = 256; + public const int STEAM_INPUT_MAX_ORIGINS = 8; + public const int STEAM_INPUT_MAX_ACTIVE_LAYERS = 16; + // When sending an option to a specific controller handle, you can send to all devices via this command + public const ulong STEAM_INPUT_HANDLE_ALL_CONTROLLERS = 0xFFFFFFFFFFFFFFFF; + public const float STEAM_INPUT_MIN_ANALOG_ACTION_DATA = -1.0f; + public const float STEAM_INPUT_MAX_ANALOG_ACTION_DATA = 1.0f; + // maximum number of characters a lobby metadata key can be + public const byte k_nMaxLobbyKeyLength = 255; + public const int k_SteamMusicNameMaxLength = 255; + public const int k_SteamMusicPNGMaxLength = 65535; + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamConstants.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamConstants.cs.meta new file mode 100644 index 0000000..d5e07af --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamConstants.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: faa542b98284c9a40a8b61bf0977c97b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamEnums.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamEnums.cs new file mode 100644 index 0000000..bb31a82 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamEnums.cs @@ -0,0 +1,2787 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +using Flags = System.FlagsAttribute; + +namespace Steamworks { + //----------------------------------------------------------------------------- + // Purpose: set of relationships to other users + //----------------------------------------------------------------------------- + public enum EFriendRelationship : int { + k_EFriendRelationshipNone = 0, + k_EFriendRelationshipBlocked = 1, // this doesn't get stored; the user has just done an Ignore on an friendship invite + k_EFriendRelationshipRequestRecipient = 2, + k_EFriendRelationshipFriend = 3, + k_EFriendRelationshipRequestInitiator = 4, + k_EFriendRelationshipIgnored = 5, // this is stored; the user has explicit blocked this other user from comments/chat/etc + k_EFriendRelationshipIgnoredFriend = 6, + k_EFriendRelationshipSuggested_DEPRECATED = 7, // was used by the original implementation of the facebook linking feature, but now unused. + + // keep this updated + k_EFriendRelationshipMax = 8, + } + + //----------------------------------------------------------------------------- + // Purpose: list of states a friend can be in + //----------------------------------------------------------------------------- + public enum EPersonaState : int { + k_EPersonaStateOffline = 0, // friend is not currently logged on + k_EPersonaStateOnline = 1, // friend is logged on + k_EPersonaStateBusy = 2, // user is on, but busy + k_EPersonaStateAway = 3, // auto-away feature + k_EPersonaStateSnooze = 4, // auto-away for a long time + k_EPersonaStateLookingToTrade = 5, // Online, trading + k_EPersonaStateLookingToPlay = 6, // Online, wanting to play + k_EPersonaStateInvisible = 7, // Online, but appears offline to friends. This status is never published to clients. + k_EPersonaStateMax, + } + + //----------------------------------------------------------------------------- + // Purpose: flags for enumerating friends list, or quickly checking a the relationship between users + //----------------------------------------------------------------------------- + [Flags] + public enum EFriendFlags : int { + k_EFriendFlagNone = 0x00, + k_EFriendFlagBlocked = 0x01, + k_EFriendFlagFriendshipRequested = 0x02, + k_EFriendFlagImmediate = 0x04, // "regular" friend + k_EFriendFlagClanMember = 0x08, + k_EFriendFlagOnGameServer = 0x10, + // k_EFriendFlagHasPlayedWith = 0x20, // not currently used + // k_EFriendFlagFriendOfFriend = 0x40, // not currently used + k_EFriendFlagRequestingFriendship = 0x80, + k_EFriendFlagRequestingInfo = 0x100, + k_EFriendFlagIgnored = 0x200, + k_EFriendFlagIgnoredFriend = 0x400, + // k_EFriendFlagSuggested = 0x800, // not used + k_EFriendFlagChatMember = 0x1000, + k_EFriendFlagAll = 0xFFFF, + } + + //----------------------------------------------------------------------------- + // Purpose: user restriction flags + //----------------------------------------------------------------------------- + public enum EUserRestriction : int { + k_nUserRestrictionNone = 0, // no known chat/content restriction + k_nUserRestrictionUnknown = 1, // we don't know yet (user offline) + k_nUserRestrictionAnyChat = 2, // user is not allowed to (or can't) send/recv any chat + k_nUserRestrictionVoiceChat = 4, // user is not allowed to (or can't) send/recv voice chat + k_nUserRestrictionGroupChat = 8, // user is not allowed to (or can't) send/recv group chat + k_nUserRestrictionRating = 16, // user is too young according to rating in current region + k_nUserRestrictionGameInvites = 32, // user cannot send or recv game invites (e.g. mobile) + k_nUserRestrictionTrading = 64, // user cannot participate in trading (console, mobile) + } + + // These values are passed as parameters to the store + public enum EOverlayToStoreFlag : int { + k_EOverlayToStoreFlag_None = 0, + k_EOverlayToStoreFlag_AddToCart = 1, + k_EOverlayToStoreFlag_AddToCartAndShow = 2, + } + + //----------------------------------------------------------------------------- + // Purpose: Tells Steam where to place the browser window inside the overlay + //----------------------------------------------------------------------------- + public enum EActivateGameOverlayToWebPageMode : int { + k_EActivateGameOverlayToWebPageMode_Default = 0, // Browser will open next to all other windows that the user has open in the overlay. + // The window will remain open, even if the user closes then re-opens the overlay. + + k_EActivateGameOverlayToWebPageMode_Modal = 1 // Browser will be opened in a special overlay configuration which hides all other windows + // that the user has open in the overlay. When the user closes the overlay, the browser window + // will also close. When the user closes the browser window, the overlay will automatically close. + } + + //----------------------------------------------------------------------------- + // Purpose: See GetProfileItemPropertyString and GetProfileItemPropertyUint + //----------------------------------------------------------------------------- + public enum ECommunityProfileItemType : int { + k_ECommunityProfileItemType_AnimatedAvatar = 0, + k_ECommunityProfileItemType_AvatarFrame = 1, + k_ECommunityProfileItemType_ProfileModifier = 2, + k_ECommunityProfileItemType_ProfileBackground = 3, + k_ECommunityProfileItemType_MiniProfileBackground = 4, + } + + public enum ECommunityProfileItemProperty : int { + k_ECommunityProfileItemProperty_ImageSmall = 0, // string + k_ECommunityProfileItemProperty_ImageLarge = 1, // string + k_ECommunityProfileItemProperty_InternalName = 2, // string + k_ECommunityProfileItemProperty_Title = 3, // string + k_ECommunityProfileItemProperty_Description = 4, // string + k_ECommunityProfileItemProperty_AppID = 5, // uint32 + k_ECommunityProfileItemProperty_TypeID = 6, // uint32 + k_ECommunityProfileItemProperty_Class = 7, // uint32 + k_ECommunityProfileItemProperty_MovieWebM = 8, // string + k_ECommunityProfileItemProperty_MovieMP4 = 9, // string + k_ECommunityProfileItemProperty_MovieWebMSmall = 10, // string + k_ECommunityProfileItemProperty_MovieMP4Small = 11, // string + } + + // used in PersonaStateChange_t::m_nChangeFlags to describe what's changed about a user + // these flags describe what the client has learned has changed recently, so on startup you'll see a name, avatar & relationship change for every friend + [Flags] + public enum EPersonaChange : int { + k_EPersonaChangeName = 0x0001, + k_EPersonaChangeStatus = 0x0002, + k_EPersonaChangeComeOnline = 0x0004, + k_EPersonaChangeGoneOffline = 0x0008, + k_EPersonaChangeGamePlayed = 0x0010, + k_EPersonaChangeGameServer = 0x0020, + k_EPersonaChangeAvatar = 0x0040, + k_EPersonaChangeJoinedSource= 0x0080, + k_EPersonaChangeLeftSource = 0x0100, + k_EPersonaChangeRelationshipChanged = 0x0200, + k_EPersonaChangeNameFirstSet = 0x0400, + k_EPersonaChangeBroadcast = 0x0800, + k_EPersonaChangeNickname = 0x1000, + k_EPersonaChangeSteamLevel = 0x2000, + k_EPersonaChangeRichPresence = 0x4000, + } + + // list of possible return values from the ISteamGameCoordinator API + public enum EGCResults : int { + k_EGCResultOK = 0, + k_EGCResultNoMessage = 1, // There is no message in the queue + k_EGCResultBufferTooSmall = 2, // The buffer is too small for the requested message + k_EGCResultNotLoggedOn = 3, // The client is not logged onto Steam + k_EGCResultInvalidMessage = 4, // Something was wrong with the message being sent with SendMessage + } + + public enum EHTMLMouseButton : int { + eHTMLMouseButton_Left = 0, + eHTMLMouseButton_Right = 1, + eHTMLMouseButton_Middle = 2, + } + + public enum EMouseCursor : int { + dc_user = 0, + dc_none, + dc_arrow, + dc_ibeam, + dc_hourglass, + dc_waitarrow, + dc_crosshair, + dc_up, + dc_sizenw, + dc_sizese, + dc_sizene, + dc_sizesw, + dc_sizew, + dc_sizee, + dc_sizen, + dc_sizes, + dc_sizewe, + dc_sizens, + dc_sizeall, + dc_no, + dc_hand, + dc_blank, // don't show any custom cursor, just use your default + dc_middle_pan, + dc_north_pan, + dc_north_east_pan, + dc_east_pan, + dc_south_east_pan, + dc_south_pan, + dc_south_west_pan, + dc_west_pan, + dc_north_west_pan, + dc_alias, + dc_cell, + dc_colresize, + dc_copycur, + dc_verticaltext, + dc_rowresize, + dc_zoomin, + dc_zoomout, + dc_help, + dc_custom, + + dc_last, // custom cursors start from this value and up + } + + [Flags] + public enum EHTMLKeyModifiers : int { + k_eHTMLKeyModifier_None = 0, + k_eHTMLKeyModifier_AltDown = 1 << 0, + k_eHTMLKeyModifier_CtrlDown = 1 << 1, + k_eHTMLKeyModifier_ShiftDown = 1 << 2, + } + + public enum EInputSourceMode : int { + k_EInputSourceMode_None, + k_EInputSourceMode_Dpad, + k_EInputSourceMode_Buttons, + k_EInputSourceMode_FourButtons, + k_EInputSourceMode_AbsoluteMouse, + k_EInputSourceMode_RelativeMouse, + k_EInputSourceMode_JoystickMove, + k_EInputSourceMode_JoystickMouse, + k_EInputSourceMode_JoystickCamera, + k_EInputSourceMode_ScrollWheel, + k_EInputSourceMode_Trigger, + k_EInputSourceMode_TouchMenu, + k_EInputSourceMode_MouseJoystick, + k_EInputSourceMode_MouseRegion, + k_EInputSourceMode_RadialMenu, + k_EInputSourceMode_SingleButton, + k_EInputSourceMode_Switches + } + + // Note: Please do not use action origins as a way to identify controller types. There is no + // guarantee that they will be added in a contiguous manner - use GetInputTypeForHandle instead. + // Versions of Steam that add new controller types in the future will extend this enum so if you're + // using a lookup table please check the bounds of any origins returned by Steam. + public enum EInputActionOrigin : int { + // Steam Controller + k_EInputActionOrigin_None, + k_EInputActionOrigin_SteamController_A, + k_EInputActionOrigin_SteamController_B, + k_EInputActionOrigin_SteamController_X, + k_EInputActionOrigin_SteamController_Y, + k_EInputActionOrigin_SteamController_LeftBumper, + k_EInputActionOrigin_SteamController_RightBumper, + k_EInputActionOrigin_SteamController_LeftGrip, + k_EInputActionOrigin_SteamController_RightGrip, + k_EInputActionOrigin_SteamController_Start, + k_EInputActionOrigin_SteamController_Back, + k_EInputActionOrigin_SteamController_LeftPad_Touch, + k_EInputActionOrigin_SteamController_LeftPad_Swipe, + k_EInputActionOrigin_SteamController_LeftPad_Click, + k_EInputActionOrigin_SteamController_LeftPad_DPadNorth, + k_EInputActionOrigin_SteamController_LeftPad_DPadSouth, + k_EInputActionOrigin_SteamController_LeftPad_DPadWest, + k_EInputActionOrigin_SteamController_LeftPad_DPadEast, + k_EInputActionOrigin_SteamController_RightPad_Touch, + k_EInputActionOrigin_SteamController_RightPad_Swipe, + k_EInputActionOrigin_SteamController_RightPad_Click, + k_EInputActionOrigin_SteamController_RightPad_DPadNorth, + k_EInputActionOrigin_SteamController_RightPad_DPadSouth, + k_EInputActionOrigin_SteamController_RightPad_DPadWest, + k_EInputActionOrigin_SteamController_RightPad_DPadEast, + k_EInputActionOrigin_SteamController_LeftTrigger_Pull, + k_EInputActionOrigin_SteamController_LeftTrigger_Click, + k_EInputActionOrigin_SteamController_RightTrigger_Pull, + k_EInputActionOrigin_SteamController_RightTrigger_Click, + k_EInputActionOrigin_SteamController_LeftStick_Move, + k_EInputActionOrigin_SteamController_LeftStick_Click, + k_EInputActionOrigin_SteamController_LeftStick_DPadNorth, + k_EInputActionOrigin_SteamController_LeftStick_DPadSouth, + k_EInputActionOrigin_SteamController_LeftStick_DPadWest, + k_EInputActionOrigin_SteamController_LeftStick_DPadEast, + k_EInputActionOrigin_SteamController_Gyro_Move, + k_EInputActionOrigin_SteamController_Gyro_Pitch, + k_EInputActionOrigin_SteamController_Gyro_Yaw, + k_EInputActionOrigin_SteamController_Gyro_Roll, + k_EInputActionOrigin_SteamController_Reserved0, + k_EInputActionOrigin_SteamController_Reserved1, + k_EInputActionOrigin_SteamController_Reserved2, + k_EInputActionOrigin_SteamController_Reserved3, + k_EInputActionOrigin_SteamController_Reserved4, + k_EInputActionOrigin_SteamController_Reserved5, + k_EInputActionOrigin_SteamController_Reserved6, + k_EInputActionOrigin_SteamController_Reserved7, + k_EInputActionOrigin_SteamController_Reserved8, + k_EInputActionOrigin_SteamController_Reserved9, + k_EInputActionOrigin_SteamController_Reserved10, + + // PS4 Dual Shock + k_EInputActionOrigin_PS4_X, + k_EInputActionOrigin_PS4_Circle, + k_EInputActionOrigin_PS4_Triangle, + k_EInputActionOrigin_PS4_Square, + k_EInputActionOrigin_PS4_LeftBumper, + k_EInputActionOrigin_PS4_RightBumper, + k_EInputActionOrigin_PS4_Options, //Start + k_EInputActionOrigin_PS4_Share, //Back + k_EInputActionOrigin_PS4_LeftPad_Touch, + k_EInputActionOrigin_PS4_LeftPad_Swipe, + k_EInputActionOrigin_PS4_LeftPad_Click, + k_EInputActionOrigin_PS4_LeftPad_DPadNorth, + k_EInputActionOrigin_PS4_LeftPad_DPadSouth, + k_EInputActionOrigin_PS4_LeftPad_DPadWest, + k_EInputActionOrigin_PS4_LeftPad_DPadEast, + k_EInputActionOrigin_PS4_RightPad_Touch, + k_EInputActionOrigin_PS4_RightPad_Swipe, + k_EInputActionOrigin_PS4_RightPad_Click, + k_EInputActionOrigin_PS4_RightPad_DPadNorth, + k_EInputActionOrigin_PS4_RightPad_DPadSouth, + k_EInputActionOrigin_PS4_RightPad_DPadWest, + k_EInputActionOrigin_PS4_RightPad_DPadEast, + k_EInputActionOrigin_PS4_CenterPad_Touch, + k_EInputActionOrigin_PS4_CenterPad_Swipe, + k_EInputActionOrigin_PS4_CenterPad_Click, + k_EInputActionOrigin_PS4_CenterPad_DPadNorth, + k_EInputActionOrigin_PS4_CenterPad_DPadSouth, + k_EInputActionOrigin_PS4_CenterPad_DPadWest, + k_EInputActionOrigin_PS4_CenterPad_DPadEast, + k_EInputActionOrigin_PS4_LeftTrigger_Pull, + k_EInputActionOrigin_PS4_LeftTrigger_Click, + k_EInputActionOrigin_PS4_RightTrigger_Pull, + k_EInputActionOrigin_PS4_RightTrigger_Click, + k_EInputActionOrigin_PS4_LeftStick_Move, + k_EInputActionOrigin_PS4_LeftStick_Click, + k_EInputActionOrigin_PS4_LeftStick_DPadNorth, + k_EInputActionOrigin_PS4_LeftStick_DPadSouth, + k_EInputActionOrigin_PS4_LeftStick_DPadWest, + k_EInputActionOrigin_PS4_LeftStick_DPadEast, + k_EInputActionOrigin_PS4_RightStick_Move, + k_EInputActionOrigin_PS4_RightStick_Click, + k_EInputActionOrigin_PS4_RightStick_DPadNorth, + k_EInputActionOrigin_PS4_RightStick_DPadSouth, + k_EInputActionOrigin_PS4_RightStick_DPadWest, + k_EInputActionOrigin_PS4_RightStick_DPadEast, + k_EInputActionOrigin_PS4_DPad_North, + k_EInputActionOrigin_PS4_DPad_South, + k_EInputActionOrigin_PS4_DPad_West, + k_EInputActionOrigin_PS4_DPad_East, + k_EInputActionOrigin_PS4_Gyro_Move, + k_EInputActionOrigin_PS4_Gyro_Pitch, + k_EInputActionOrigin_PS4_Gyro_Yaw, + k_EInputActionOrigin_PS4_Gyro_Roll, + k_EInputActionOrigin_PS4_DPad_Move, + k_EInputActionOrigin_PS4_Reserved1, + k_EInputActionOrigin_PS4_Reserved2, + k_EInputActionOrigin_PS4_Reserved3, + k_EInputActionOrigin_PS4_Reserved4, + k_EInputActionOrigin_PS4_Reserved5, + k_EInputActionOrigin_PS4_Reserved6, + k_EInputActionOrigin_PS4_Reserved7, + k_EInputActionOrigin_PS4_Reserved8, + k_EInputActionOrigin_PS4_Reserved9, + k_EInputActionOrigin_PS4_Reserved10, + + // XBox One + k_EInputActionOrigin_XBoxOne_A, + k_EInputActionOrigin_XBoxOne_B, + k_EInputActionOrigin_XBoxOne_X, + k_EInputActionOrigin_XBoxOne_Y, + k_EInputActionOrigin_XBoxOne_LeftBumper, + k_EInputActionOrigin_XBoxOne_RightBumper, + k_EInputActionOrigin_XBoxOne_Menu, //Start + k_EInputActionOrigin_XBoxOne_View, //Back + k_EInputActionOrigin_XBoxOne_LeftTrigger_Pull, + k_EInputActionOrigin_XBoxOne_LeftTrigger_Click, + k_EInputActionOrigin_XBoxOne_RightTrigger_Pull, + k_EInputActionOrigin_XBoxOne_RightTrigger_Click, + k_EInputActionOrigin_XBoxOne_LeftStick_Move, + k_EInputActionOrigin_XBoxOne_LeftStick_Click, + k_EInputActionOrigin_XBoxOne_LeftStick_DPadNorth, + k_EInputActionOrigin_XBoxOne_LeftStick_DPadSouth, + k_EInputActionOrigin_XBoxOne_LeftStick_DPadWest, + k_EInputActionOrigin_XBoxOne_LeftStick_DPadEast, + k_EInputActionOrigin_XBoxOne_RightStick_Move, + k_EInputActionOrigin_XBoxOne_RightStick_Click, + k_EInputActionOrigin_XBoxOne_RightStick_DPadNorth, + k_EInputActionOrigin_XBoxOne_RightStick_DPadSouth, + k_EInputActionOrigin_XBoxOne_RightStick_DPadWest, + k_EInputActionOrigin_XBoxOne_RightStick_DPadEast, + k_EInputActionOrigin_XBoxOne_DPad_North, + k_EInputActionOrigin_XBoxOne_DPad_South, + k_EInputActionOrigin_XBoxOne_DPad_West, + k_EInputActionOrigin_XBoxOne_DPad_East, + k_EInputActionOrigin_XBoxOne_DPad_Move, + k_EInputActionOrigin_XBoxOne_LeftGrip_Lower, + k_EInputActionOrigin_XBoxOne_LeftGrip_Upper, + k_EInputActionOrigin_XBoxOne_RightGrip_Lower, + k_EInputActionOrigin_XBoxOne_RightGrip_Upper, + k_EInputActionOrigin_XBoxOne_Share, // Xbox Series X controllers only + k_EInputActionOrigin_XBoxOne_Reserved6, + k_EInputActionOrigin_XBoxOne_Reserved7, + k_EInputActionOrigin_XBoxOne_Reserved8, + k_EInputActionOrigin_XBoxOne_Reserved9, + k_EInputActionOrigin_XBoxOne_Reserved10, + + // XBox 360 + k_EInputActionOrigin_XBox360_A, + k_EInputActionOrigin_XBox360_B, + k_EInputActionOrigin_XBox360_X, + k_EInputActionOrigin_XBox360_Y, + k_EInputActionOrigin_XBox360_LeftBumper, + k_EInputActionOrigin_XBox360_RightBumper, + k_EInputActionOrigin_XBox360_Start, //Start + k_EInputActionOrigin_XBox360_Back, //Back + k_EInputActionOrigin_XBox360_LeftTrigger_Pull, + k_EInputActionOrigin_XBox360_LeftTrigger_Click, + k_EInputActionOrigin_XBox360_RightTrigger_Pull, + k_EInputActionOrigin_XBox360_RightTrigger_Click, + k_EInputActionOrigin_XBox360_LeftStick_Move, + k_EInputActionOrigin_XBox360_LeftStick_Click, + k_EInputActionOrigin_XBox360_LeftStick_DPadNorth, + k_EInputActionOrigin_XBox360_LeftStick_DPadSouth, + k_EInputActionOrigin_XBox360_LeftStick_DPadWest, + k_EInputActionOrigin_XBox360_LeftStick_DPadEast, + k_EInputActionOrigin_XBox360_RightStick_Move, + k_EInputActionOrigin_XBox360_RightStick_Click, + k_EInputActionOrigin_XBox360_RightStick_DPadNorth, + k_EInputActionOrigin_XBox360_RightStick_DPadSouth, + k_EInputActionOrigin_XBox360_RightStick_DPadWest, + k_EInputActionOrigin_XBox360_RightStick_DPadEast, + k_EInputActionOrigin_XBox360_DPad_North, + k_EInputActionOrigin_XBox360_DPad_South, + k_EInputActionOrigin_XBox360_DPad_West, + k_EInputActionOrigin_XBox360_DPad_East, + k_EInputActionOrigin_XBox360_DPad_Move, + k_EInputActionOrigin_XBox360_Reserved1, + k_EInputActionOrigin_XBox360_Reserved2, + k_EInputActionOrigin_XBox360_Reserved3, + k_EInputActionOrigin_XBox360_Reserved4, + k_EInputActionOrigin_XBox360_Reserved5, + k_EInputActionOrigin_XBox360_Reserved6, + k_EInputActionOrigin_XBox360_Reserved7, + k_EInputActionOrigin_XBox360_Reserved8, + k_EInputActionOrigin_XBox360_Reserved9, + k_EInputActionOrigin_XBox360_Reserved10, + + + // Switch - Pro or Joycons used as a single input device. + // This does not apply to a single joycon + k_EInputActionOrigin_Switch_A, + k_EInputActionOrigin_Switch_B, + k_EInputActionOrigin_Switch_X, + k_EInputActionOrigin_Switch_Y, + k_EInputActionOrigin_Switch_LeftBumper, + k_EInputActionOrigin_Switch_RightBumper, + k_EInputActionOrigin_Switch_Plus, //Start + k_EInputActionOrigin_Switch_Minus, //Back + k_EInputActionOrigin_Switch_Capture, + k_EInputActionOrigin_Switch_LeftTrigger_Pull, + k_EInputActionOrigin_Switch_LeftTrigger_Click, + k_EInputActionOrigin_Switch_RightTrigger_Pull, + k_EInputActionOrigin_Switch_RightTrigger_Click, + k_EInputActionOrigin_Switch_LeftStick_Move, + k_EInputActionOrigin_Switch_LeftStick_Click, + k_EInputActionOrigin_Switch_LeftStick_DPadNorth, + k_EInputActionOrigin_Switch_LeftStick_DPadSouth, + k_EInputActionOrigin_Switch_LeftStick_DPadWest, + k_EInputActionOrigin_Switch_LeftStick_DPadEast, + k_EInputActionOrigin_Switch_RightStick_Move, + k_EInputActionOrigin_Switch_RightStick_Click, + k_EInputActionOrigin_Switch_RightStick_DPadNorth, + k_EInputActionOrigin_Switch_RightStick_DPadSouth, + k_EInputActionOrigin_Switch_RightStick_DPadWest, + k_EInputActionOrigin_Switch_RightStick_DPadEast, + k_EInputActionOrigin_Switch_DPad_North, + k_EInputActionOrigin_Switch_DPad_South, + k_EInputActionOrigin_Switch_DPad_West, + k_EInputActionOrigin_Switch_DPad_East, + k_EInputActionOrigin_Switch_ProGyro_Move, // Primary Gyro in Pro Controller, or Right JoyCon + k_EInputActionOrigin_Switch_ProGyro_Pitch, // Primary Gyro in Pro Controller, or Right JoyCon + k_EInputActionOrigin_Switch_ProGyro_Yaw, // Primary Gyro in Pro Controller, or Right JoyCon + k_EInputActionOrigin_Switch_ProGyro_Roll, // Primary Gyro in Pro Controller, or Right JoyCon + k_EInputActionOrigin_Switch_DPad_Move, + k_EInputActionOrigin_Switch_Reserved1, + k_EInputActionOrigin_Switch_Reserved2, + k_EInputActionOrigin_Switch_Reserved3, + k_EInputActionOrigin_Switch_Reserved4, + k_EInputActionOrigin_Switch_Reserved5, + k_EInputActionOrigin_Switch_Reserved6, + k_EInputActionOrigin_Switch_Reserved7, + k_EInputActionOrigin_Switch_Reserved8, + k_EInputActionOrigin_Switch_Reserved9, + k_EInputActionOrigin_Switch_Reserved10, + + // Switch JoyCon Specific + k_EInputActionOrigin_Switch_RightGyro_Move, // Right JoyCon Gyro generally should correspond to Pro's single gyro + k_EInputActionOrigin_Switch_RightGyro_Pitch, // Right JoyCon Gyro generally should correspond to Pro's single gyro + k_EInputActionOrigin_Switch_RightGyro_Yaw, // Right JoyCon Gyro generally should correspond to Pro's single gyro + k_EInputActionOrigin_Switch_RightGyro_Roll, // Right JoyCon Gyro generally should correspond to Pro's single gyro + k_EInputActionOrigin_Switch_LeftGyro_Move, + k_EInputActionOrigin_Switch_LeftGyro_Pitch, + k_EInputActionOrigin_Switch_LeftGyro_Yaw, + k_EInputActionOrigin_Switch_LeftGyro_Roll, + k_EInputActionOrigin_Switch_LeftGrip_Lower, // Left JoyCon SR Button + k_EInputActionOrigin_Switch_LeftGrip_Upper, // Left JoyCon SL Button + k_EInputActionOrigin_Switch_RightGrip_Lower, // Right JoyCon SL Button + k_EInputActionOrigin_Switch_RightGrip_Upper, // Right JoyCon SR Button + k_EInputActionOrigin_Switch_JoyConButton_N, // With a Horizontal JoyCon this will be Y or what would be Dpad Right when vertical + k_EInputActionOrigin_Switch_JoyConButton_E, // X + k_EInputActionOrigin_Switch_JoyConButton_S, // A + k_EInputActionOrigin_Switch_JoyConButton_W, // B + k_EInputActionOrigin_Switch_Reserved15, + k_EInputActionOrigin_Switch_Reserved16, + k_EInputActionOrigin_Switch_Reserved17, + k_EInputActionOrigin_Switch_Reserved18, + k_EInputActionOrigin_Switch_Reserved19, + k_EInputActionOrigin_Switch_Reserved20, + + // Added in SDK 1.51 + k_EInputActionOrigin_PS5_X, + k_EInputActionOrigin_PS5_Circle, + k_EInputActionOrigin_PS5_Triangle, + k_EInputActionOrigin_PS5_Square, + k_EInputActionOrigin_PS5_LeftBumper, + k_EInputActionOrigin_PS5_RightBumper, + k_EInputActionOrigin_PS5_Option, //Start + k_EInputActionOrigin_PS5_Create, //Back + k_EInputActionOrigin_PS5_Mute, + k_EInputActionOrigin_PS5_LeftPad_Touch, + k_EInputActionOrigin_PS5_LeftPad_Swipe, + k_EInputActionOrigin_PS5_LeftPad_Click, + k_EInputActionOrigin_PS5_LeftPad_DPadNorth, + k_EInputActionOrigin_PS5_LeftPad_DPadSouth, + k_EInputActionOrigin_PS5_LeftPad_DPadWest, + k_EInputActionOrigin_PS5_LeftPad_DPadEast, + k_EInputActionOrigin_PS5_RightPad_Touch, + k_EInputActionOrigin_PS5_RightPad_Swipe, + k_EInputActionOrigin_PS5_RightPad_Click, + k_EInputActionOrigin_PS5_RightPad_DPadNorth, + k_EInputActionOrigin_PS5_RightPad_DPadSouth, + k_EInputActionOrigin_PS5_RightPad_DPadWest, + k_EInputActionOrigin_PS5_RightPad_DPadEast, + k_EInputActionOrigin_PS5_CenterPad_Touch, + k_EInputActionOrigin_PS5_CenterPad_Swipe, + k_EInputActionOrigin_PS5_CenterPad_Click, + k_EInputActionOrigin_PS5_CenterPad_DPadNorth, + k_EInputActionOrigin_PS5_CenterPad_DPadSouth, + k_EInputActionOrigin_PS5_CenterPad_DPadWest, + k_EInputActionOrigin_PS5_CenterPad_DPadEast, + k_EInputActionOrigin_PS5_LeftTrigger_Pull, + k_EInputActionOrigin_PS5_LeftTrigger_Click, + k_EInputActionOrigin_PS5_RightTrigger_Pull, + k_EInputActionOrigin_PS5_RightTrigger_Click, + k_EInputActionOrigin_PS5_LeftStick_Move, + k_EInputActionOrigin_PS5_LeftStick_Click, + k_EInputActionOrigin_PS5_LeftStick_DPadNorth, + k_EInputActionOrigin_PS5_LeftStick_DPadSouth, + k_EInputActionOrigin_PS5_LeftStick_DPadWest, + k_EInputActionOrigin_PS5_LeftStick_DPadEast, + k_EInputActionOrigin_PS5_RightStick_Move, + k_EInputActionOrigin_PS5_RightStick_Click, + k_EInputActionOrigin_PS5_RightStick_DPadNorth, + k_EInputActionOrigin_PS5_RightStick_DPadSouth, + k_EInputActionOrigin_PS5_RightStick_DPadWest, + k_EInputActionOrigin_PS5_RightStick_DPadEast, + k_EInputActionOrigin_PS5_DPad_North, + k_EInputActionOrigin_PS5_DPad_South, + k_EInputActionOrigin_PS5_DPad_West, + k_EInputActionOrigin_PS5_DPad_East, + k_EInputActionOrigin_PS5_Gyro_Move, + k_EInputActionOrigin_PS5_Gyro_Pitch, + k_EInputActionOrigin_PS5_Gyro_Yaw, + k_EInputActionOrigin_PS5_Gyro_Roll, + k_EInputActionOrigin_PS5_DPad_Move, + k_EInputActionOrigin_PS5_LeftGrip, + k_EInputActionOrigin_PS5_RightGrip, + k_EInputActionOrigin_PS5_LeftFn, + k_EInputActionOrigin_PS5_RightFn, + k_EInputActionOrigin_PS5_Reserved5, + k_EInputActionOrigin_PS5_Reserved6, + k_EInputActionOrigin_PS5_Reserved7, + k_EInputActionOrigin_PS5_Reserved8, + k_EInputActionOrigin_PS5_Reserved9, + k_EInputActionOrigin_PS5_Reserved10, + k_EInputActionOrigin_PS5_Reserved11, + k_EInputActionOrigin_PS5_Reserved12, + k_EInputActionOrigin_PS5_Reserved13, + k_EInputActionOrigin_PS5_Reserved14, + k_EInputActionOrigin_PS5_Reserved15, + k_EInputActionOrigin_PS5_Reserved16, + k_EInputActionOrigin_PS5_Reserved17, + k_EInputActionOrigin_PS5_Reserved18, + k_EInputActionOrigin_PS5_Reserved19, + k_EInputActionOrigin_PS5_Reserved20, + + // Added in SDK 1.53 + k_EInputActionOrigin_SteamDeck_A, + k_EInputActionOrigin_SteamDeck_B, + k_EInputActionOrigin_SteamDeck_X, + k_EInputActionOrigin_SteamDeck_Y, + k_EInputActionOrigin_SteamDeck_L1, + k_EInputActionOrigin_SteamDeck_R1, + k_EInputActionOrigin_SteamDeck_Menu, + k_EInputActionOrigin_SteamDeck_View, + k_EInputActionOrigin_SteamDeck_LeftPad_Touch, + k_EInputActionOrigin_SteamDeck_LeftPad_Swipe, + k_EInputActionOrigin_SteamDeck_LeftPad_Click, + k_EInputActionOrigin_SteamDeck_LeftPad_DPadNorth, + k_EInputActionOrigin_SteamDeck_LeftPad_DPadSouth, + k_EInputActionOrigin_SteamDeck_LeftPad_DPadWest, + k_EInputActionOrigin_SteamDeck_LeftPad_DPadEast, + k_EInputActionOrigin_SteamDeck_RightPad_Touch, + k_EInputActionOrigin_SteamDeck_RightPad_Swipe, + k_EInputActionOrigin_SteamDeck_RightPad_Click, + k_EInputActionOrigin_SteamDeck_RightPad_DPadNorth, + k_EInputActionOrigin_SteamDeck_RightPad_DPadSouth, + k_EInputActionOrigin_SteamDeck_RightPad_DPadWest, + k_EInputActionOrigin_SteamDeck_RightPad_DPadEast, + k_EInputActionOrigin_SteamDeck_L2_SoftPull, + k_EInputActionOrigin_SteamDeck_L2, + k_EInputActionOrigin_SteamDeck_R2_SoftPull, + k_EInputActionOrigin_SteamDeck_R2, + k_EInputActionOrigin_SteamDeck_LeftStick_Move, + k_EInputActionOrigin_SteamDeck_L3, + k_EInputActionOrigin_SteamDeck_LeftStick_DPadNorth, + k_EInputActionOrigin_SteamDeck_LeftStick_DPadSouth, + k_EInputActionOrigin_SteamDeck_LeftStick_DPadWest, + k_EInputActionOrigin_SteamDeck_LeftStick_DPadEast, + k_EInputActionOrigin_SteamDeck_LeftStick_Touch, + k_EInputActionOrigin_SteamDeck_RightStick_Move, + k_EInputActionOrigin_SteamDeck_R3, + k_EInputActionOrigin_SteamDeck_RightStick_DPadNorth, + k_EInputActionOrigin_SteamDeck_RightStick_DPadSouth, + k_EInputActionOrigin_SteamDeck_RightStick_DPadWest, + k_EInputActionOrigin_SteamDeck_RightStick_DPadEast, + k_EInputActionOrigin_SteamDeck_RightStick_Touch, + k_EInputActionOrigin_SteamDeck_L4, + k_EInputActionOrigin_SteamDeck_R4, + k_EInputActionOrigin_SteamDeck_L5, + k_EInputActionOrigin_SteamDeck_R5, + k_EInputActionOrigin_SteamDeck_DPad_Move, + k_EInputActionOrigin_SteamDeck_DPad_North, + k_EInputActionOrigin_SteamDeck_DPad_South, + k_EInputActionOrigin_SteamDeck_DPad_West, + k_EInputActionOrigin_SteamDeck_DPad_East, + k_EInputActionOrigin_SteamDeck_Gyro_Move, + k_EInputActionOrigin_SteamDeck_Gyro_Pitch, + k_EInputActionOrigin_SteamDeck_Gyro_Yaw, + k_EInputActionOrigin_SteamDeck_Gyro_Roll, + k_EInputActionOrigin_SteamDeck_Reserved1, + k_EInputActionOrigin_SteamDeck_Reserved2, + k_EInputActionOrigin_SteamDeck_Reserved3, + k_EInputActionOrigin_SteamDeck_Reserved4, + k_EInputActionOrigin_SteamDeck_Reserved5, + k_EInputActionOrigin_SteamDeck_Reserved6, + k_EInputActionOrigin_SteamDeck_Reserved7, + k_EInputActionOrigin_SteamDeck_Reserved8, + k_EInputActionOrigin_SteamDeck_Reserved9, + k_EInputActionOrigin_SteamDeck_Reserved10, + k_EInputActionOrigin_SteamDeck_Reserved11, + k_EInputActionOrigin_SteamDeck_Reserved12, + k_EInputActionOrigin_SteamDeck_Reserved13, + k_EInputActionOrigin_SteamDeck_Reserved14, + k_EInputActionOrigin_SteamDeck_Reserved15, + k_EInputActionOrigin_SteamDeck_Reserved16, + k_EInputActionOrigin_SteamDeck_Reserved17, + k_EInputActionOrigin_SteamDeck_Reserved18, + k_EInputActionOrigin_SteamDeck_Reserved19, + k_EInputActionOrigin_SteamDeck_Reserved20, + + k_EInputActionOrigin_Count, // If Steam has added support for new controllers origins will go here. + k_EInputActionOrigin_MaximumPossibleValue = 32767, // Origins are currently a maximum of 16 bits. + } + + public enum EXboxOrigin : int { + k_EXboxOrigin_A, + k_EXboxOrigin_B, + k_EXboxOrigin_X, + k_EXboxOrigin_Y, + k_EXboxOrigin_LeftBumper, + k_EXboxOrigin_RightBumper, + k_EXboxOrigin_Menu, //Start + k_EXboxOrigin_View, //Back + k_EXboxOrigin_LeftTrigger_Pull, + k_EXboxOrigin_LeftTrigger_Click, + k_EXboxOrigin_RightTrigger_Pull, + k_EXboxOrigin_RightTrigger_Click, + k_EXboxOrigin_LeftStick_Move, + k_EXboxOrigin_LeftStick_Click, + k_EXboxOrigin_LeftStick_DPadNorth, + k_EXboxOrigin_LeftStick_DPadSouth, + k_EXboxOrigin_LeftStick_DPadWest, + k_EXboxOrigin_LeftStick_DPadEast, + k_EXboxOrigin_RightStick_Move, + k_EXboxOrigin_RightStick_Click, + k_EXboxOrigin_RightStick_DPadNorth, + k_EXboxOrigin_RightStick_DPadSouth, + k_EXboxOrigin_RightStick_DPadWest, + k_EXboxOrigin_RightStick_DPadEast, + k_EXboxOrigin_DPad_North, + k_EXboxOrigin_DPad_South, + k_EXboxOrigin_DPad_West, + k_EXboxOrigin_DPad_East, + k_EXboxOrigin_Count, + } + + public enum ESteamControllerPad : int { + k_ESteamControllerPad_Left, + k_ESteamControllerPad_Right + } + + [Flags] + public enum EControllerHapticLocation : int { + k_EControllerHapticLocation_Left = ( 1 << ESteamControllerPad.k_ESteamControllerPad_Left ), + k_EControllerHapticLocation_Right = ( 1 << ESteamControllerPad.k_ESteamControllerPad_Right ), + k_EControllerHapticLocation_Both = ( 1 << ESteamControllerPad.k_ESteamControllerPad_Left | 1 << ESteamControllerPad.k_ESteamControllerPad_Right ), + } + + public enum EControllerHapticType : int { + k_EControllerHapticType_Off, + k_EControllerHapticType_Tick, + k_EControllerHapticType_Click, + } + + public enum ESteamInputType : int { + k_ESteamInputType_Unknown, + k_ESteamInputType_SteamController, + k_ESteamInputType_XBox360Controller, + k_ESteamInputType_XBoxOneController, + k_ESteamInputType_GenericGamepad, // DirectInput controllers + k_ESteamInputType_PS4Controller, + k_ESteamInputType_AppleMFiController, // Unused + k_ESteamInputType_AndroidController, // Unused + k_ESteamInputType_SwitchJoyConPair, // Unused + k_ESteamInputType_SwitchJoyConSingle, // Unused + k_ESteamInputType_SwitchProController, + k_ESteamInputType_MobileTouch, // Steam Link App On-screen Virtual Controller + k_ESteamInputType_PS3Controller, // Currently uses PS4 Origins + k_ESteamInputType_PS5Controller, // Added in SDK 151 + k_ESteamInputType_SteamDeckController, // Added in SDK 153 + k_ESteamInputType_Count, + k_ESteamInputType_MaximumPossibleValue = 255, + } + + // Individual values are used by the GetSessionInputConfigurationSettings bitmask + public enum ESteamInputConfigurationEnableType : int { + k_ESteamInputConfigurationEnableType_None = 0x0000, + k_ESteamInputConfigurationEnableType_Playstation = 0x0001, + k_ESteamInputConfigurationEnableType_Xbox = 0x0002, + k_ESteamInputConfigurationEnableType_Generic = 0x0004, + k_ESteamInputConfigurationEnableType_Switch = 0x0008, + } + + // These values are passed into SetLEDColor + public enum ESteamInputLEDFlag : int { + k_ESteamInputLEDFlag_SetColor, + // Restore the LED color to the user's preference setting as set in the controller personalization menu. + // This also happens automatically on exit of your game. + k_ESteamInputLEDFlag_RestoreUserDefault + } + + // These values are passed into GetGlyphPNGForActionOrigin + public enum ESteamInputGlyphSize : int { + k_ESteamInputGlyphSize_Small, // 32x32 pixels + k_ESteamInputGlyphSize_Medium, // 128x128 pixels + k_ESteamInputGlyphSize_Large, // 256x256 pixels + k_ESteamInputGlyphSize_Count, + } + + public enum ESteamInputGlyphStyle : int { + // Base-styles - cannot mix + ESteamInputGlyphStyle_Knockout = 0x0, // Face buttons will have colored labels/outlines on a knocked out background + // Rest of inputs will have white detail/borders on a knocked out background + ESteamInputGlyphStyle_Light = 0x1, // Black detail/borders on a white background + ESteamInputGlyphStyle_Dark = 0x2, // White detail/borders on a black background + + // Modifiers + // Default ABXY/PS equivalent glyphs have a solid fill w/ color matching the physical buttons on the device + ESteamInputGlyphStyle_NeutralColorABXY = 0x10, // ABXY Buttons will match the base style color instead of their normal associated color + ESteamInputGlyphStyle_SolidABXY = 0x20, // ABXY Buttons will have a solid fill + } + + public enum ESteamInputActionEventType : int { + ESteamInputActionEventType_DigitalAction, + ESteamInputActionEventType_AnalogAction, + } + + [Flags] + public enum ESteamItemFlags : int { + // Item status flags - these flags are permanently attached to specific item instances + k_ESteamItemNoTrade = 1 << 0, // This item is account-locked and cannot be traded or given away. + + // Action confirmation flags - these flags are set one time only, as part of a result set + k_ESteamItemRemoved = 1 << 8, // The item has been destroyed, traded away, expired, or otherwise invalidated + k_ESteamItemConsumed = 1 << 9, // The item quantity has been decreased by 1 via ConsumeItem API. + + // All other flag bits are currently reserved for internal Steam use at this time. + // Do not assume anything about the state of other flags which are not defined here. + } + + // lobby type description + public enum ELobbyType : int { + k_ELobbyTypePrivate = 0, // only way to join the lobby is to invite to someone else + k_ELobbyTypeFriendsOnly = 1, // shows for friends or invitees, but not in lobby list + k_ELobbyTypePublic = 2, // visible for friends and in lobby list + k_ELobbyTypeInvisible = 3, // returned by search, but not visible to other friends + // useful if you want a user in two lobbies, for example matching groups together + // a user can be in only one regular lobby, and up to two invisible lobbies + k_ELobbyTypePrivateUnique = 4, // private, unique and does not delete when empty - only one of these may exist per unique keypair set + // can only create from webapi + } + + // lobby search filter tools + public enum ELobbyComparison : int { + k_ELobbyComparisonEqualToOrLessThan = -2, + k_ELobbyComparisonLessThan = -1, + k_ELobbyComparisonEqual = 0, + k_ELobbyComparisonGreaterThan = 1, + k_ELobbyComparisonEqualToOrGreaterThan = 2, + k_ELobbyComparisonNotEqual = 3, + } + + // lobby search distance. Lobby results are sorted from closest to farthest. + public enum ELobbyDistanceFilter : int { + k_ELobbyDistanceFilterClose, // only lobbies in the same immediate region will be returned + k_ELobbyDistanceFilterDefault, // only lobbies in the same region or near by regions + k_ELobbyDistanceFilterFar, // for games that don't have many latency requirements, will return lobbies about half-way around the globe + k_ELobbyDistanceFilterWorldwide, // no filtering, will match lobbies as far as India to NY (not recommended, expect multiple seconds of latency between the clients) + } + + //----------------------------------------------------------------------------- + // Purpose: Used in ChatInfo messages - fields specific to a chat member - must fit in a uint32 + //----------------------------------------------------------------------------- + [Flags] + public enum EChatMemberStateChange : int { + // Specific to joining / leaving the chatroom + k_EChatMemberStateChangeEntered = 0x0001, // This user has joined or is joining the chat room + k_EChatMemberStateChangeLeft = 0x0002, // This user has left or is leaving the chat room + k_EChatMemberStateChangeDisconnected = 0x0004, // User disconnected without leaving the chat first + k_EChatMemberStateChangeKicked = 0x0008, // User kicked + k_EChatMemberStateChangeBanned = 0x0010, // User kicked and banned + } + + //----------------------------------------------------------------------------- + // Purpose: Functions for quickly creating a Party with friends or acquaintances, + // EG from chat rooms. + //----------------------------------------------------------------------------- + public enum ESteamPartyBeaconLocationType : int { + k_ESteamPartyBeaconLocationType_Invalid = 0, + k_ESteamPartyBeaconLocationType_ChatGroup = 1, + + k_ESteamPartyBeaconLocationType_Max, + } + + public enum ESteamPartyBeaconLocationData : int { + k_ESteamPartyBeaconLocationDataInvalid = 0, + k_ESteamPartyBeaconLocationDataName = 1, + k_ESteamPartyBeaconLocationDataIconURLSmall = 2, + k_ESteamPartyBeaconLocationDataIconURLMedium = 3, + k_ESteamPartyBeaconLocationDataIconURLLarge = 4, + } + + public enum PlayerAcceptState_t : int { + k_EStateUnknown = 0, + k_EStatePlayerAccepted = 1, + k_EStatePlayerDeclined = 2, + } + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + public enum AudioPlayback_Status : int { + AudioPlayback_Undefined = 0, + AudioPlayback_Playing = 1, + AudioPlayback_Paused = 2, + AudioPlayback_Idle = 3 + } + + // list of possible errors returned by SendP2PPacket() API + // these will be posted in the P2PSessionConnectFail_t callback + public enum EP2PSessionError : int { + k_EP2PSessionErrorNone = 0, + k_EP2PSessionErrorNoRightsToApp = 2, // local user doesn't own the app that is running + k_EP2PSessionErrorTimeout = 4, // target isn't responding, perhaps not calling AcceptP2PSessionWithUser() + // corporate firewalls can also block this (NAT traversal is not firewall traversal) + // make sure that UDP ports 3478, 4379, and 4380 are open in an outbound direction + + // The following error codes were removed and will never be sent. + // For privacy reasons, there is no reply if the user is offline or playing another game. + k_EP2PSessionErrorNotRunningApp_DELETED = 1, + k_EP2PSessionErrorDestinationNotLoggedIn_DELETED = 3, + + k_EP2PSessionErrorMax = 5 + } + + // SendP2PPacket() send types + // Typically k_EP2PSendUnreliable is what you want for UDP-like packets, k_EP2PSendReliable for TCP-like packets + public enum EP2PSend : int { + // Basic UDP send. Packets can't be bigger than 1200 bytes (your typical MTU size). Can be lost, or arrive out of order (rare). + // The sending API does have some knowledge of the underlying connection, so if there is no NAT-traversal accomplished or + // there is a recognized adjustment happening on the connection, the packet will be batched until the connection is open again. + k_EP2PSendUnreliable = 0, + + // As above, but if the underlying p2p connection isn't yet established the packet will just be thrown away. Using this on the first + // packet sent to a remote host almost guarantees the packet will be dropped. + // This is only really useful for kinds of data that should never buffer up, i.e. voice payload packets + k_EP2PSendUnreliableNoDelay = 1, + + // Reliable message send. Can send up to 1MB of data in a single message. + // Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for efficient sends of large chunks of data. + k_EP2PSendReliable = 2, + + // As above, but applies the Nagle algorithm to the send - sends will accumulate + // until the current MTU size (typically ~1200 bytes, but can change) or ~200ms has passed (Nagle algorithm). + // Useful if you want to send a set of smaller messages but have the coalesced into a single packet + // Since the reliable stream is all ordered, you can do several small message sends with k_EP2PSendReliableWithBuffering and then + // do a normal k_EP2PSendReliable to force all the buffered data to be sent. + k_EP2PSendReliableWithBuffering = 3, + + } + + // connection progress indicators, used by CreateP2PConnectionSocket() + public enum ESNetSocketState : int { + k_ESNetSocketStateInvalid = 0, + + // communication is valid + k_ESNetSocketStateConnected = 1, + + // states while establishing a connection + k_ESNetSocketStateInitiated = 10, // the connection state machine has started + + // p2p connections + k_ESNetSocketStateLocalCandidatesFound = 11, // we've found our local IP info + k_ESNetSocketStateReceivedRemoteCandidates = 12,// we've received information from the remote machine, via the Steam back-end, about their IP info + + // direct connections + k_ESNetSocketStateChallengeHandshake = 15, // we've received a challenge packet from the server + + // failure states + k_ESNetSocketStateDisconnecting = 21, // the API shut it down, and we're in the process of telling the other end + k_ESNetSocketStateLocalDisconnect = 22, // the API shut it down, and we've completed shutdown + k_ESNetSocketStateTimeoutDuringConnect = 23, // we timed out while trying to creating the connection + k_ESNetSocketStateRemoteEndDisconnected = 24, // the remote end has disconnected from us + k_ESNetSocketStateConnectionBroken = 25, // connection has been broken; either the other end has disappeared or our local network connection has broke + + } + + // describes how the socket is currently connected + public enum ESNetSocketConnectionType : int { + k_ESNetSocketConnectionTypeNotConnected = 0, + k_ESNetSocketConnectionTypeUDP = 1, + k_ESNetSocketConnectionTypeUDPRelay = 2, + } + + // Feature types for parental settings + public enum EParentalFeature : int { + k_EFeatureInvalid = 0, + k_EFeatureStore = 1, + k_EFeatureCommunity = 2, + k_EFeatureProfile = 3, + k_EFeatureFriends = 4, + k_EFeatureNews = 5, + k_EFeatureTrading = 6, + k_EFeatureSettings = 7, + k_EFeatureConsole = 8, + k_EFeatureBrowser = 9, + k_EFeatureParentalSetup = 10, + k_EFeatureLibrary = 11, + k_EFeatureTest = 12, + k_EFeatureSiteLicense = 13, + k_EFeatureKioskMode = 14, + k_EFeatureMax + } + + //----------------------------------------------------------------------------- + // Purpose: The form factor of a device + //----------------------------------------------------------------------------- + public enum ESteamDeviceFormFactor : int { + k_ESteamDeviceFormFactorUnknown = 0, + k_ESteamDeviceFormFactorPhone = 1, + k_ESteamDeviceFormFactorTablet = 2, + k_ESteamDeviceFormFactorComputer = 3, + k_ESteamDeviceFormFactorTV = 4, + } + + [Flags] + public enum ERemoteStoragePlatform : int { + k_ERemoteStoragePlatformNone = 0, + k_ERemoteStoragePlatformWindows = (1 << 0), + k_ERemoteStoragePlatformOSX = (1 << 1), + k_ERemoteStoragePlatformPS3 = (1 << 2), + k_ERemoteStoragePlatformLinux = (1 << 3), + k_ERemoteStoragePlatformSwitch = (1 << 4), + k_ERemoteStoragePlatformAndroid = (1 << 5), + k_ERemoteStoragePlatformIOS = (1 << 6), + // NB we get one more before we need to widen some things + + k_ERemoteStoragePlatformAll = -1 + } + + public enum ERemoteStoragePublishedFileVisibility : int { + k_ERemoteStoragePublishedFileVisibilityPublic = 0, + k_ERemoteStoragePublishedFileVisibilityFriendsOnly = 1, + k_ERemoteStoragePublishedFileVisibilityPrivate = 2, + k_ERemoteStoragePublishedFileVisibilityUnlisted = 3, + } + + public enum EWorkshopFileType : int { + k_EWorkshopFileTypeFirst = 0, + + k_EWorkshopFileTypeCommunity = 0, // normal Workshop item that can be subscribed to + k_EWorkshopFileTypeMicrotransaction = 1, // Workshop item that is meant to be voted on for the purpose of selling in-game + k_EWorkshopFileTypeCollection = 2, // a collection of Workshop or Greenlight items + k_EWorkshopFileTypeArt = 3, // artwork + k_EWorkshopFileTypeVideo = 4, // external video + k_EWorkshopFileTypeScreenshot = 5, // screenshot + k_EWorkshopFileTypeGame = 6, // Greenlight game entry + k_EWorkshopFileTypeSoftware = 7, // Greenlight software entry + k_EWorkshopFileTypeConcept = 8, // Greenlight concept + k_EWorkshopFileTypeWebGuide = 9, // Steam web guide + k_EWorkshopFileTypeIntegratedGuide = 10, // application integrated guide + k_EWorkshopFileTypeMerch = 11, // Workshop merchandise meant to be voted on for the purpose of being sold + k_EWorkshopFileTypeControllerBinding = 12, // Steam Controller bindings + k_EWorkshopFileTypeSteamworksAccessInvite = 13, // internal + k_EWorkshopFileTypeSteamVideo = 14, // Steam video + k_EWorkshopFileTypeGameManagedItem = 15, // managed completely by the game, not the user, and not shown on the web + + // Update k_EWorkshopFileTypeMax if you add values. + k_EWorkshopFileTypeMax = 16 + + } + + public enum EWorkshopVote : int { + k_EWorkshopVoteUnvoted = 0, + k_EWorkshopVoteFor = 1, + k_EWorkshopVoteAgainst = 2, + k_EWorkshopVoteLater = 3, + } + + public enum EWorkshopFileAction : int { + k_EWorkshopFileActionPlayed = 0, + k_EWorkshopFileActionCompleted = 1, + } + + public enum EWorkshopEnumerationType : int { + k_EWorkshopEnumerationTypeRankedByVote = 0, + k_EWorkshopEnumerationTypeRecent = 1, + k_EWorkshopEnumerationTypeTrending = 2, + k_EWorkshopEnumerationTypeFavoritesOfFriends = 3, + k_EWorkshopEnumerationTypeVotedByFriends = 4, + k_EWorkshopEnumerationTypeContentByFriends = 5, + k_EWorkshopEnumerationTypeRecentFromFollowedUsers = 6, + } + + public enum EWorkshopVideoProvider : int { + k_EWorkshopVideoProviderNone = 0, + k_EWorkshopVideoProviderYoutube = 1 + } + + public enum EUGCReadAction : int { + // Keeps the file handle open unless the last byte is read. You can use this when reading large files (over 100MB) in sequential chunks. + // If the last byte is read, this will behave the same as k_EUGCRead_Close. Otherwise, it behaves the same as k_EUGCRead_ContinueReading. + // This value maintains the same behavior as before the EUGCReadAction parameter was introduced. + k_EUGCRead_ContinueReadingUntilFinished = 0, + + // Keeps the file handle open. Use this when using UGCRead to seek to different parts of the file. + // When you are done seeking around the file, make a final call with k_EUGCRead_Close to close it. + k_EUGCRead_ContinueReading = 1, + + // Frees the file handle. Use this when you're done reading the content. + // To read the file from Steam again you will need to call UGCDownload again. + k_EUGCRead_Close = 2, + } + + public enum ERemoteStorageLocalFileChange : int { + k_ERemoteStorageLocalFileChange_Invalid = 0, + + // The file was updated from another device + k_ERemoteStorageLocalFileChange_FileUpdated = 1, + + // The file was deleted by another device + k_ERemoteStorageLocalFileChange_FileDeleted = 2, + } + + public enum ERemoteStorageFilePathType : int { + k_ERemoteStorageFilePathType_Invalid = 0, + + // The file is directly accessed by the game and this is the full path + k_ERemoteStorageFilePathType_Absolute = 1, + + // The file is accessed via the ISteamRemoteStorage API and this is the filename + k_ERemoteStorageFilePathType_APIFilename = 2, + } + + public enum EVRScreenshotType : int { + k_EVRScreenshotType_None = 0, + k_EVRScreenshotType_Mono = 1, + k_EVRScreenshotType_Stereo = 2, + k_EVRScreenshotType_MonoCubemap = 3, + k_EVRScreenshotType_MonoPanorama = 4, + k_EVRScreenshotType_StereoPanorama = 5 + } + + // Matching UGC types for queries + public enum EUGCMatchingUGCType : int { + k_EUGCMatchingUGCType_Items = 0, // both mtx items and ready-to-use items + k_EUGCMatchingUGCType_Items_Mtx = 1, + k_EUGCMatchingUGCType_Items_ReadyToUse = 2, + k_EUGCMatchingUGCType_Collections = 3, + k_EUGCMatchingUGCType_Artwork = 4, + k_EUGCMatchingUGCType_Videos = 5, + k_EUGCMatchingUGCType_Screenshots = 6, + k_EUGCMatchingUGCType_AllGuides = 7, // both web guides and integrated guides + k_EUGCMatchingUGCType_WebGuides = 8, + k_EUGCMatchingUGCType_IntegratedGuides = 9, + k_EUGCMatchingUGCType_UsableInGame = 10, // ready-to-use items and integrated guides + k_EUGCMatchingUGCType_ControllerBindings = 11, + k_EUGCMatchingUGCType_GameManagedItems = 12, // game managed items (not managed by users) + k_EUGCMatchingUGCType_All = ~0, // @note: will only be valid for CreateQueryUserUGCRequest requests + } + + // Different lists of published UGC for a user. + // If the current logged in user is different than the specified user, then some options may not be allowed. + public enum EUserUGCList : int { + k_EUserUGCList_Published, + k_EUserUGCList_VotedOn, + k_EUserUGCList_VotedUp, + k_EUserUGCList_VotedDown, + k_EUserUGCList_WillVoteLater, + k_EUserUGCList_Favorited, + k_EUserUGCList_Subscribed, + k_EUserUGCList_UsedOrPlayed, + k_EUserUGCList_Followed, + } + + // Sort order for user published UGC lists (defaults to creation order descending) + public enum EUserUGCListSortOrder : int { + k_EUserUGCListSortOrder_CreationOrderDesc, + k_EUserUGCListSortOrder_CreationOrderAsc, + k_EUserUGCListSortOrder_TitleAsc, + k_EUserUGCListSortOrder_LastUpdatedDesc, + k_EUserUGCListSortOrder_SubscriptionDateDesc, + k_EUserUGCListSortOrder_VoteScoreDesc, + k_EUserUGCListSortOrder_ForModeration, + } + + // Combination of sorting and filtering for queries across all UGC + public enum EUGCQuery : int { + k_EUGCQuery_RankedByVote = 0, + k_EUGCQuery_RankedByPublicationDate = 1, + k_EUGCQuery_AcceptedForGameRankedByAcceptanceDate = 2, + k_EUGCQuery_RankedByTrend = 3, + k_EUGCQuery_FavoritedByFriendsRankedByPublicationDate = 4, + k_EUGCQuery_CreatedByFriendsRankedByPublicationDate = 5, + k_EUGCQuery_RankedByNumTimesReported = 6, + k_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate = 7, + k_EUGCQuery_NotYetRated = 8, + k_EUGCQuery_RankedByTotalVotesAsc = 9, + k_EUGCQuery_RankedByVotesUp = 10, + k_EUGCQuery_RankedByTextSearch = 11, + k_EUGCQuery_RankedByTotalUniqueSubscriptions = 12, + k_EUGCQuery_RankedByPlaytimeTrend = 13, + k_EUGCQuery_RankedByTotalPlaytime = 14, + k_EUGCQuery_RankedByAveragePlaytimeTrend = 15, + k_EUGCQuery_RankedByLifetimeAveragePlaytime = 16, + k_EUGCQuery_RankedByPlaytimeSessionsTrend = 17, + k_EUGCQuery_RankedByLifetimePlaytimeSessions = 18, + k_EUGCQuery_RankedByLastUpdatedDate = 19, + } + + public enum EItemUpdateStatus : int { + k_EItemUpdateStatusInvalid = 0, // The item update handle was invalid, job might be finished, listen too SubmitItemUpdateResult_t + k_EItemUpdateStatusPreparingConfig = 1, // The item update is processing configuration data + k_EItemUpdateStatusPreparingContent = 2, // The item update is reading and processing content files + k_EItemUpdateStatusUploadingContent = 3, // The item update is uploading content changes to Steam + k_EItemUpdateStatusUploadingPreviewFile = 4, // The item update is uploading new preview file image + k_EItemUpdateStatusCommittingChanges = 5 // The item update is committing all changes + } + + [Flags] + public enum EItemState : int { + k_EItemStateNone = 0, // item not tracked on client + k_EItemStateSubscribed = 1, // current user is subscribed to this item. Not just cached. + k_EItemStateLegacyItem = 2, // item was created with ISteamRemoteStorage + k_EItemStateInstalled = 4, // item is installed and usable (but maybe out of date) + k_EItemStateNeedsUpdate = 8, // items needs an update. Either because it's not installed yet or creator updated content + k_EItemStateDownloading = 16, // item update is currently downloading + k_EItemStateDownloadPending = 32, // DownloadItem() was called for this item, content isn't available until DownloadItemResult_t is fired + } + + public enum EItemStatistic : int { + k_EItemStatistic_NumSubscriptions = 0, + k_EItemStatistic_NumFavorites = 1, + k_EItemStatistic_NumFollowers = 2, + k_EItemStatistic_NumUniqueSubscriptions = 3, + k_EItemStatistic_NumUniqueFavorites = 4, + k_EItemStatistic_NumUniqueFollowers = 5, + k_EItemStatistic_NumUniqueWebsiteViews = 6, + k_EItemStatistic_ReportScore = 7, + k_EItemStatistic_NumSecondsPlayed = 8, + k_EItemStatistic_NumPlaytimeSessions = 9, + k_EItemStatistic_NumComments = 10, + k_EItemStatistic_NumSecondsPlayedDuringTimePeriod = 11, + k_EItemStatistic_NumPlaytimeSessionsDuringTimePeriod = 12, + } + + public enum EItemPreviewType : int { + k_EItemPreviewType_Image = 0, // standard image file expected (e.g. jpg, png, gif, etc.) + k_EItemPreviewType_YouTubeVideo = 1, // video id is stored + k_EItemPreviewType_Sketchfab = 2, // model id is stored + k_EItemPreviewType_EnvironmentMap_HorizontalCross = 3, // standard image file expected - cube map in the layout + // +---+---+-------+ + // | |Up | | + // +---+---+---+---+ + // | L | F | R | B | + // +---+---+---+---+ + // | |Dn | | + // +---+---+---+---+ + k_EItemPreviewType_EnvironmentMap_LatLong = 4, // standard image file expected + k_EItemPreviewType_ReservedMax = 255, // you can specify your own types above this value + } + + public enum EUGCContentDescriptorID : int { + k_EUGCContentDescriptor_NudityOrSexualContent = 1, + k_EUGCContentDescriptor_FrequentViolenceOrGore = 2, + k_EUGCContentDescriptor_AdultOnlySexualContent = 3, + k_EUGCContentDescriptor_GratuitousSexualContent = 4, + k_EUGCContentDescriptor_AnyMatureContent = 5, + } + + public enum EFailureType : int { + k_EFailureFlushedCallbackQueue, + k_EFailurePipeFail, + } + + // type of data request, when downloading leaderboard entries + public enum ELeaderboardDataRequest : int { + k_ELeaderboardDataRequestGlobal = 0, + k_ELeaderboardDataRequestGlobalAroundUser = 1, + k_ELeaderboardDataRequestFriends = 2, + k_ELeaderboardDataRequestUsers = 3 + } + + // the sort order of a leaderboard + public enum ELeaderboardSortMethod : int { + k_ELeaderboardSortMethodNone = 0, + k_ELeaderboardSortMethodAscending = 1, // top-score is lowest number + k_ELeaderboardSortMethodDescending = 2, // top-score is highest number + } + + // the display type (used by the Steam Community web site) for a leaderboard + public enum ELeaderboardDisplayType : int { + k_ELeaderboardDisplayTypeNone = 0, + k_ELeaderboardDisplayTypeNumeric = 1, // simple numerical score + k_ELeaderboardDisplayTypeTimeSeconds = 2, // the score represents a time, in seconds + k_ELeaderboardDisplayTypeTimeMilliSeconds = 3, // the score represents a time, in milliseconds + } + + public enum ELeaderboardUploadScoreMethod : int { + k_ELeaderboardUploadScoreMethodNone = 0, + k_ELeaderboardUploadScoreMethodKeepBest = 1, // Leaderboard will keep user's best score + k_ELeaderboardUploadScoreMethodForceUpdate = 2, // Leaderboard will always replace score with specified + } + + // Steam API call failure results + public enum ESteamAPICallFailure : int { + k_ESteamAPICallFailureNone = -1, // no failure + k_ESteamAPICallFailureSteamGone = 0, // the local Steam process has gone away + k_ESteamAPICallFailureNetworkFailure = 1, // the network connection to Steam has been broken, or was already broken + // SteamServersDisconnected_t callback will be sent around the same time + // SteamServersConnected_t will be sent when the client is able to talk to the Steam servers again + k_ESteamAPICallFailureInvalidHandle = 2, // the SteamAPICall_t handle passed in no longer exists + k_ESteamAPICallFailureMismatchedCallback = 3,// GetAPICallResult() was called with the wrong callback type for this API call + } + + // Input modes for the Big Picture gamepad text entry + public enum EGamepadTextInputMode : int { + k_EGamepadTextInputModeNormal = 0, + k_EGamepadTextInputModePassword = 1 + } + + // Controls number of allowed lines for the Big Picture gamepad text entry + public enum EGamepadTextInputLineMode : int { + k_EGamepadTextInputLineModeSingleLine = 0, + k_EGamepadTextInputLineModeMultipleLines = 1 + } + + public enum EFloatingGamepadTextInputMode : int { + k_EFloatingGamepadTextInputModeModeSingleLine = 0, // Enter dismisses the keyboard + k_EFloatingGamepadTextInputModeModeMultipleLines = 1, // User needs to explictly close the keyboard + k_EFloatingGamepadTextInputModeModeEmail = 2, // Keyboard layout is email, enter dismisses the keyboard + k_EFloatingGamepadTextInputModeModeNumeric = 3, // Keyboard layout is numeric, enter dismisses the keyboard + + } + + // The context where text filtering is being done + public enum ETextFilteringContext : int { + k_ETextFilteringContextUnknown = 0, // Unknown context + k_ETextFilteringContextGameContent = 1, // Game content, only legally required filtering is performed + k_ETextFilteringContextChat = 2, // Chat from another player + k_ETextFilteringContextName = 3, // Character or item name + } + + //----------------------------------------------------------------------------- + // results for CheckFileSignature + //----------------------------------------------------------------------------- + public enum ECheckFileSignature : int { + k_ECheckFileSignatureInvalidSignature = 0, + k_ECheckFileSignatureValidSignature = 1, + k_ECheckFileSignatureFileNotFound = 2, + k_ECheckFileSignatureNoSignaturesFoundForThisApp = 3, + k_ECheckFileSignatureNoSignaturesFoundForThisFile = 4, + } + + public enum EMatchMakingServerResponse : int { + eServerResponded = 0, + eServerFailedToRespond, + eNoServersListedOnMasterServer // for the Internet query type, returned in response callback if no servers of this type match + } + + public enum EServerMode : int { + eServerModeInvalid = 0, // DO NOT USE + eServerModeNoAuthentication = 1, // Don't authenticate user logins and don't list on the server list + eServerModeAuthentication = 2, // Authenticate users, list on the server list, don't run VAC on clients that connect + eServerModeAuthenticationAndSecure = 3, // Authenticate users, list on the server list and VAC protect clients + } + + // General result codes + public enum EResult : int { + k_EResultNone = 0, // no result + k_EResultOK = 1, // success + k_EResultFail = 2, // generic failure + k_EResultNoConnection = 3, // no/failed network connection + // k_EResultNoConnectionRetry = 4, // OBSOLETE - removed + k_EResultInvalidPassword = 5, // password/ticket is invalid + k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere + k_EResultInvalidProtocolVer = 7, // protocol version is incorrect + k_EResultInvalidParam = 8, // a parameter is incorrect + k_EResultFileNotFound = 9, // file was not found + k_EResultBusy = 10, // called method busy - action not taken + k_EResultInvalidState = 11, // called object was in an invalid state + k_EResultInvalidName = 12, // name is invalid + k_EResultInvalidEmail = 13, // email is invalid + k_EResultDuplicateName = 14, // name is not unique + k_EResultAccessDenied = 15, // access is denied + k_EResultTimeout = 16, // operation timed out + k_EResultBanned = 17, // VAC2 banned + k_EResultAccountNotFound = 18, // account not found + k_EResultInvalidSteamID = 19, // steamID is invalid + k_EResultServiceUnavailable = 20, // The requested service is currently unavailable + k_EResultNotLoggedOn = 21, // The user is not logged on + k_EResultPending = 22, // Request is pending (may be in process, or waiting on third party) + k_EResultEncryptionFailure = 23, // Encryption or Decryption failed + k_EResultInsufficientPrivilege = 24, // Insufficient privilege + k_EResultLimitExceeded = 25, // Too much of a good thing + k_EResultRevoked = 26, // Access has been revoked (used for revoked guest passes) + k_EResultExpired = 27, // License/Guest pass the user is trying to access is expired + k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again + k_EResultDuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time + k_EResultAlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user + k_EResultIPNotFound = 31, // IP address not found + k_EResultPersistFailed = 32, // failed to write change to the data store + k_EResultLockingFailed = 33, // failed to acquire access lock for this operation + k_EResultLogonSessionReplaced = 34, + k_EResultConnectFailed = 35, + k_EResultHandshakeFailed = 36, + k_EResultIOFailure = 37, + k_EResultRemoteDisconnect = 38, + k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart requested + k_EResultBlocked = 40, // a user didn't allow it + k_EResultIgnored = 41, // target is ignoring sender + k_EResultNoMatch = 42, // nothing matching the request found + k_EResultAccountDisabled = 43, + k_EResultServiceReadOnly = 44, // this service is not accepting content changes right now + k_EResultAccountNotFeatured = 45, // account doesn't have value, so this feature isn't available + k_EResultAdministratorOK = 46, // allowed to take this action, but only because requester is admin + k_EResultContentVersion = 47, // A Version mismatch in content transmitted within the Steam protocol. + k_EResultTryAnotherCM = 48, // The current CM can't service the user making a request, user should try another. + k_EResultPasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed. + k_EResultAlreadyLoggedInElsewhere = 50, // You are already logged in elsewhere, you must wait + k_EResultSuspended = 51, // Long running operation (content download) suspended/paused + k_EResultCancelled = 52, // Operation canceled (typically by user: content download) + k_EResultDataCorruption = 53, // Operation canceled because data is ill formed or unrecoverable + k_EResultDiskFull = 54, // Operation canceled - not enough disk space. + k_EResultRemoteCallFailed = 55, // an remote call or IPC call failed + k_EResultPasswordUnset = 56, // Password could not be verified as it's unset server side + k_EResultExternalAccountUnlinked = 57, // External account (PSN, Facebook...) is not linked to a Steam account + k_EResultPSNTicketInvalid = 58, // PSN ticket was invalid + k_EResultExternalAccountAlreadyLinked = 59, // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first + k_EResultRemoteFileConflict = 60, // The sync cannot resume due to a conflict between the local and remote files + k_EResultIllegalPassword = 61, // The requested new password is not legal + k_EResultSameAsPreviousValue = 62, // new value is the same as the old one ( secret question and answer ) + k_EResultAccountLogonDenied = 63, // account login denied due to 2nd factor authentication failure + k_EResultCannotUseOldPassword = 64, // The requested new password is not legal + k_EResultInvalidLoginAuthCode = 65, // account login denied due to auth code invalid + k_EResultAccountLogonDeniedNoMail = 66, // account login denied due to 2nd factor auth failure - and no mail has been sent - partner site specific + k_EResultHardwareNotCapableOfIPT = 67, // + k_EResultIPTInitError = 68, // + k_EResultParentalControlRestricted = 69, // operation failed due to parental control restrictions for current user + k_EResultFacebookQueryError = 70, // Facebook query returned an error + k_EResultExpiredLoginAuthCode = 71, // account login denied due to auth code expired + k_EResultIPLoginRestrictionFailed = 72, + k_EResultAccountLockedDown = 73, + k_EResultAccountLogonDeniedVerifiedEmailRequired = 74, + k_EResultNoMatchingURL = 75, + k_EResultBadResponse = 76, // parse failure, missing field, etc. + k_EResultRequirePasswordReEntry = 77, // The user cannot complete the action until they re-enter their password + k_EResultValueOutOfRange = 78, // the value entered is outside the acceptable range + k_EResultUnexpectedError = 79, // something happened that we didn't expect to ever happen + k_EResultDisabled = 80, // The requested service has been configured to be unavailable + k_EResultInvalidCEGSubmission = 81, // The set of files submitted to the CEG server are not valid ! + k_EResultRestrictedDevice = 82, // The device being used is not allowed to perform this action + k_EResultRegionLocked = 83, // The action could not be complete because it is region restricted + k_EResultRateLimitExceeded = 84, // Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent + k_EResultAccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to login + k_EResultItemDeleted = 86, // The thing we're trying to access has been deleted + k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker + k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch + k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match + k_EResultAccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners + k_EResultNotModified = 91, // data not modified + k_EResultNoMobileDevice = 92, // the account does not have a mobile device associated with it + k_EResultTimeNotSynced = 93, // the time presented is out of range or tolerance + k_EResultSmsCodeFailed = 94, // SMS code failure (no match, none pending, etc.) + k_EResultAccountLimitExceeded = 95, // Too many accounts access this resource + k_EResultAccountActivityLimitExceeded = 96, // Too many changes to this account + k_EResultPhoneActivityLimitExceeded = 97, // Too many changes to this phone + k_EResultRefundToWallet = 98, // Cannot refund to payment method, must use wallet + k_EResultEmailSendFailure = 99, // Cannot send an email + k_EResultNotSettled = 100, // Can't perform operation till payment has settled + k_EResultNeedCaptcha = 101, // Needs to provide a valid captcha + k_EResultGSLTDenied = 102, // a game server login token owned by this token's owner has been banned + k_EResultGSOwnerDenied = 103, // game server owner is denied for other reason (account lock, community ban, vac ban, missing phone) + k_EResultInvalidItemType = 104, // the type of thing we were requested to act on is invalid + k_EResultIPBanned = 105, // the ip address has been banned from taking this action + k_EResultGSLTExpired = 106, // this token has expired from disuse; can be reset for use + k_EResultInsufficientFunds = 107, // user doesn't have enough wallet funds to complete the action + k_EResultTooManyPending = 108, // There are too many of this thing pending already + k_EResultNoSiteLicensesFound = 109, // No site licenses found + k_EResultWGNetworkSendExceeded = 110, // the WG couldn't send a response because we exceeded max network send size + k_EResultAccountNotFriends = 111, // the user is not mutually friends + k_EResultLimitedUserAccount = 112, // the user is limited + k_EResultCantRemoveItem = 113, // item can't be removed + k_EResultAccountDeleted = 114, // account has been deleted + k_EResultExistingUserCancelledLicense = 115, // A license for this already exists, but cancelled + k_EResultCommunityCooldown = 116, // access is denied because of a community cooldown (probably from support profile data resets) + k_EResultNoLauncherSpecified = 117, // No launcher was specified, but a launcher was needed to choose correct realm for operation. + k_EResultMustAgreeToSSA = 118, // User must agree to china SSA or global SSA before login + k_EResultLauncherMigrated = 119, // The specified launcher type is no longer supported; the user should be directed elsewhere + k_EResultSteamRealmMismatch = 120, // The user's realm does not match the realm of the requested resource + k_EResultInvalidSignature = 121, // signature check did not match + k_EResultParseFailure = 122, // Failed to parse input + k_EResultNoVerifiedPhone = 123, // account does not have a verified phone number + k_EResultInsufficientBattery = 124, // user device doesn't have enough battery charge currently to complete the action + k_EResultChargerRequired = 125, // The operation requires a charger to be plugged in, which wasn't present + k_EResultCachedCredentialInvalid = 126, // Cached credential was invalid - user must reauthenticate + K_EResultPhoneNumberIsVOIP = 127, // The phone number provided is a Voice Over IP number + } + + // Error codes for use with the voice functions + public enum EVoiceResult : int { + k_EVoiceResultOK = 0, + k_EVoiceResultNotInitialized = 1, + k_EVoiceResultNotRecording = 2, + k_EVoiceResultNoData = 3, + k_EVoiceResultBufferTooSmall = 4, + k_EVoiceResultDataCorrupted = 5, + k_EVoiceResultRestricted = 6, + k_EVoiceResultUnsupportedCodec = 7, + k_EVoiceResultReceiverOutOfDate = 8, + k_EVoiceResultReceiverDidNotAnswer = 9, + + } + + // Result codes to GSHandleClientDeny/Kick + public enum EDenyReason : int { + k_EDenyInvalid = 0, + k_EDenyInvalidVersion = 1, + k_EDenyGeneric = 2, + k_EDenyNotLoggedOn = 3, + k_EDenyNoLicense = 4, + k_EDenyCheater = 5, + k_EDenyLoggedInElseWhere = 6, + k_EDenyUnknownText = 7, + k_EDenyIncompatibleAnticheat = 8, + k_EDenyMemoryCorruption = 9, + k_EDenyIncompatibleSoftware = 10, + k_EDenySteamConnectionLost = 11, + k_EDenySteamConnectionError = 12, + k_EDenySteamResponseTimedOut = 13, + k_EDenySteamValidationStalled = 14, + k_EDenySteamOwnerLeftGuestUser = 15, + } + + // results from BeginAuthSession + public enum EBeginAuthSessionResult : int { + k_EBeginAuthSessionResultOK = 0, // Ticket is valid for this game and this steamID. + k_EBeginAuthSessionResultInvalidTicket = 1, // Ticket is not valid. + k_EBeginAuthSessionResultDuplicateRequest = 2, // A ticket has already been submitted for this steamID + k_EBeginAuthSessionResultInvalidVersion = 3, // Ticket is from an incompatible interface version + k_EBeginAuthSessionResultGameMismatch = 4, // Ticket is not for this game + k_EBeginAuthSessionResultExpiredTicket = 5, // Ticket has expired + } + + // Callback values for callback ValidateAuthTicketResponse_t which is a response to BeginAuthSession + public enum EAuthSessionResponse : int { + k_EAuthSessionResponseOK = 0, // Steam has verified the user is online, the ticket is valid and ticket has not been reused. + k_EAuthSessionResponseUserNotConnectedToSteam = 1, // The user in question is not connected to steam + k_EAuthSessionResponseNoLicenseOrExpired = 2, // The license has expired. + k_EAuthSessionResponseVACBanned = 3, // The user is VAC banned for this game. + k_EAuthSessionResponseLoggedInElseWhere = 4, // The user account has logged in elsewhere and the session containing the game instance has been disconnected. + k_EAuthSessionResponseVACCheckTimedOut = 5, // VAC has been unable to perform anti-cheat checks on this user + k_EAuthSessionResponseAuthTicketCanceled = 6, // The ticket has been canceled by the issuer + k_EAuthSessionResponseAuthTicketInvalidAlreadyUsed = 7, // This ticket has already been used, it is not valid. + k_EAuthSessionResponseAuthTicketInvalid = 8, // This ticket is not from a user instance currently connected to steam. + k_EAuthSessionResponsePublisherIssuedBan = 9, // The user is banned for this game. The ban came via the web api and not VAC + k_EAuthSessionResponseAuthTicketNetworkIdentityFailure = 10, // The network identity in the ticket does not match the server authenticating the ticket + } + + // results from UserHasLicenseForApp + public enum EUserHasLicenseForAppResult : int { + k_EUserHasLicenseResultHasLicense = 0, // User has a license for specified app + k_EUserHasLicenseResultDoesNotHaveLicense = 1, // User does not have a license for the specified app + k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated + } + + // Steam account types + public enum EAccountType : int { + k_EAccountTypeInvalid = 0, + k_EAccountTypeIndividual = 1, // single user account + k_EAccountTypeMultiseat = 2, // multiseat (e.g. cybercafe) account + k_EAccountTypeGameServer = 3, // game server account + k_EAccountTypeAnonGameServer = 4, // anonymous game server account + k_EAccountTypePending = 5, // pending + k_EAccountTypeContentServer = 6, // content server + k_EAccountTypeClan = 7, + k_EAccountTypeChat = 8, + k_EAccountTypeConsoleUser = 9, // Fake SteamID for local PSN account on PS3 or Live account on 360, etc. + k_EAccountTypeAnonUser = 10, + + // Max of 16 items in this field + k_EAccountTypeMax + } + + //----------------------------------------------------------------------------- + // Purpose: Chat Entry Types (previously was only friend-to-friend message types) + //----------------------------------------------------------------------------- + public enum EChatEntryType : int { + k_EChatEntryTypeInvalid = 0, + k_EChatEntryTypeChatMsg = 1, // Normal text message from another user + k_EChatEntryTypeTyping = 2, // Another user is typing (not used in multi-user chat) + k_EChatEntryTypeInviteGame = 3, // Invite from other user into that users current game + k_EChatEntryTypeEmote = 4, // text emote message (deprecated, should be treated as ChatMsg) + //k_EChatEntryTypeLobbyGameStart = 5, // lobby game is starting (dead - listen for LobbyGameCreated_t callback instead) + k_EChatEntryTypeLeftConversation = 6, // user has left the conversation ( closed chat window ) + // Above are previous FriendMsgType entries, now merged into more generic chat entry types + k_EChatEntryTypeEntered = 7, // user has entered the conversation (used in multi-user chat and group chat) + k_EChatEntryTypeWasKicked = 8, // user was kicked (data: 64-bit steamid of actor performing the kick) + k_EChatEntryTypeWasBanned = 9, // user was banned (data: 64-bit steamid of actor performing the ban) + k_EChatEntryTypeDisconnected = 10, // user disconnected + k_EChatEntryTypeHistoricalChat = 11, // a chat message from user's chat history or offilne message + //k_EChatEntryTypeReserved1 = 12, // No longer used + //k_EChatEntryTypeReserved2 = 13, // No longer used + k_EChatEntryTypeLinkBlocked = 14, // a link was removed by the chat filter. + } + + //----------------------------------------------------------------------------- + // Purpose: Chat Room Enter Responses + //----------------------------------------------------------------------------- + public enum EChatRoomEnterResponse : int { + k_EChatRoomEnterResponseSuccess = 1, // Success + k_EChatRoomEnterResponseDoesntExist = 2, // Chat doesn't exist (probably closed) + k_EChatRoomEnterResponseNotAllowed = 3, // General Denied - You don't have the permissions needed to join the chat + k_EChatRoomEnterResponseFull = 4, // Chat room has reached its maximum size + k_EChatRoomEnterResponseError = 5, // Unexpected Error + k_EChatRoomEnterResponseBanned = 6, // You are banned from this chat room and may not join + k_EChatRoomEnterResponseLimited = 7, // Joining this chat is not allowed because you are a limited user (no value on account) + k_EChatRoomEnterResponseClanDisabled = 8, // Attempt to join a clan chat when the clan is locked or disabled + k_EChatRoomEnterResponseCommunityBan = 9, // Attempt to join a chat when the user has a community lock on their account + k_EChatRoomEnterResponseMemberBlockedYou = 10, // Join failed - some member in the chat has blocked you from joining + k_EChatRoomEnterResponseYouBlockedMember = 11, // Join failed - you have blocked some member already in the chat + // k_EChatRoomEnterResponseNoRankingDataLobby = 12, // No longer used + // k_EChatRoomEnterResponseNoRankingDataUser = 13, // No longer used + // k_EChatRoomEnterResponseRankOutOfRange = 14, // No longer used + k_EChatRoomEnterResponseRatelimitExceeded = 15, // Join failed - to many join attempts in a very short period of time + } + + // Special flags for Chat accounts - they go in the top 8 bits + // of the steam ID's "instance", leaving 12 for the actual instances + [Flags] + public enum EChatSteamIDInstanceFlags : int { + k_EChatAccountInstanceMask = 0x00000FFF, // top 8 bits are flags + + k_EChatInstanceFlagClan = ( Constants.k_unSteamAccountInstanceMask + 1 ) >> 1, // top bit + k_EChatInstanceFlagLobby = ( Constants.k_unSteamAccountInstanceMask + 1 ) >> 2, // next one down, etc + k_EChatInstanceFlagMMSLobby = ( Constants.k_unSteamAccountInstanceMask + 1 ) >> 3, // next one down, etc + + // Max of 8 flags + } + + //----------------------------------------------------------------------------- + // Purpose: Possible positions to tell the overlay to show notifications in + //----------------------------------------------------------------------------- + public enum ENotificationPosition : int { + k_EPositionInvalid = -1, + k_EPositionTopLeft = 0, + k_EPositionTopRight = 1, + k_EPositionBottomLeft = 2, + k_EPositionBottomRight = 3, + } + + //----------------------------------------------------------------------------- + // Purpose: Broadcast upload result details + //----------------------------------------------------------------------------- + public enum EBroadcastUploadResult : int { + k_EBroadcastUploadResultNone = 0, // broadcast state unknown + k_EBroadcastUploadResultOK = 1, // broadcast was good, no problems + k_EBroadcastUploadResultInitFailed = 2, // broadcast init failed + k_EBroadcastUploadResultFrameFailed = 3, // broadcast frame upload failed + k_EBroadcastUploadResultTimeout = 4, // broadcast upload timed out + k_EBroadcastUploadResultBandwidthExceeded = 5, // broadcast send too much data + k_EBroadcastUploadResultLowFPS = 6, // broadcast FPS too low + k_EBroadcastUploadResultMissingKeyFrames = 7, // broadcast sending not enough key frames + k_EBroadcastUploadResultNoConnection = 8, // broadcast client failed to connect to relay + k_EBroadcastUploadResultRelayFailed = 9, // relay dropped the upload + k_EBroadcastUploadResultSettingsChanged = 10, // the client changed broadcast settings + k_EBroadcastUploadResultMissingAudio = 11, // client failed to send audio data + k_EBroadcastUploadResultTooFarBehind = 12, // clients was too slow uploading + k_EBroadcastUploadResultTranscodeBehind = 13, // server failed to keep up with transcode + k_EBroadcastUploadResultNotAllowedToPlay = 14, // Broadcast does not have permissions to play game + k_EBroadcastUploadResultBusy = 15, // RTMP host to busy to take new broadcast stream, choose another + k_EBroadcastUploadResultBanned = 16, // Account banned from community broadcast + k_EBroadcastUploadResultAlreadyActive = 17, // We already already have an stream running. + k_EBroadcastUploadResultForcedOff = 18, // We explicitly shutting down a broadcast + k_EBroadcastUploadResultAudioBehind = 19, // Audio stream was too far behind video + k_EBroadcastUploadResultShutdown = 20, // Broadcast Server was shut down + k_EBroadcastUploadResultDisconnect = 21, // broadcast uploader TCP disconnected + k_EBroadcastUploadResultVideoInitFailed = 22, // invalid video settings + k_EBroadcastUploadResultAudioInitFailed = 23, // invalid audio settings + } + + //----------------------------------------------------------------------------- + // Purpose: Reasons a user may not use the Community Market. + // Used in MarketEligibilityResponse_t. + //----------------------------------------------------------------------------- + [Flags] + public enum EMarketNotAllowedReasonFlags : int { + k_EMarketNotAllowedReason_None = 0, + + // A back-end call failed or something that might work again on retry + k_EMarketNotAllowedReason_TemporaryFailure = (1 << 0), + + // Disabled account + k_EMarketNotAllowedReason_AccountDisabled = (1 << 1), + + // Locked account + k_EMarketNotAllowedReason_AccountLockedDown = (1 << 2), + + // Limited account (no purchases) + k_EMarketNotAllowedReason_AccountLimited = (1 << 3), + + // The account is banned from trading items + k_EMarketNotAllowedReason_TradeBanned = (1 << 4), + + // Wallet funds aren't tradable because the user has had no purchase + // activity in the last year or has had no purchases prior to last month + k_EMarketNotAllowedReason_AccountNotTrusted = (1 << 5), + + // The user doesn't have Steam Guard enabled + k_EMarketNotAllowedReason_SteamGuardNotEnabled = (1 << 6), + + // The user has Steam Guard, but it hasn't been enabled for the required + // number of days + k_EMarketNotAllowedReason_SteamGuardOnlyRecentlyEnabled = (1 << 7), + + // The user has recently forgotten their password and reset it + k_EMarketNotAllowedReason_RecentPasswordReset = (1 << 8), + + // The user has recently funded his or her wallet with a new payment method + k_EMarketNotAllowedReason_NewPaymentMethod = (1 << 9), + + // An invalid cookie was sent by the user + k_EMarketNotAllowedReason_InvalidCookie = (1 << 10), + + // The user has Steam Guard, but is using a new computer or web browser + k_EMarketNotAllowedReason_UsingNewDevice = (1 << 11), + + // The user has recently refunded a store purchase by his or herself + k_EMarketNotAllowedReason_RecentSelfRefund = (1 << 12), + + // The user has recently funded his or her wallet with a new payment method that cannot be verified + k_EMarketNotAllowedReason_NewPaymentMethodCannotBeVerified = (1 << 13), + + // Not only is the account not trusted, but they have no recent purchases at all + k_EMarketNotAllowedReason_NoRecentPurchases = (1 << 14), + + // User accepted a wallet gift that was recently purchased + k_EMarketNotAllowedReason_AcceptedWalletGift = (1 << 15), + } + + // + // describes XP / progress restrictions to apply for games with duration control / + // anti-indulgence enabled for minor Steam China users. + // + // WARNING: DO NOT RENUMBER + public enum EDurationControlProgress : int { + k_EDurationControlProgress_Full = 0, // Full progress + k_EDurationControlProgress_Half = 1, // deprecated - XP or persistent rewards should be halved + k_EDurationControlProgress_None = 2, // deprecated - XP or persistent rewards should be stopped + + k_EDurationControl_ExitSoon_3h = 3, // allowed 3h time since 5h gap/break has elapsed, game should exit - steam will terminate the game soon + k_EDurationControl_ExitSoon_5h = 4, // allowed 5h time in calendar day has elapsed, game should exit - steam will terminate the game soon + k_EDurationControl_ExitSoon_Night = 5, // game running after day period, game should exit - steam will terminate the game soon + } + + // + // describes which notification timer has expired, for steam china duration control feature + // + // WARNING: DO NOT RENUMBER + public enum EDurationControlNotification : int { + k_EDurationControlNotification_None = 0, // just informing you about progress, no notification to show + k_EDurationControlNotification_1Hour = 1, // "you've been playing for N hours" + + k_EDurationControlNotification_3Hours = 2, // deprecated - "you've been playing for 3 hours; take a break" + k_EDurationControlNotification_HalfProgress = 3,// deprecated - "your XP / progress is half normal" + k_EDurationControlNotification_NoProgress = 4, // deprecated - "your XP / progress is zero" + + k_EDurationControlNotification_ExitSoon_3h = 5, // allowed 3h time since 5h gap/break has elapsed, game should exit - steam will terminate the game soon + k_EDurationControlNotification_ExitSoon_5h = 6, // allowed 5h time in calendar day has elapsed, game should exit - steam will terminate the game soon + k_EDurationControlNotification_ExitSoon_Night = 7,// game running after day period, game should exit - steam will terminate the game soon + } + + // + // Specifies a game's online state in relation to duration control + // + public enum EDurationControlOnlineState : int { + k_EDurationControlOnlineState_Invalid = 0, // nil value + k_EDurationControlOnlineState_Offline = 1, // currently in offline play - single-player, offline co-op, etc. + k_EDurationControlOnlineState_Online = 2, // currently in online play + k_EDurationControlOnlineState_OnlineHighPri = 3, // currently in online play and requests not to be interrupted + } + + public enum EGameSearchErrorCode_t : int { + k_EGameSearchErrorCode_OK = 1, + k_EGameSearchErrorCode_Failed_Search_Already_In_Progress = 2, + k_EGameSearchErrorCode_Failed_No_Search_In_Progress = 3, + k_EGameSearchErrorCode_Failed_Not_Lobby_Leader = 4, // if not the lobby leader can not call SearchForGameWithLobby + k_EGameSearchErrorCode_Failed_No_Host_Available = 5, // no host is available that matches those search params + k_EGameSearchErrorCode_Failed_Search_Params_Invalid = 6, // search params are invalid + k_EGameSearchErrorCode_Failed_Offline = 7, // offline, could not communicate with server + k_EGameSearchErrorCode_Failed_NotAuthorized = 8, // either the user or the application does not have priveledges to do this + k_EGameSearchErrorCode_Failed_Unknown_Error = 9, // unknown error + } + + public enum EPlayerResult_t : int { + k_EPlayerResultFailedToConnect = 1, // failed to connect after confirming + k_EPlayerResultAbandoned = 2, // quit game without completing it + k_EPlayerResultKicked = 3, // kicked by other players/moderator/server rules + k_EPlayerResultIncomplete = 4, // player stayed to end but game did not conclude successfully ( nofault to player ) + k_EPlayerResultCompleted = 5, // player completed game + } + + public enum ESteamIPv6ConnectivityProtocol : int { + k_ESteamIPv6ConnectivityProtocol_Invalid = 0, + k_ESteamIPv6ConnectivityProtocol_HTTP = 1, // because a proxy may make this different than other protocols + k_ESteamIPv6ConnectivityProtocol_UDP = 2, // test UDP connectivity. Uses a port that is commonly needed for other Steam stuff. If UDP works, TCP probably works. + } + + // For the above transport protocol, what do we think the local machine's connectivity to the internet over ipv6 is like + public enum ESteamIPv6ConnectivityState : int { + k_ESteamIPv6ConnectivityState_Unknown = 0, // We haven't run a test yet + k_ESteamIPv6ConnectivityState_Good = 1, // We have recently been able to make a request on ipv6 for the given protocol + k_ESteamIPv6ConnectivityState_Bad = 2, // We failed to make a request, either because this machine has no ipv6 address assigned, or it has no upstream connectivity + } + + // HTTP related types + // This enum is used in client API methods, do not re-number existing values. + public enum EHTTPMethod : int { + k_EHTTPMethodInvalid = 0, + k_EHTTPMethodGET, + k_EHTTPMethodHEAD, + k_EHTTPMethodPOST, + k_EHTTPMethodPUT, + k_EHTTPMethodDELETE, + k_EHTTPMethodOPTIONS, + k_EHTTPMethodPATCH, + + // The remaining HTTP methods are not yet supported, per rfc2616 section 5.1.1 only GET and HEAD are required for + // a compliant general purpose server. We'll likely add more as we find uses for them. + + // k_EHTTPMethodTRACE, + // k_EHTTPMethodCONNECT + } + + // HTTP Status codes that the server can send in response to a request, see rfc2616 section 10.3 for descriptions + // of each of these. + public enum EHTTPStatusCode : int { + // Invalid status code (this isn't defined in HTTP, used to indicate unset in our code) + k_EHTTPStatusCodeInvalid = 0, + + // Informational codes + k_EHTTPStatusCode100Continue = 100, + k_EHTTPStatusCode101SwitchingProtocols = 101, + + // Success codes + k_EHTTPStatusCode200OK = 200, + k_EHTTPStatusCode201Created = 201, + k_EHTTPStatusCode202Accepted = 202, + k_EHTTPStatusCode203NonAuthoritative = 203, + k_EHTTPStatusCode204NoContent = 204, + k_EHTTPStatusCode205ResetContent = 205, + k_EHTTPStatusCode206PartialContent = 206, + + // Redirection codes + k_EHTTPStatusCode300MultipleChoices = 300, + k_EHTTPStatusCode301MovedPermanently = 301, + k_EHTTPStatusCode302Found = 302, + k_EHTTPStatusCode303SeeOther = 303, + k_EHTTPStatusCode304NotModified = 304, + k_EHTTPStatusCode305UseProxy = 305, + //k_EHTTPStatusCode306Unused = 306, (used in old HTTP spec, now unused in 1.1) + k_EHTTPStatusCode307TemporaryRedirect = 307, + k_EHTTPStatusCode308PermanentRedirect = 308, + + // Error codes + k_EHTTPStatusCode400BadRequest = 400, + k_EHTTPStatusCode401Unauthorized = 401, // You probably want 403 or something else. 401 implies you're sending a WWW-Authenticate header and the client can sent an Authorization header in response. + k_EHTTPStatusCode402PaymentRequired = 402, // This is reserved for future HTTP specs, not really supported by clients + k_EHTTPStatusCode403Forbidden = 403, + k_EHTTPStatusCode404NotFound = 404, + k_EHTTPStatusCode405MethodNotAllowed = 405, + k_EHTTPStatusCode406NotAcceptable = 406, + k_EHTTPStatusCode407ProxyAuthRequired = 407, + k_EHTTPStatusCode408RequestTimeout = 408, + k_EHTTPStatusCode409Conflict = 409, + k_EHTTPStatusCode410Gone = 410, + k_EHTTPStatusCode411LengthRequired = 411, + k_EHTTPStatusCode412PreconditionFailed = 412, + k_EHTTPStatusCode413RequestEntityTooLarge = 413, + k_EHTTPStatusCode414RequestURITooLong = 414, + k_EHTTPStatusCode415UnsupportedMediaType = 415, + k_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416, + k_EHTTPStatusCode417ExpectationFailed = 417, + k_EHTTPStatusCode4xxUnknown = 418, // 418 is reserved, so we'll use it to mean unknown + k_EHTTPStatusCode429TooManyRequests = 429, + k_EHTTPStatusCode444ConnectionClosed = 444, // nginx only? + + // Server error codes + k_EHTTPStatusCode500InternalServerError = 500, + k_EHTTPStatusCode501NotImplemented = 501, + k_EHTTPStatusCode502BadGateway = 502, + k_EHTTPStatusCode503ServiceUnavailable = 503, + k_EHTTPStatusCode504GatewayTimeout = 504, + k_EHTTPStatusCode505HTTPVersionNotSupported = 505, + k_EHTTPStatusCode5xxUnknown = 599, + } + + /// Describe the status of a particular network resource + public enum ESteamNetworkingAvailability : int { + // Negative values indicate a problem. + // + // In general, we will not automatically retry unless you take some action that + // depends on of requests this resource, such as querying the status, attempting + // to initiate a connection, receive a connection, etc. If you do not take any + // action at all, we do not automatically retry in the background. + k_ESteamNetworkingAvailability_CannotTry = -102, // A dependent resource is missing, so this service is unavailable. (E.g. we cannot talk to routers because Internet is down or we don't have the network config.) + k_ESteamNetworkingAvailability_Failed = -101, // We have tried for enough time that we would expect to have been successful by now. We have never been successful + k_ESteamNetworkingAvailability_Previously = -100, // We tried and were successful at one time, but now it looks like we have a problem + + k_ESteamNetworkingAvailability_Retrying = -10, // We previously failed and are currently retrying + + // Not a problem, but not ready either + k_ESteamNetworkingAvailability_NeverTried = 1, // We don't know because we haven't ever checked/tried + k_ESteamNetworkingAvailability_Waiting = 2, // We're waiting on a dependent resource to be acquired. (E.g. we cannot obtain a cert until we are logged into Steam. We cannot measure latency to relays until we have the network config.) + k_ESteamNetworkingAvailability_Attempting = 3, // We're actively trying now, but are not yet successful. + + k_ESteamNetworkingAvailability_Current = 100, // Resource is online/available + + + k_ESteamNetworkingAvailability_Unknown = 0, // Internal dummy/sentinel, or value is not applicable in this context + k_ESteamNetworkingAvailability__Force32bit = 0x7fffffff, + } + + // + // Describing network hosts + // + /// Different methods of describing the identity of a network host + public enum ESteamNetworkingIdentityType : int { + // Dummy/empty/invalid. + // Please note that if we parse a string that we don't recognize + // but that appears reasonable, we will NOT use this type. Instead + // we'll use k_ESteamNetworkingIdentityType_UnknownType. + k_ESteamNetworkingIdentityType_Invalid = 0, + + // + // Basic platform-specific identifiers. + // + k_ESteamNetworkingIdentityType_SteamID = 16, // 64-bit CSteamID + k_ESteamNetworkingIdentityType_XboxPairwiseID = 17, // Publisher-specific user identity, as string + k_ESteamNetworkingIdentityType_SonyPSN = 18, // 64-bit ID + k_ESteamNetworkingIdentityType_GoogleStadia = 19, // 64-bit ID + //k_ESteamNetworkingIdentityType_NintendoNetworkServiceAccount, + //k_ESteamNetworkingIdentityType_EpicGameStore + //k_ESteamNetworkingIdentityType_WeGame + + // + // Special identifiers. + // + + // Use their IP address (and port) as their "identity". + // These types of identities are always unauthenticated. + // They are useful for porting plain sockets code, and other + // situations where you don't care about authentication. In this + // case, the local identity will be "localhost", + // and the remote address will be their network address. + // + // We use the same type for either IPv4 or IPv6, and + // the address is always store as IPv6. We use IPv4 + // mapped addresses to handle IPv4. + k_ESteamNetworkingIdentityType_IPAddress = 1, + + // Generic string/binary blobs. It's up to your app to interpret this. + // This library can tell you if the remote host presented a certificate + // signed by somebody you have chosen to trust, with this identity on it. + // It's up to you to ultimately decide what this identity means. + k_ESteamNetworkingIdentityType_GenericString = 2, + k_ESteamNetworkingIdentityType_GenericBytes = 3, + + // This identity type is used when we parse a string that looks like is a + // valid identity, just of a kind that we don't recognize. In this case, we + // can often still communicate with the peer! Allowing such identities + // for types we do not recognize useful is very useful for forward + // compatibility. + k_ESteamNetworkingIdentityType_UnknownType = 4, + + // Make sure this enum is stored in an int. + k_ESteamNetworkingIdentityType__Force32bit = 0x7fffffff, + } + + /// "Fake IPs" are assigned to hosts, to make it easier to interface with + /// older code that assumed all hosts will have an IPv4 address + public enum ESteamNetworkingFakeIPType : int { + k_ESteamNetworkingFakeIPType_Invalid, // Error, argument was not even an IP address, etc. + k_ESteamNetworkingFakeIPType_NotFake, // Argument was a valid IP, but was not from the reserved "fake" range + k_ESteamNetworkingFakeIPType_GlobalIPv4, // Globally unique (for a given app) IPv4 address. Address space managed by Steam + k_ESteamNetworkingFakeIPType_LocalIPv4, // Locally unique IPv4 address. Address space managed by the local process. For internal use only; should not be shared! + + k_ESteamNetworkingFakeIPType__Force32Bit = 0x7fffffff + } + + // + // Connection status + // + /// High level connection status + public enum ESteamNetworkingConnectionState : int { + + /// Dummy value used to indicate an error condition in the API. + /// Specified connection doesn't exist or has already been closed. + k_ESteamNetworkingConnectionState_None = 0, + + /// We are trying to establish whether peers can talk to each other, + /// whether they WANT to talk to each other, perform basic auth, + /// and exchange crypt keys. + /// + /// - For connections on the "client" side (initiated locally): + /// We're in the process of trying to establish a connection. + /// Depending on the connection type, we might not know who they are. + /// Note that it is not possible to tell if we are waiting on the + /// network to complete handshake packets, or for the application layer + /// to accept the connection. + /// + /// - For connections on the "server" side (accepted through listen socket): + /// We have completed some basic handshake and the client has presented + /// some proof of identity. The connection is ready to be accepted + /// using AcceptConnection(). + /// + /// In either case, any unreliable packets sent now are almost certain + /// to be dropped. Attempts to receive packets are guaranteed to fail. + /// You may send messages if the send mode allows for them to be queued. + /// but if you close the connection before the connection is actually + /// established, any queued messages will be discarded immediately. + /// (We will not attempt to flush the queue and confirm delivery to the + /// remote host, which ordinarily happens when a connection is closed.) + k_ESteamNetworkingConnectionState_Connecting = 1, + + /// Some connection types use a back channel or trusted 3rd party + /// for earliest communication. If the server accepts the connection, + /// then these connections switch into the rendezvous state. During this + /// state, we still have not yet established an end-to-end route (through + /// the relay network), and so if you send any messages unreliable, they + /// are going to be discarded. + k_ESteamNetworkingConnectionState_FindingRoute = 2, + + /// We've received communications from our peer (and we know + /// who they are) and are all good. If you close the connection now, + /// we will make our best effort to flush out any reliable sent data that + /// has not been acknowledged by the peer. (But note that this happens + /// from within the application process, so unlike a TCP connection, you are + /// not totally handing it off to the operating system to deal with it.) + k_ESteamNetworkingConnectionState_Connected = 3, + + /// Connection has been closed by our peer, but not closed locally. + /// The connection still exists from an API perspective. You must close the + /// handle to free up resources. If there are any messages in the inbound queue, + /// you may retrieve them. Otherwise, nothing may be done with the connection + /// except to close it. + /// + /// This stats is similar to CLOSE_WAIT in the TCP state machine. + k_ESteamNetworkingConnectionState_ClosedByPeer = 4, + + /// A disruption in the connection has been detected locally. (E.g. timeout, + /// local internet connection disrupted, etc.) + /// + /// The connection still exists from an API perspective. You must close the + /// handle to free up resources. + /// + /// Attempts to send further messages will fail. Any remaining received messages + /// in the queue are available. + k_ESteamNetworkingConnectionState_ProblemDetectedLocally = 5, + + // + // The following values are used internally and will not be returned by any API. + // We document them here to provide a little insight into the state machine that is used + // under the hood. + // + + /// We've disconnected on our side, and from an API perspective the connection is closed. + /// No more data may be sent or received. All reliable data has been flushed, or else + /// we've given up and discarded it. We do not yet know for sure that the peer knows + /// the connection has been closed, however, so we're just hanging around so that if we do + /// get a packet from them, we can send them the appropriate packets so that they can + /// know why the connection was closed (and not have to rely on a timeout, which makes + /// it appear as if something is wrong). + k_ESteamNetworkingConnectionState_FinWait = -1, + + /// We've disconnected on our side, and from an API perspective the connection is closed. + /// No more data may be sent or received. From a network perspective, however, on the wire, + /// we have not yet given any indication to the peer that the connection is closed. + /// We are in the process of flushing out the last bit of reliable data. Once that is done, + /// we will inform the peer that the connection has been closed, and transition to the + /// FinWait state. + /// + /// Note that no indication is given to the remote host that we have closed the connection, + /// until the data has been flushed. If the remote host attempts to send us data, we will + /// do whatever is necessary to keep the connection alive until it can be closed properly. + /// But in fact the data will be discarded, since there is no way for the application to + /// read it back. Typically this is not a problem, as application protocols that utilize + /// the lingering functionality are designed for the remote host to wait for the response + /// before sending any more data. + k_ESteamNetworkingConnectionState_Linger = -2, + + /// Connection is completely inactive and ready to be destroyed + k_ESteamNetworkingConnectionState_Dead = -3, + + k_ESteamNetworkingConnectionState__Force32Bit = 0x7fffffff + } + + /// Enumerate various causes of connection termination. These are designed to work similar + /// to HTTP error codes: the numeric range gives you a rough classification as to the source + /// of the problem. + public enum ESteamNetConnectionEnd : int { + // Invalid/sentinel value + k_ESteamNetConnectionEnd_Invalid = 0, + + // + // Application codes. These are the values you will pass to + // ISteamNetworkingSockets::CloseConnection. You can use these codes if + // you want to plumb through application-specific reason codes. If you don't + // need this facility, feel free to always pass + // k_ESteamNetConnectionEnd_App_Generic. + // + // The distinction between "normal" and "exceptional" termination is + // one you may use if you find useful, but it's not necessary for you + // to do so. The only place where we distinguish between normal and + // exceptional is in connection analytics. If a significant + // proportion of connections terminates in an exceptional manner, + // this can trigger an alert. + // + + // 1xxx: Application ended the connection in a "usual" manner. + // E.g.: user intentionally disconnected from the server, + // gameplay ended normally, etc + k_ESteamNetConnectionEnd_App_Min = 1000, + k_ESteamNetConnectionEnd_App_Generic = k_ESteamNetConnectionEnd_App_Min, + // Use codes in this range for "normal" disconnection + k_ESteamNetConnectionEnd_App_Max = 1999, + + // 2xxx: Application ended the connection in some sort of exceptional + // or unusual manner that might indicate a bug or configuration + // issue. + // + k_ESteamNetConnectionEnd_AppException_Min = 2000, + k_ESteamNetConnectionEnd_AppException_Generic = k_ESteamNetConnectionEnd_AppException_Min, + // Use codes in this range for "unusual" disconnection + k_ESteamNetConnectionEnd_AppException_Max = 2999, + + // + // System codes. These will be returned by the system when + // the connection state is k_ESteamNetworkingConnectionState_ClosedByPeer + // or k_ESteamNetworkingConnectionState_ProblemDetectedLocally. It is + // illegal to pass a code in this range to ISteamNetworkingSockets::CloseConnection + // + + // 3xxx: Connection failed or ended because of problem with the + // local host or their connection to the Internet. + k_ESteamNetConnectionEnd_Local_Min = 3000, + + // You cannot do what you want to do because you're running in offline mode. + k_ESteamNetConnectionEnd_Local_OfflineMode = 3001, + + // We're having trouble contacting many (perhaps all) relays. + // Since it's unlikely that they all went offline at once, the best + // explanation is that we have a problem on our end. Note that we don't + // bother distinguishing between "many" and "all", because in practice, + // it takes time to detect a connection problem, and by the time + // the connection has timed out, we might not have been able to + // actively probe all of the relay clusters, even if we were able to + // contact them at one time. So this code just means that: + // + // * We don't have any recent successful communication with any relay. + // * We have evidence of recent failures to communicate with multiple relays. + k_ESteamNetConnectionEnd_Local_ManyRelayConnectivity = 3002, + + // A hosted server is having trouble talking to the relay + // that the client was using, so the problem is most likely + // on our end + k_ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay = 3003, + + // We're not able to get the SDR network config. This is + // *almost* always a local issue, since the network config + // comes from the CDN, which is pretty darn reliable. + k_ESteamNetConnectionEnd_Local_NetworkConfig = 3004, + + // Steam rejected our request because we don't have rights + // to do this. + k_ESteamNetConnectionEnd_Local_Rights = 3005, + + // ICE P2P rendezvous failed because we were not able to + // determine our "public" address (e.g. reflexive address via STUN) + // + // If relay fallback is available (it always is on Steam), then + // this is only used internally and will not be returned as a high + // level failure. + k_ESteamNetConnectionEnd_Local_P2P_ICE_NoPublicAddresses = 3006, + + k_ESteamNetConnectionEnd_Local_Max = 3999, + + // 4xxx: Connection failed or ended, and it appears that the + // cause does NOT have to do with the local host or their + // connection to the Internet. It could be caused by the + // remote host, or it could be somewhere in between. + k_ESteamNetConnectionEnd_Remote_Min = 4000, + + // The connection was lost, and as far as we can tell our connection + // to relevant services (relays) has not been disrupted. This doesn't + // mean that the problem is "their fault", it just means that it doesn't + // appear that we are having network issues on our end. + k_ESteamNetConnectionEnd_Remote_Timeout = 4001, + + // Something was invalid with the cert or crypt handshake + // info you gave me, I don't understand or like your key types, + // etc. + k_ESteamNetConnectionEnd_Remote_BadCrypt = 4002, + + // You presented me with a cert that was I was able to parse + // and *technically* we could use encrypted communication. + // But there was a problem that prevents me from checking your identity + // or ensuring that somebody int he middle can't observe our communication. + // E.g.: - the CA key was missing (and I don't accept unsigned certs) + // - The CA key isn't one that I trust, + // - The cert doesn't was appropriately restricted by app, user, time, data center, etc. + // - The cert wasn't issued to you. + // - etc + k_ESteamNetConnectionEnd_Remote_BadCert = 4003, + + // These will never be returned + //k_ESteamNetConnectionEnd_Remote_NotLoggedIn_DEPRECATED = 4004, + //k_ESteamNetConnectionEnd_Remote_NotRunningApp_DEPRECATED = 4005, + + // Something wrong with the protocol version you are using. + // (Probably the code you are running is too old.) + k_ESteamNetConnectionEnd_Remote_BadProtocolVersion = 4006, + + // NAT punch failed failed because we never received any public + // addresses from the remote host. (But we did receive some + // signals form them.) + // + // If relay fallback is available (it always is on Steam), then + // this is only used internally and will not be returned as a high + // level failure. + k_ESteamNetConnectionEnd_Remote_P2P_ICE_NoPublicAddresses = 4007, + + k_ESteamNetConnectionEnd_Remote_Max = 4999, + + // 5xxx: Connection failed for some other reason. + k_ESteamNetConnectionEnd_Misc_Min = 5000, + + // A failure that isn't necessarily the result of a software bug, + // but that should happen rarely enough that it isn't worth specifically + // writing UI or making a localized message for. + // The debug string should contain further details. + k_ESteamNetConnectionEnd_Misc_Generic = 5001, + + // Generic failure that is most likely a software bug. + k_ESteamNetConnectionEnd_Misc_InternalError = 5002, + + // The connection to the remote host timed out, but we + // don't know if the problem is on our end, in the middle, + // or on their end. + k_ESteamNetConnectionEnd_Misc_Timeout = 5003, + + //k_ESteamNetConnectionEnd_Misc_RelayConnectivity_DEPRECATED = 5004, + + // There's some trouble talking to Steam. + k_ESteamNetConnectionEnd_Misc_SteamConnectivity = 5005, + + // A server in a dedicated hosting situation has no relay sessions + // active with which to talk back to a client. (It's the client's + // job to open and maintain those sessions.) + k_ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient = 5006, + + // While trying to initiate a connection, we never received + // *any* communication from the peer. + //k_ESteamNetConnectionEnd_Misc_ServerNeverReplied = 5007, + + // P2P rendezvous failed in a way that we don't have more specific + // information + k_ESteamNetConnectionEnd_Misc_P2P_Rendezvous = 5008, + + // NAT punch failed, probably due to NAT/firewall configuration. + // + // If relay fallback is available (it always is on Steam), then + // this is only used internally and will not be returned as a high + // level failure. + k_ESteamNetConnectionEnd_Misc_P2P_NAT_Firewall = 5009, + + // Our peer replied that it has no record of the connection. + // This should not happen ordinarily, but can happen in a few + // exception cases: + // + // - This is an old connection, and the peer has already cleaned + // up and forgotten about it. (Perhaps it timed out and they + // closed it and were not able to communicate this to us.) + // - A bug or internal protocol error has caused us to try to + // talk to the peer about the connection before we received + // confirmation that the peer has accepted the connection. + // - The peer thinks that we have closed the connection for some + // reason (perhaps a bug), and believes that is it is + // acknowledging our closure. + k_ESteamNetConnectionEnd_Misc_PeerSentNoConnection = 5010, + + k_ESteamNetConnectionEnd_Misc_Max = 5999, + + k_ESteamNetConnectionEnd__Force32Bit = 0x7fffffff + } + + // + // Configuration values + // + /// Configuration values can be applied to different types of objects. + public enum ESteamNetworkingConfigScope : int { + + /// Get/set global option, or defaults. Even options that apply to more specific scopes + /// have global scope, and you may be able to just change the global defaults. If you + /// need different settings per connection (for example), then you will need to set those + /// options at the more specific scope. + k_ESteamNetworkingConfig_Global = 1, + + /// Some options are specific to a particular interface. Note that all connection + /// and listen socket settings can also be set at the interface level, and they will + /// apply to objects created through those interfaces. + k_ESteamNetworkingConfig_SocketsInterface = 2, + + /// Options for a listen socket. Listen socket options can be set at the interface layer, + /// if you have multiple listen sockets and they all use the same options. + /// You can also set connection options on a listen socket, and they set the defaults + /// for all connections accepted through this listen socket. (They will be used if you don't + /// set a connection option.) + k_ESteamNetworkingConfig_ListenSocket = 3, + + /// Options for a specific connection. + k_ESteamNetworkingConfig_Connection = 4, + + k_ESteamNetworkingConfigScope__Force32Bit = 0x7fffffff + } + + // Different configuration values have different data types + public enum ESteamNetworkingConfigDataType : int { + k_ESteamNetworkingConfig_Int32 = 1, + k_ESteamNetworkingConfig_Int64 = 2, + k_ESteamNetworkingConfig_Float = 3, + k_ESteamNetworkingConfig_String = 4, + k_ESteamNetworkingConfig_Ptr = 5, + + k_ESteamNetworkingConfigDataType__Force32Bit = 0x7fffffff + } + + /// Configuration options + public enum ESteamNetworkingConfigValue : int { + k_ESteamNetworkingConfig_Invalid = 0, + + // + // Connection options + // + + /// [connection int32] Timeout value (in ms) to use when first connecting + k_ESteamNetworkingConfig_TimeoutInitial = 24, + + /// [connection int32] Timeout value (in ms) to use after connection is established + k_ESteamNetworkingConfig_TimeoutConnected = 25, + + /// [connection int32] Upper limit of buffered pending bytes to be sent, + /// if this is reached SendMessage will return k_EResultLimitExceeded + /// Default is 512k (524288 bytes) + k_ESteamNetworkingConfig_SendBufferSize = 9, + + /// [connection int64] Get/set userdata as a configuration option. + /// The default value is -1. You may want to set the user data as + /// a config value, instead of using ISteamNetworkingSockets::SetConnectionUserData + /// in two specific instances: + /// + /// - You wish to set the userdata atomically when creating + /// an outbound connection, so that the userdata is filled in properly + /// for any callbacks that happen. However, note that this trick + /// only works for connections initiated locally! For incoming + /// connections, multiple state transitions may happen and + /// callbacks be queued, before you are able to service the first + /// callback! Be careful! + /// + /// - You can set the default userdata for all newly created connections + /// by setting this value at a higher level (e.g. on the listen + /// socket or at the global level.) Then this default + /// value will be inherited when the connection is created. + /// This is useful in case -1 is a valid userdata value, and you + /// wish to use something else as the default value so you can + /// tell if it has been set or not. + /// + /// HOWEVER: once a connection is created, the effective value is + /// then bound to the connection. Unlike other connection options, + /// if you change it again at a higher level, the new value will not + /// be inherited by connections. + /// + /// Using the userdata field in callback structs is not advised because + /// of tricky race conditions. Instead, you might try one of these methods: + /// + /// - Use a separate map with the HSteamNetConnection as the key. + /// - Fetch the userdata from the connection in your callback + /// using ISteamNetworkingSockets::GetConnectionUserData, to + // ensure you have the current value. + k_ESteamNetworkingConfig_ConnectionUserData = 40, + + /// [connection int32] Minimum/maximum send rate clamp, 0 is no limit. + /// This value will control the min/max allowed sending rate that + /// bandwidth estimation is allowed to reach. Default is 0 (no-limit) + k_ESteamNetworkingConfig_SendRateMin = 10, + k_ESteamNetworkingConfig_SendRateMax = 11, + + /// [connection int32] Nagle time, in microseconds. When SendMessage is called, if + /// the outgoing message is less than the size of the MTU, it will be + /// queued for a delay equal to the Nagle timer value. This is to ensure + /// that if the application sends several small messages rapidly, they are + /// coalesced into a single packet. + /// See historical RFC 896. Value is in microseconds. + /// Default is 5000us (5ms). + k_ESteamNetworkingConfig_NagleTime = 12, + + /// [connection int32] Don't automatically fail IP connections that don't have + /// strong auth. On clients, this means we will attempt the connection even if + /// we don't know our identity or can't get a cert. On the server, it means that + /// we won't automatically reject a connection due to a failure to authenticate. + /// (You can examine the incoming connection and decide whether to accept it.) + /// + /// This is a dev configuration value, and you should not let users modify it in + /// production. + k_ESteamNetworkingConfig_IP_AllowWithoutAuth = 23, + + /// [connection int32] Do not send UDP packets with a payload of + /// larger than N bytes. If you set this, k_ESteamNetworkingConfig_MTU_DataSize + /// is automatically adjusted + k_ESteamNetworkingConfig_MTU_PacketSize = 32, + + /// [connection int32] (read only) Maximum message size you can send that + /// will not fragment, based on k_ESteamNetworkingConfig_MTU_PacketSize + k_ESteamNetworkingConfig_MTU_DataSize = 33, + + /// [connection int32] Allow unencrypted (and unauthenticated) communication. + /// 0: Not allowed (the default) + /// 1: Allowed, but prefer encrypted + /// 2: Allowed, and preferred + /// 3: Required. (Fail the connection if the peer requires encryption.) + /// + /// This is a dev configuration value, since its purpose is to disable encryption. + /// You should not let users modify it in production. (But note that it requires + /// the peer to also modify their value in order for encryption to be disabled.) + k_ESteamNetworkingConfig_Unencrypted = 34, + + /// [connection int32] Set this to 1 on outbound connections and listen sockets, + /// to enable "symmetric connect mode", which is useful in the following + /// common peer-to-peer use case: + /// + /// - The two peers are "equal" to each other. (Neither is clearly the "client" + /// or "server".) + /// - Either peer may initiate the connection, and indeed they may do this + /// at the same time + /// - The peers only desire a single connection to each other, and if both + /// peers initiate connections simultaneously, a protocol is needed for them + /// to resolve the conflict, so that we end up with a single connection. + /// + /// This use case is both common, and involves subtle race conditions and tricky + /// pitfalls, which is why the API has support for dealing with it. + /// + /// If an incoming connection arrives on a listen socket or via custom signaling, + /// and the application has not attempted to make a matching outbound connection + /// in symmetric mode, then the incoming connection can be accepted as usual. + /// A "matching" connection means that the relevant endpoint information matches. + /// (At the time this comment is being written, this is only supported for P2P + /// connections, which means that the peer identities must match, and the virtual + /// port must match. At a later time, symmetric mode may be supported for other + /// connection types.) + /// + /// If connections are initiated by both peers simultaneously, race conditions + /// can arise, but fortunately, most of them are handled internally and do not + /// require any special awareness from the application. However, there + /// is one important case that application code must be aware of: + /// If application code attempts an outbound connection using a ConnectXxx + /// function in symmetric mode, and a matching incoming connection is already + /// waiting on a listen socket, then instead of forming a new connection, + /// the ConnectXxx call will accept the existing incoming connection, and return + /// a connection handle to this accepted connection. + /// IMPORTANT: in this case, a SteamNetConnectionStatusChangedCallback_t + /// has probably *already* been posted to the queue for the incoming connection! + /// (Once callbacks are posted to the queue, they are not modified.) It doesn't + /// matter if the callback has not been consumed by the app. Thus, application + /// code that makes use of symmetric connections must be aware that, when processing a + /// SteamNetConnectionStatusChangedCallback_t for an incoming connection, the + /// m_hConn may refer to a new connection that the app has has not + /// seen before (the usual case), but it may also refer to a connection that + /// has already been accepted implicitly through a call to Connect()! In this + /// case, AcceptConnection() will return k_EResultDuplicateRequest. + /// + /// Only one symmetric connection to a given peer (on a given virtual port) + /// may exist at any given time. If client code attempts to create a connection, + /// and a (live) connection already exists on the local host, then either the + /// existing connection will be accepted as described above, or the attempt + /// to create a new connection will fail. Furthermore, linger mode functionality + /// is not supported on symmetric connections. + /// + /// A more complicated race condition can arise if both peers initiate a connection + /// at roughly the same time. In this situation, each peer will receive an incoming + /// connection from the other peer, when the application code has already initiated + /// an outgoing connection to that peer. The peers must resolve this conflict and + /// decide who is going to act as the "server" and who will act as the "client". + /// Typically the application does not need to be aware of this case as it is handled + /// internally. On both sides, the will observe their outbound connection being + /// "accepted", although one of them one have been converted internally to act + /// as the "server". + /// + /// In general, symmetric mode should be all-or-nothing: do not mix symmetric + /// connections with a non-symmetric connection that it might possible "match" + /// with. If you use symmetric mode on any connections, then both peers should + /// use it on all connections, and the corresponding listen socket, if any. The + /// behaviour when symmetric and ordinary connections are mixed is not defined by + /// this API, and you should not rely on it. (This advice only applies when connections + /// might possibly "match". For example, it's OK to use all symmetric mode + /// connections on one virtual port, and all ordinary, non-symmetric connections + /// on a different virtual port, as there is no potential for ambiguity.) + /// + /// When using the feature, you should set it in the following situations on + /// applicable objects: + /// + /// - When creating an outbound connection using ConnectXxx function + /// - When creating a listen socket. (Note that this will automatically cause + /// any accepted connections to inherit the flag.) + /// - When using custom signaling, before accepting an incoming connection. + /// + /// Setting the flag on listen socket and accepted connections will enable the + /// API to automatically deal with duplicate incoming connections, even if the + /// local host has not made any outbound requests. (In general, such duplicate + /// requests from a peer are ignored internally and will not be visible to the + /// application code. The previous connection must be closed or resolved first.) + k_ESteamNetworkingConfig_SymmetricConnect = 37, + + /// [connection int32] For connection types that use "virtual ports", this can be used + /// to assign a local virtual port. For incoming connections, this will always be the + /// virtual port of the listen socket (or the port requested by the remote host if custom + /// signaling is used and the connection is accepted), and cannot be changed. For + /// connections initiated locally, the local virtual port will default to the same as the + /// requested remote virtual port, if you do not specify a different option when creating + /// the connection. The local port is only relevant for symmetric connections, when + /// determining if two connections "match." In this case, if you need the local and remote + /// port to differ, you can set this value. + /// + /// You can also read back this value on listen sockets. + /// + /// This value should not be read or written in any other context. + k_ESteamNetworkingConfig_LocalVirtualPort = 38, + + /// [connection int32] Enable Dual wifi band support for this connection + /// 0 = no, 1 = yes, 2 = simulate it for debugging, even if dual wifi not available + k_ESteamNetworkingConfig_DualWifi_Enable = 39, + + /// [connection int32] True to enable diagnostics reporting through + /// generic platform UI. (Only available on Steam.) + k_ESteamNetworkingConfig_EnableDiagnosticsUI = 46, + + // + // Simulating network conditions + // + // These are global (not per-connection) because they apply at + // a relatively low UDP layer. + // + + /// [global float, 0--100] Randomly discard N pct of packets instead of sending/recv + /// This is a global option only, since it is applied at a low level + /// where we don't have much context + k_ESteamNetworkingConfig_FakePacketLoss_Send = 2, + k_ESteamNetworkingConfig_FakePacketLoss_Recv = 3, + + /// [global int32]. Delay all outbound/inbound packets by N ms + k_ESteamNetworkingConfig_FakePacketLag_Send = 4, + k_ESteamNetworkingConfig_FakePacketLag_Recv = 5, + + /// [global float] 0-100 Percentage of packets we will add additional delay + /// to (causing them to be reordered) + k_ESteamNetworkingConfig_FakePacketReorder_Send = 6, + k_ESteamNetworkingConfig_FakePacketReorder_Recv = 7, + + /// [global int32] Extra delay, in ms, to apply to reordered packets. + k_ESteamNetworkingConfig_FakePacketReorder_Time = 8, + + /// [global float 0--100] Globally duplicate some percentage of packets we send + k_ESteamNetworkingConfig_FakePacketDup_Send = 26, + k_ESteamNetworkingConfig_FakePacketDup_Recv = 27, + + /// [global int32] Amount of delay, in ms, to delay duplicated packets. + /// (We chose a random delay between 0 and this value) + k_ESteamNetworkingConfig_FakePacketDup_TimeMax = 28, + + /// [global int32] Trace every UDP packet, similar to Wireshark or tcpdump. + /// Value is max number of bytes to dump. -1 disables tracing. + // 0 only traces the info but no actual data bytes + k_ESteamNetworkingConfig_PacketTraceMaxBytes = 41, + + + // [global int32] Global UDP token bucket rate limits. + // "Rate" refers to the steady state rate. (Bytes/sec, the + // rate that tokens are put into the bucket.) "Burst" + // refers to the max amount that could be sent in a single + // burst. (In bytes, the max capacity of the bucket.) + // Rate=0 disables the limiter entirely, which is the default. + // Burst=0 disables burst. (This is not realistic. A + // burst of at least 4K is recommended; the default is higher.) + k_ESteamNetworkingConfig_FakeRateLimit_Send_Rate = 42, + k_ESteamNetworkingConfig_FakeRateLimit_Send_Burst = 43, + k_ESteamNetworkingConfig_FakeRateLimit_Recv_Rate = 44, + k_ESteamNetworkingConfig_FakeRateLimit_Recv_Burst = 45, + + // + // Callbacks + // + + // On Steam, you may use the default Steam callback dispatch mechanism. If you prefer + // to not use this dispatch mechanism (or you are not running with Steam), or you want + // to associate specific functions with specific listen sockets or connections, you can + // register them as configuration values. + // + // Note also that ISteamNetworkingUtils has some helpers to set these globally. + + /// [connection FnSteamNetConnectionStatusChanged] Callback that will be invoked + /// when the state of a connection changes. + /// + /// IMPORTANT: callbacks are dispatched to the handler that is in effect at the time + /// the event occurs, which might be in another thread. For example, immediately after + /// creating a listen socket, you may receive an incoming connection. And then immediately + /// after this, the remote host may close the connection. All of this could happen + /// before the function to create the listen socket has returned. For this reason, + /// callbacks usually must be in effect at the time of object creation. This means + /// you should set them when you are creating the listen socket or connection, or have + /// them in effect so they will be inherited at the time of object creation. + /// + /// For example: + /// + /// exterm void MyStatusChangedFunc( SteamNetConnectionStatusChangedCallback_t *info ); + /// SteamNetworkingConfigValue_t opt; opt.SetPtr( k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, MyStatusChangedFunc ); + /// SteamNetworkingIPAddr localAddress; localAddress.Clear(); + /// HSteamListenSocket hListenSock = SteamNetworkingSockets()->CreateListenSocketIP( localAddress, 1, &opt ); + /// + /// When accepting an incoming connection, there is no atomic way to switch the + /// callback. However, if the connection is DOA, AcceptConnection() will fail, and + /// you can fetch the state of the connection at that time. + /// + /// If all connections and listen sockets can use the same callback, the simplest + /// method is to set it globally before you create any listen sockets or connections. + k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged = 201, + + /// [global FnSteamNetAuthenticationStatusChanged] Callback that will be invoked + /// when our auth state changes. If you use this, install the callback before creating + /// any connections or listen sockets, and don't change it. + /// See: ISteamNetworkingUtils::SetGlobalCallback_SteamNetAuthenticationStatusChanged + k_ESteamNetworkingConfig_Callback_AuthStatusChanged = 202, + + /// [global FnSteamRelayNetworkStatusChanged] Callback that will be invoked + /// when our auth state changes. If you use this, install the callback before creating + /// any connections or listen sockets, and don't change it. + /// See: ISteamNetworkingUtils::SetGlobalCallback_SteamRelayNetworkStatusChanged + k_ESteamNetworkingConfig_Callback_RelayNetworkStatusChanged = 203, + + /// [global FnSteamNetworkingMessagesSessionRequest] Callback that will be invoked + /// when a peer wants to initiate a SteamNetworkingMessagesSessionRequest. + /// See: ISteamNetworkingUtils::SetGlobalCallback_MessagesSessionRequest + k_ESteamNetworkingConfig_Callback_MessagesSessionRequest = 204, + + /// [global FnSteamNetworkingMessagesSessionFailed] Callback that will be invoked + /// when a session you have initiated, or accepted either fails to connect, or loses + /// connection in some unexpected way. + /// See: ISteamNetworkingUtils::SetGlobalCallback_MessagesSessionFailed + k_ESteamNetworkingConfig_Callback_MessagesSessionFailed = 205, + + /// [global FnSteamNetworkingSocketsCreateConnectionSignaling] Callback that will + /// be invoked when we need to create a signaling object for a connection + /// initiated locally. See: ISteamNetworkingSockets::ConnectP2P, + /// ISteamNetworkingMessages. + k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling = 206, + + /// [global FnSteamNetworkingFakeIPResult] Callback that's invoked when + /// a FakeIP allocation finishes. See: ISteamNetworkingSockets::BeginAsyncRequestFakeIP, + /// ISteamNetworkingUtils::SetGlobalCallback_FakeIPResult + k_ESteamNetworkingConfig_Callback_FakeIPResult = 207, + + // + // P2P connection settings + // + + // /// [listen socket int32] When you create a P2P listen socket, we will automatically + // /// open up a UDP port to listen for LAN connections. LAN connections can be made + // /// without any signaling: both sides can be disconnected from the Internet. + // /// + // /// This value can be set to zero to disable the feature. + // k_ESteamNetworkingConfig_P2P_Discovery_Server_LocalPort = 101, + // + // /// [connection int32] P2P connections can perform broadcasts looking for the peer + // /// on the LAN. + // k_ESteamNetworkingConfig_P2P_Discovery_Client_RemotePort = 102, + + /// [connection string] Comma-separated list of STUN servers that can be used + /// for NAT piercing. If you set this to an empty string, NAT piercing will + /// not be attempted. Also if "public" candidates are not allowed for + /// P2P_Transport_ICE_Enable, then this is ignored. + k_ESteamNetworkingConfig_P2P_STUN_ServerList = 103, + + /// [connection int32] What types of ICE candidates to share with the peer. + /// See k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_xxx values + k_ESteamNetworkingConfig_P2P_Transport_ICE_Enable = 104, + + /// [connection int32] When selecting P2P transport, add various + /// penalties to the scores for selected transports. (Route selection + /// scores are on a scale of milliseconds. The score begins with the + /// route ping time and is then adjusted.) + k_ESteamNetworkingConfig_P2P_Transport_ICE_Penalty = 105, + k_ESteamNetworkingConfig_P2P_Transport_SDR_Penalty = 106, + k_ESteamNetworkingConfig_P2P_TURN_ServerList = 107, + k_ESteamNetworkingConfig_P2P_TURN_UserList = 108, + k_ESteamNetworkingConfig_P2P_TURN_PassList = 109, + //k_ESteamNetworkingConfig_P2P_Transport_LANBeacon_Penalty = 107, + k_ESteamNetworkingConfig_P2P_Transport_ICE_Implementation = 110, + + // + // Settings for SDR relayed connections + // + + /// [int32 global] If the first N pings to a port all fail, mark that port as unavailable for + /// a while, and try a different one. Some ISPs and routers may drop the first + /// packet, so setting this to 1 may greatly disrupt communications. + k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFailInitial = 19, + + /// [int32 global] If N consecutive pings to a port fail, after having received successful + /// communication, mark that port as unavailable for a while, and try a + /// different one. + k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFail = 20, + + /// [int32 global] Minimum number of lifetime pings we need to send, before we think our estimate + /// is solid. The first ping to each cluster is very often delayed because of NAT, + /// routers not having the best route, etc. Until we've sent a sufficient number + /// of pings, our estimate is often inaccurate. Keep pinging until we get this + /// many pings. + k_ESteamNetworkingConfig_SDRClient_MinPingsBeforePingAccurate = 21, + + /// [int32 global] Set all steam datagram traffic to originate from the same + /// local port. By default, we open up a new UDP socket (on a different local + /// port) for each relay. This is slightly less optimal, but it works around + /// some routers that don't implement NAT properly. If you have intermittent + /// problems talking to relays that might be NAT related, try toggling + /// this flag + k_ESteamNetworkingConfig_SDRClient_SingleSocket = 22, + + /// [global string] Code of relay cluster to force use. If not empty, we will + /// only use relays in that cluster. E.g. 'iad' + k_ESteamNetworkingConfig_SDRClient_ForceRelayCluster = 29, + + /// [connection string] For debugging, generate our own (unsigned) ticket, using + /// the specified gameserver address. Router must be configured to accept unsigned + /// tickets. + k_ESteamNetworkingConfig_SDRClient_DebugTicketAddress = 30, + + /// [global string] For debugging. Override list of relays from the config with + /// this set (maybe just one). Comma-separated list. + k_ESteamNetworkingConfig_SDRClient_ForceProxyAddr = 31, + + /// [global string] For debugging. Force ping times to clusters to be the specified + /// values. A comma separated list of = values. E.g. "sto=32,iad=100" + /// + /// This is a dev configuration value, you probably should not let users modify it + /// in production. + k_ESteamNetworkingConfig_SDRClient_FakeClusterPing = 36, + + // + // Log levels for debugging information of various subsystems. + // Higher numeric values will cause more stuff to be printed. + // See ISteamNetworkingUtils::SetDebugOutputFunction for more + // information + // + // The default for all values is k_ESteamNetworkingSocketsDebugOutputType_Warning. + // + k_ESteamNetworkingConfig_LogLevel_AckRTT = 13, // [connection int32] RTT calculations for inline pings and replies + k_ESteamNetworkingConfig_LogLevel_PacketDecode = 14, // [connection int32] log SNP packets send/recv + k_ESteamNetworkingConfig_LogLevel_Message = 15, // [connection int32] log each message send/recv + k_ESteamNetworkingConfig_LogLevel_PacketGaps = 16, // [connection int32] dropped packets + k_ESteamNetworkingConfig_LogLevel_P2PRendezvous = 17, // [connection int32] P2P rendezvous messages + k_ESteamNetworkingConfig_LogLevel_SDRRelayPings = 18, // [global int32] Ping relays + + + // Deleted, do not use + k_ESteamNetworkingConfig_DELETED_EnumerateDevVars = 35, + + k_ESteamNetworkingConfigValue__Force32Bit = 0x7fffffff + } + + /// Return value of ISteamNetworkintgUtils::GetConfigValue + public enum ESteamNetworkingGetConfigValueResult : int { + k_ESteamNetworkingGetConfigValue_BadValue = -1, // No such configuration value + k_ESteamNetworkingGetConfigValue_BadScopeObj = -2, // Bad connection handle, etc + k_ESteamNetworkingGetConfigValue_BufferTooSmall = -3, // Couldn't fit the result in your buffer + k_ESteamNetworkingGetConfigValue_OK = 1, + k_ESteamNetworkingGetConfigValue_OKInherited = 2, // A value was not set at this level, but the effective (inherited) value was returned. + + k_ESteamNetworkingGetConfigValueResult__Force32Bit = 0x7fffffff + } + + // + // Debug output + // + /// Detail level for diagnostic output callback. + /// See ISteamNetworkingUtils::SetDebugOutputFunction + public enum ESteamNetworkingSocketsDebugOutputType : int { + k_ESteamNetworkingSocketsDebugOutputType_None = 0, + k_ESteamNetworkingSocketsDebugOutputType_Bug = 1, // You used the API incorrectly, or an internal error happened + k_ESteamNetworkingSocketsDebugOutputType_Error = 2, // Run-time error condition that isn't the result of a bug. (E.g. we are offline, cannot bind a port, etc) + k_ESteamNetworkingSocketsDebugOutputType_Important = 3, // Nothing is wrong, but this is an important notification + k_ESteamNetworkingSocketsDebugOutputType_Warning = 4, + k_ESteamNetworkingSocketsDebugOutputType_Msg = 5, // Recommended amount + k_ESteamNetworkingSocketsDebugOutputType_Verbose = 6, // Quite a bit + k_ESteamNetworkingSocketsDebugOutputType_Debug = 7, // Practically everything + k_ESteamNetworkingSocketsDebugOutputType_Everything = 8, // Wall of text, detailed packet contents breakdown, etc + + k_ESteamNetworkingSocketsDebugOutputType__Force32Bit = 0x7fffffff + } + + public enum ESteamIPType : int { + k_ESteamIPTypeIPv4 = 0, + k_ESteamIPTypeIPv6 = 1, + } + + // Steam universes. Each universe is a self-contained Steam instance. + public enum EUniverse : int { + k_EUniverseInvalid = 0, + k_EUniversePublic = 1, + k_EUniverseBeta = 2, + k_EUniverseInternal = 3, + k_EUniverseDev = 4, + // k_EUniverseRC = 5, // no such universe anymore + k_EUniverseMax + } + +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamEnums.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamEnums.cs.meta new file mode 100644 index 0000000..4a12139 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamEnums.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e736b081fa90e7d4b89c2062fd2c6526 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamStructs.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamStructs.cs new file mode 100644 index 0000000..49df056 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamStructs.cs @@ -0,0 +1,452 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + // friend game played information + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct FriendGameInfo_t { + public CGameID m_gameID; + public uint m_unGameIP; + public ushort m_usGamePort; + public ushort m_usQueryPort; + public CSteamID m_steamIDLobby; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct InputAnalogActionData_t { + // Type of data coming from this action, this will match what got specified in the action set + public EInputSourceMode eMode; + + // The current state of this action; will be delta updates for mouse actions + public float x, y; + + // Whether or not this action is currently available to be bound in the active action set + public byte bActive; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct InputDigitalActionData_t { + // The current state of this action; will be true if currently pressed + public byte bState; + + // Whether or not this action is currently available to be bound in the active action set + public byte bActive; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct InputMotionData_t { + // Sensor-fused absolute rotation; will drift in heading toward average + public float rotQuatX; + public float rotQuatY; + public float rotQuatZ; + public float rotQuatW; + + // Positional acceleration + public float posAccelX; + public float posAccelY; + public float posAccelZ; + + // Angular velocity + public float rotVelX; + public float rotVelY; + public float rotVelZ; + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct InputMotionDataV2_t { + // + // Gyro post processing: + // + + // Drift Corrected Quaternion is calculated after steam input controller calibration values have been applied. + // Rawest _useful_ version of a quaternion. + // Most camera implementations should use this by comparing last rotation against current rotation, and applying the difference to the in game camera (plus your own sensitivity tweaks) + // It is worth viewing + public float driftCorrectedQuatX; + public float driftCorrectedQuatY; + public float driftCorrectedQuatZ; + public float driftCorrectedQuatW; + + // Sensor fusion corrects using accelerometer, and "average forward over time" for "forward". + // This can "ouija" your aim, so it's not so appropriate for camera controls (sensor fusion was originally made for racing game steering ) + // Same result as from old InputMotionData_t::rotQuatX/Y/Z/W + public float sensorFusionQuatX; + public float sensorFusionQuatY; + public float sensorFusionQuatZ; + public float sensorFusionQuatW; + + // Deferred Sensor fusion quaternion with deferred correction + // Reduces perception of "ouija" effect by only applying correction when the controller is below "low noise" thresholds, + // while the controller rotates fast - never when the user is attempting precision aim. + public float deferredSensorFusionQuatX; + public float deferredSensorFusionQuatY; + public float deferredSensorFusionQuatZ; + public float deferredSensorFusionQuatW; + + // Same as accel but values are calibrated such that 1 unit = 1G. + // X = Right + // Y = Forward out through the joystick USB port. + // Z = Up through the joystick axis. + public float gravityX; + public float gravityY; + public float gravityZ; + + // + // Same as rotVel values in GetMotionData but values are calibrated to degrees per second. + // Local Space (controller relative) + // X = Pitch = left to right axis + // Y = Roll = axis through charging port + // Z = Yaw = axis through sticks + public float degreesPerSecondX; + public float degreesPerSecondY; + public float degreesPerSecondZ; + + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamItemDetails_t { + public SteamItemInstanceID_t m_itemId; + public SteamItemDef_t m_iDefinition; + public ushort m_unQuantity; + public ushort m_unFlags; // see ESteamItemFlags + } + + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamPartyBeaconLocation_t { + public ESteamPartyBeaconLocationType m_eType; + public ulong m_ulLocationID; + } + + // connection state to a specified user, returned by GetP2PSessionState() + // this is under-the-hood info about what's going on with a SendP2PPacket(), shouldn't be needed except for debuggin + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct P2PSessionState_t { + public byte m_bConnectionActive; // true if we've got an active open connection + public byte m_bConnecting; // true if we're currently trying to establish a connection + public byte m_eP2PSessionError; // last error recorded (see enum above) + public byte m_bUsingRelay; // true if it's going through a relay server (TURN) + public int m_nBytesQueuedForSend; + public int m_nPacketsQueuedForSend; + public uint m_nRemoteIP; // potential IP:Port of remote host. Could be TURN server. + public ushort m_nRemotePort; // Only exists for compatibility with older authentication api's + } + + //----------------------------------------------------------------------------- + // Purpose: Structure that contains an array of const char * strings and the number of those strings + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamParamStringArray_t { + public IntPtr m_ppStrings; + public int m_nNumStrings; + } + + // Details for a single published file/UGC + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamUGCDetails_t { + public PublishedFileId_t m_nPublishedFileId; + public EResult m_eResult; // The result of the operation. + public EWorkshopFileType m_eFileType; // Type of the file + public AppId_t m_nCreatorAppID; // ID of the app that created this file. + public AppId_t m_nConsumerAppID; // ID of the app that will consume this file. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedDocumentTitleMax)] + private byte[] m_rgchTitle_; + public string m_rgchTitle // title of document + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchTitle_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchTitle_, Constants.k_cchPublishedDocumentTitleMax); } + } + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedDocumentDescriptionMax)] + private byte[] m_rgchDescription_; + public string m_rgchDescription // description of document + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchDescription_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchDescription_, Constants.k_cchPublishedDocumentDescriptionMax); } + } + public ulong m_ulSteamIDOwner; // Steam ID of the user who created this content. + public uint m_rtimeCreated; // time when the published file was created + public uint m_rtimeUpdated; // time when the published file was last updated + public uint m_rtimeAddedToUserList; // time when the user added the published file to their list (not always applicable) + public ERemoteStoragePublishedFileVisibility m_eVisibility; // visibility + [MarshalAs(UnmanagedType.I1)] + public bool m_bBanned; // whether the file was banned + [MarshalAs(UnmanagedType.I1)] + public bool m_bAcceptedForUse; // developer has specifically flagged this item as accepted in the Workshop + [MarshalAs(UnmanagedType.I1)] + public bool m_bTagsTruncated; // whether the list of tags was too long to be returned in the provided buffer + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchTagListMax)] + private byte[] m_rgchTags_; + public string m_rgchTags // comma separated list of all tags associated with this file + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchTags_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchTags_, Constants.k_cchTagListMax); } + } + // file/url information + public UGCHandle_t m_hFile; // The handle of the primary file + public UGCHandle_t m_hPreviewFile; // The handle of the preview file + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchFilenameMax)] + private byte[] m_pchFileName_; + public string m_pchFileName // The cloud filename of the primary file + { + get { return InteropHelp.ByteArrayToStringUTF8(m_pchFileName_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_pchFileName_, Constants.k_cchFilenameMax); } + } + public int m_nFileSize; // Size of the primary file + public int m_nPreviewFileSize; // Size of the preview file + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedFileURLMax)] + private byte[] m_rgchURL_; + public string m_rgchURL // URL (for a video or a website) + { + get { return InteropHelp.ByteArrayToStringUTF8(m_rgchURL_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_rgchURL_, Constants.k_cchPublishedFileURLMax); } + } + // voting information + public uint m_unVotesUp; // number of votes up + public uint m_unVotesDown; // number of votes down + public float m_flScore; // calculated score + // collection details + public uint m_unNumChildren; + } + + // a single entry in a leaderboard, as returned by GetDownloadedLeaderboardEntry() + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct LeaderboardEntry_t { + public CSteamID m_steamIDUser; // user with the entry - use SteamFriends()->GetFriendPersonaName() & SteamFriends()->GetFriendAvatar() to get more info + public int m_nGlobalRank; // [1..N], where N is the number of users with an entry in the leaderboard + public int m_nScore; // score as set in the leaderboard + public int m_cDetails; // number of int32 details available for this entry + public UGCHandle_t m_hUGC; // handle for UGC attached to the entry + } + + /// Store key/value pair used in matchmaking queries. + /// + /// Actually, the name Key/Value is a bit misleading. The "key" is better + /// understood as "filter operation code" and the "value" is the operand to this + /// filter operation. The meaning of the operand depends upon the filter. + [StructLayout(LayoutKind.Sequential)] + public struct MatchMakingKeyValuePair_t { + MatchMakingKeyValuePair_t(string strKey, string strValue) { + m_szKey = strKey; + m_szValue = strValue; + } + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string m_szKey; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string m_szValue; + } + + // structure that contains client callback data + // see callbacks documentation for more details + /// Internal structure used in manual callback dispatch + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct CallbackMsg_t { + public int m_hSteamUser; // Specific user to whom this callback applies. + public int m_iCallback; // Callback identifier. (Corresponds to the k_iCallback enum in the callback structure.) + public IntPtr m_pubParam; // Points to the callback structure + public int m_cubParam; // Size of the data pointed to by m_pubParam + } + + /// Describe the state of a connection. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamNetConnectionInfo_t { + + /// Who is on the other end? Depending on the connection type and phase of the connection, we might not know + public SteamNetworkingIdentity m_identityRemote; + + /// Arbitrary user data set by the local application code + public long m_nUserData; + + /// Handle to listen socket this was connected on, or k_HSteamListenSocket_Invalid if we initiated the connection + public HSteamListenSocket m_hListenSocket; + + /// Remote address. Might be all 0's if we don't know it, or if this is N/A. + /// (E.g. Basically everything except direct UDP connection.) + public SteamNetworkingIPAddr m_addrRemote; + public ushort m__pad1; + + /// What data center is the remote host in? (0 if we don't know.) + public SteamNetworkingPOPID m_idPOPRemote; + + /// What relay are we using to communicate with the remote host? + /// (0 if not applicable.) + public SteamNetworkingPOPID m_idPOPRelay; + + /// High level state of the connection + public ESteamNetworkingConnectionState m_eState; + + /// Basic cause of the connection termination or problem. + /// See ESteamNetConnectionEnd for the values used + public int m_eEndReason; + + /// Human-readable, but non-localized explanation for connection + /// termination or problem. This is intended for debugging / + /// diagnostic purposes only, not to display to users. It might + /// have some details specific to the issue. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchSteamNetworkingMaxConnectionCloseReason)] + private byte[] m_szEndDebug_; + public string m_szEndDebug + { + get { return InteropHelp.ByteArrayToStringUTF8(m_szEndDebug_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_szEndDebug_, Constants.k_cchSteamNetworkingMaxConnectionCloseReason); } + } + + /// Debug description. This includes the internal connection ID, + /// connection type (and peer information), and any name + /// given to the connection by the app. This string is used in various + /// internal logging messages. + /// + /// Note that the connection ID *usually* matches the HSteamNetConnection + /// handle, but in certain cases with symmetric connections it might not. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchSteamNetworkingMaxConnectionDescription)] + private byte[] m_szConnectionDescription_; + public string m_szConnectionDescription + { + get { return InteropHelp.ByteArrayToStringUTF8(m_szConnectionDescription_); } + set { InteropHelp.StringToByteArrayUTF8(value, m_szConnectionDescription_, Constants.k_cchSteamNetworkingMaxConnectionDescription); } + } + + /// Misc flags. Bitmask of k_nSteamNetworkConnectionInfoFlags_Xxxx + public int m_nFlags; + + /// Internal stuff, room to change API easily + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 63)] + public uint[] reserved; + } + + /// Quick connection state, pared down to something you could call + /// more frequently without it being too big of a perf hit. + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamNetConnectionRealTimeStatus_t { + + /// High level state of the connection + public ESteamNetworkingConnectionState m_eState; + + /// Current ping (ms) + public int m_nPing; + + /// Connection quality measured locally, 0...1. (Percentage of packets delivered + /// end-to-end in order). + public float m_flConnectionQualityLocal; + + /// Packet delivery success rate as observed from remote host + public float m_flConnectionQualityRemote; + + /// Current data rates from recent history. + public float m_flOutPacketsPerSec; + public float m_flOutBytesPerSec; + public float m_flInPacketsPerSec; + public float m_flInBytesPerSec; + + /// Estimate rate that we believe that we can send data to our peer. + /// Note that this could be significantly higher than m_flOutBytesPerSec, + /// meaning the capacity of the channel is higher than you are sending data. + /// (That's OK!) + public int m_nSendRateBytesPerSecond; + + /// Number of bytes pending to be sent. This is data that you have recently + /// requested to be sent but has not yet actually been put on the wire. The + /// reliable number ALSO includes data that was previously placed on the wire, + /// but has now been scheduled for re-transmission. Thus, it's possible to + /// observe m_cbPendingReliable increasing between two checks, even if no + /// calls were made to send reliable data between the checks. Data that is + /// awaiting the Nagle delay will appear in these numbers. + public int m_cbPendingUnreliable; + public int m_cbPendingReliable; + + /// Number of bytes of reliable data that has been placed the wire, but + /// for which we have not yet received an acknowledgment, and thus we may + /// have to re-transmit. + public int m_cbSentUnackedReliable; + + /// If you queued a message right now, approximately how long would that message + /// wait in the queue before we actually started putting its data on the wire in + /// a packet? + /// + /// In general, data that is sent by the application is limited by the bandwidth + /// of the channel. If you send data faster than this, it must be queued and + /// put on the wire at a metered rate. Even sending a small amount of data (e.g. + /// a few MTU, say ~3k) will require some of the data to be delayed a bit. + /// + /// Ignoring multiple lanes, the estimated delay will be approximately equal to + /// + /// ( m_cbPendingUnreliable+m_cbPendingReliable ) / m_nSendRateBytesPerSecond + /// + /// plus or minus one MTU. It depends on how much time has elapsed since the last + /// packet was put on the wire. For example, the queue might have *just* been emptied, + /// and the last packet placed on the wire, and we are exactly up against the send + /// rate limit. In that case we might need to wait for one packet's worth of time to + /// elapse before we can send again. On the other extreme, the queue might have data + /// in it waiting for Nagle. (This will always be less than one packet, because as + /// soon as we have a complete packet we would send it.) In that case, we might be + /// ready to send data now, and this value will be 0. + /// + /// This value is only valid if multiple lanes are not used. If multiple lanes are + /// in use, then the queue time will be different for each lane, and you must use + /// the value in SteamNetConnectionRealTimeLaneStatus_t. + /// + /// Nagle delay is ignored for the purposes of this calculation. + public SteamNetworkingMicroseconds m_usecQueueTime; + + // Internal stuff, room to change API easily + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public uint[] reserved; + } + + /// Quick status of a particular lane + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamNetConnectionRealTimeLaneStatus_t { + // Counters for this particular lane. See the corresponding variables + // in SteamNetConnectionRealTimeStatus_t + public int m_cbPendingUnreliable; + public int m_cbPendingReliable; + public int m_cbSentUnackedReliable; + public int _reservePad1; // Reserved for future use + + /// Lane-specific queue time. This value takes into consideration lane priorities + /// and weights, and how much data is queued in each lane, and attempts to predict + /// how any data currently queued will be sent out. + public SteamNetworkingMicroseconds m_usecQueueTime; + + // Internal stuff, room to change API easily + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public uint[] reserved; + } + + // + // Ping location / measurement + // + /// Object that describes a "location" on the Internet with sufficient + /// detail that we can reasonably estimate an upper bound on the ping between + /// the two hosts, even if a direct route between the hosts is not possible, + /// and the connection must be routed through the Steam Datagram Relay network. + /// This does not contain any information that identifies the host. Indeed, + /// if two hosts are in the same building or otherwise have nearly identical + /// networking characteristics, then it's valid to use the same location + /// object for both of them. + /// + /// NOTE: This object should only be used in the same process! Do not serialize it, + /// send it over the wire, or persist it in a file or database! If you need + /// to do that, convert it to a string representation using the methods in + /// ISteamNetworkingUtils(). + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamNetworkPingLocation_t { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] + public byte[] m_data; + } + +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamStructs.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamStructs.cs.meta new file mode 100644 index 0000000..67739ed --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamStructs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d968b64f163754c49be340a5b8ddd933 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapplist.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapplist.cs new file mode 100644 index 0000000..9bff5de --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapplist.cs @@ -0,0 +1,63 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamAppList { + public static uint GetNumInstalledApps() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamAppList_GetNumInstalledApps(CSteamAPIContext.GetSteamAppList()); + } + + public static uint GetInstalledApps(AppId_t[] pvecAppID, uint unMaxAppIDs) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamAppList_GetInstalledApps(CSteamAPIContext.GetSteamAppList(), pvecAppID, unMaxAppIDs); + } + + /// + /// returns -1 if no name was found + /// + public static int GetAppName(AppId_t nAppID, out string pchName, int cchNameMax) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchName2 = Marshal.AllocHGlobal(cchNameMax); + int ret = NativeMethods.ISteamAppList_GetAppName(CSteamAPIContext.GetSteamAppList(), nAppID, pchName2, cchNameMax); + pchName = ret != -1 ? InteropHelp.PtrToStringUTF8(pchName2) : null; + Marshal.FreeHGlobal(pchName2); + return ret; + } + + /// + /// returns -1 if no dir was found + /// + public static int GetAppInstallDir(AppId_t nAppID, out string pchDirectory, int cchNameMax) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchDirectory2 = Marshal.AllocHGlobal(cchNameMax); + int ret = NativeMethods.ISteamAppList_GetAppInstallDir(CSteamAPIContext.GetSteamAppList(), nAppID, pchDirectory2, cchNameMax); + pchDirectory = ret != -1 ? InteropHelp.PtrToStringUTF8(pchDirectory2) : null; + Marshal.FreeHGlobal(pchDirectory2); + return ret; + } + + /// + /// return the buildid of this app, may change at any time based on backend updates to the game + /// + public static int GetAppBuildId(AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamAppList_GetAppBuildId(CSteamAPIContext.GetSteamAppList(), nAppID); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapplist.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapplist.cs.meta new file mode 100644 index 0000000..5b5e0a1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapplist.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4c4286d1bfb0ce438e20d1cf8b3fed9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapps.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapps.cs new file mode 100644 index 0000000..9218b8a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapps.cs @@ -0,0 +1,277 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamApps { + public static bool BIsSubscribed() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsSubscribed(CSteamAPIContext.GetSteamApps()); + } + + public static bool BIsLowViolence() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsLowViolence(CSteamAPIContext.GetSteamApps()); + } + + public static bool BIsCybercafe() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsCybercafe(CSteamAPIContext.GetSteamApps()); + } + + public static bool BIsVACBanned() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsVACBanned(CSteamAPIContext.GetSteamApps()); + } + + public static string GetCurrentGameLanguage() { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetCurrentGameLanguage(CSteamAPIContext.GetSteamApps())); + } + + public static string GetAvailableGameLanguages() { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetAvailableGameLanguages(CSteamAPIContext.GetSteamApps())); + } + + /// + /// only use this member if you need to check ownership of another game related to yours, a demo for example + /// + public static bool BIsSubscribedApp(AppId_t appID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsSubscribedApp(CSteamAPIContext.GetSteamApps(), appID); + } + + /// + /// Takes AppID of DLC and checks if the user owns the DLC & if the DLC is installed + /// + public static bool BIsDlcInstalled(AppId_t appID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsDlcInstalled(CSteamAPIContext.GetSteamApps(), appID); + } + + /// + /// returns the Unix time of the purchase of the app + /// + public static uint GetEarliestPurchaseUnixTime(AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_GetEarliestPurchaseUnixTime(CSteamAPIContext.GetSteamApps(), nAppID); + } + + /// + /// Checks if the user is subscribed to the current app through a free weekend + /// This function will return false for users who have a retail or other type of license + /// Before using, please ask your Valve technical contact how to package and secure your free weekened + /// + public static bool BIsSubscribedFromFreeWeekend() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsSubscribedFromFreeWeekend(CSteamAPIContext.GetSteamApps()); + } + + /// + /// Returns the number of DLC pieces for the running app + /// + public static int GetDLCCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_GetDLCCount(CSteamAPIContext.GetSteamApps()); + } + + /// + /// Returns metadata for DLC by index, of range [0, GetDLCCount()] + /// + public static bool BGetDLCDataByIndex(int iDLC, out AppId_t pAppID, out bool pbAvailable, out string pchName, int cchNameBufferSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchName2 = Marshal.AllocHGlobal(cchNameBufferSize); + bool ret = NativeMethods.ISteamApps_BGetDLCDataByIndex(CSteamAPIContext.GetSteamApps(), iDLC, out pAppID, out pbAvailable, pchName2, cchNameBufferSize); + pchName = ret ? InteropHelp.PtrToStringUTF8(pchName2) : null; + Marshal.FreeHGlobal(pchName2); + return ret; + } + + /// + /// Install/Uninstall control for optional DLC + /// + public static void InstallDLC(AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamApps_InstallDLC(CSteamAPIContext.GetSteamApps(), nAppID); + } + + public static void UninstallDLC(AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamApps_UninstallDLC(CSteamAPIContext.GetSteamApps(), nAppID); + } + + /// + /// Request legacy cd-key for yourself or owned DLC. If you are interested in this + /// data then make sure you provide us with a list of valid keys to be distributed + /// to users when they purchase the game, before the game ships. + /// You'll receive an AppProofOfPurchaseKeyResponse_t callback when + /// the key is available (which may be immediately). + /// + public static void RequestAppProofOfPurchaseKey(AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamApps_RequestAppProofOfPurchaseKey(CSteamAPIContext.GetSteamApps(), nAppID); + } + + /// + /// returns current beta branch name, 'public' is the default branch + /// + public static bool GetCurrentBetaName(out string pchName, int cchNameBufferSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchName2 = Marshal.AllocHGlobal(cchNameBufferSize); + bool ret = NativeMethods.ISteamApps_GetCurrentBetaName(CSteamAPIContext.GetSteamApps(), pchName2, cchNameBufferSize); + pchName = ret ? InteropHelp.PtrToStringUTF8(pchName2) : null; + Marshal.FreeHGlobal(pchName2); + return ret; + } + + /// + /// signal Steam that game files seems corrupt or missing + /// + public static bool MarkContentCorrupt(bool bMissingFilesOnly) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_MarkContentCorrupt(CSteamAPIContext.GetSteamApps(), bMissingFilesOnly); + } + + /// + /// return installed depots in mount order + /// + public static uint GetInstalledDepots(AppId_t appID, DepotId_t[] pvecDepots, uint cMaxDepots) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_GetInstalledDepots(CSteamAPIContext.GetSteamApps(), appID, pvecDepots, cMaxDepots); + } + + /// + /// returns current app install folder for AppID, returns folder name length + /// + public static uint GetAppInstallDir(AppId_t appID, out string pchFolder, uint cchFolderBufferSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchFolder2 = Marshal.AllocHGlobal((int)cchFolderBufferSize); + uint ret = NativeMethods.ISteamApps_GetAppInstallDir(CSteamAPIContext.GetSteamApps(), appID, pchFolder2, cchFolderBufferSize); + pchFolder = ret != 0 ? InteropHelp.PtrToStringUTF8(pchFolder2) : null; + Marshal.FreeHGlobal(pchFolder2); + return ret; + } + + /// + /// returns true if that app is installed (not necessarily owned) + /// + public static bool BIsAppInstalled(AppId_t appID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsAppInstalled(CSteamAPIContext.GetSteamApps(), appID); + } + + /// + /// returns the SteamID of the original owner. If this CSteamID is different from ISteamUser::GetSteamID(), + /// the user has a temporary license borrowed via Family Sharing + /// + public static CSteamID GetAppOwner() { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamApps_GetAppOwner(CSteamAPIContext.GetSteamApps()); + } + + /// + /// Returns the associated launch param if the game is run via steam://run/<appid>//?param1=value1&param2=value2&param3=value3 etc. + /// Parameter names starting with the character '@' are reserved for internal use and will always return and empty string. + /// Parameter names starting with an underscore '_' are reserved for steam features -- they can be queried by the game, + /// but it is advised that you not param names beginning with an underscore for your own features. + /// Check for new launch parameters on callback NewUrlLaunchParameters_t + /// + public static string GetLaunchQueryParam(string pchKey) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamApps_GetLaunchQueryParam(CSteamAPIContext.GetSteamApps(), pchKey2)); + } + } + + /// + /// get download progress for optional DLC + /// + public static bool GetDlcDownloadProgress(AppId_t nAppID, out ulong punBytesDownloaded, out ulong punBytesTotal) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_GetDlcDownloadProgress(CSteamAPIContext.GetSteamApps(), nAppID, out punBytesDownloaded, out punBytesTotal); + } + + /// + /// return the buildid of this app, may change at any time based on backend updates to the game + /// + public static int GetAppBuildId() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_GetAppBuildId(CSteamAPIContext.GetSteamApps()); + } + + /// + /// Request all proof of purchase keys for the calling appid and asociated DLC. + /// A series of AppProofOfPurchaseKeyResponse_t callbacks will be sent with + /// appropriate appid values, ending with a final callback where the m_nAppId + /// member is k_uAppIdInvalid (zero). + /// + public static void RequestAllProofOfPurchaseKeys() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamApps_RequestAllProofOfPurchaseKeys(CSteamAPIContext.GetSteamApps()); + } + + public static SteamAPICall_t GetFileDetails(string pszFileName) { + InteropHelp.TestIfAvailableClient(); + using (var pszFileName2 = new InteropHelp.UTF8StringHandle(pszFileName)) { + return (SteamAPICall_t)NativeMethods.ISteamApps_GetFileDetails(CSteamAPIContext.GetSteamApps(), pszFileName2); + } + } + + /// + /// Get command line if game was launched via Steam URL, e.g. steam://run/<appid>//<command line>/. + /// This method of passing a connect string (used when joining via rich presence, accepting an + /// invite, etc) is preferable to passing the connect string on the operating system command + /// line, which is a security risk. In order for rich presence joins to go through this + /// path and not be placed on the OS command line, you must set a value in your app's + /// configuration on Steam. Ask Valve for help with this. + /// If game was already running and launched again, the NewUrlLaunchParameters_t will be fired. + /// + public static int GetLaunchCommandLine(out string pszCommandLine, int cubCommandLine) { + InteropHelp.TestIfAvailableClient(); + IntPtr pszCommandLine2 = Marshal.AllocHGlobal(cubCommandLine); + int ret = NativeMethods.ISteamApps_GetLaunchCommandLine(CSteamAPIContext.GetSteamApps(), pszCommandLine2, cubCommandLine); + pszCommandLine = ret != -1 ? InteropHelp.PtrToStringUTF8(pszCommandLine2) : null; + Marshal.FreeHGlobal(pszCommandLine2); + return ret; + } + + /// + /// Check if user borrowed this game via Family Sharing, If true, call GetAppOwner() to get the lender SteamID + /// + public static bool BIsSubscribedFromFamilySharing() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsSubscribedFromFamilySharing(CSteamAPIContext.GetSteamApps()); + } + + /// + /// check if game is a timed trial with limited playtime + /// + public static bool BIsTimedTrial(out uint punSecondsAllowed, out uint punSecondsPlayed) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_BIsTimedTrial(CSteamAPIContext.GetSteamApps(), out punSecondsAllowed, out punSecondsPlayed); + } + + /// + /// set current DLC AppID being played (or 0 if none). Allows Steam to track usage of major DLC extensions + /// + public static bool SetDlcContext(AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamApps_SetDlcContext(CSteamAPIContext.GetSteamApps(), nAppID); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapps.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapps.cs.meta new file mode 100644 index 0000000..3c619c1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapps.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc5c59b2b2e521b42a6c112e0497310a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamclient.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamclient.cs new file mode 100644 index 0000000..c0eddac --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamclient.cs @@ -0,0 +1,376 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamClient { + /// + /// Creates a communication pipe to the Steam client. + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static HSteamPipe CreateSteamPipe() { + InteropHelp.TestIfAvailableClient(); + return (HSteamPipe)NativeMethods.ISteamClient_CreateSteamPipe(CSteamAPIContext.GetSteamClient()); + } + + /// + /// Releases a previously created communications pipe + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static bool BReleaseSteamPipe(HSteamPipe hSteamPipe) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamClient_BReleaseSteamPipe(CSteamAPIContext.GetSteamClient(), hSteamPipe); + } + + /// + /// connects to an existing global user, failing if none exists + /// used by the game to coordinate with the steamUI + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static HSteamUser ConnectToGlobalUser(HSteamPipe hSteamPipe) { + InteropHelp.TestIfAvailableClient(); + return (HSteamUser)NativeMethods.ISteamClient_ConnectToGlobalUser(CSteamAPIContext.GetSteamClient(), hSteamPipe); + } + + /// + /// used by game servers, create a steam user that won't be shared with anyone else + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static HSteamUser CreateLocalUser(out HSteamPipe phSteamPipe, EAccountType eAccountType) { + InteropHelp.TestIfAvailableClient(); + return (HSteamUser)NativeMethods.ISteamClient_CreateLocalUser(CSteamAPIContext.GetSteamClient(), out phSteamPipe, eAccountType); + } + + /// + /// removes an allocated user + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static void ReleaseUser(HSteamPipe hSteamPipe, HSteamUser hUser) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamClient_ReleaseUser(CSteamAPIContext.GetSteamClient(), hSteamPipe, hUser); + } + + /// + /// retrieves the ISteamUser interface associated with the handle + /// + public static IntPtr GetISteamUser(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamUser(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// retrieves the ISteamGameServer interface associated with the handle + /// + public static IntPtr GetISteamGameServer(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamGameServer(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// set the local IP and Port to bind to + /// this must be set before CreateLocalUser() + /// + public static void SetLocalIPBinding(ref SteamIPAddress_t unIP, ushort usPort) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamClient_SetLocalIPBinding(CSteamAPIContext.GetSteamClient(), ref unIP, usPort); + } + + /// + /// returns the ISteamFriends interface + /// + public static IntPtr GetISteamFriends(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamFriends(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamUtils interface + /// + public static IntPtr GetISteamUtils(HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamUtils(CSteamAPIContext.GetSteamClient(), hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamMatchmaking interface + /// + public static IntPtr GetISteamMatchmaking(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamMatchmaking(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamMatchmakingServers interface + /// + public static IntPtr GetISteamMatchmakingServers(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamMatchmakingServers(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the a generic interface + /// + public static IntPtr GetISteamGenericInterface(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamGenericInterface(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamUserStats interface + /// + public static IntPtr GetISteamUserStats(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamUserStats(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamGameServerStats interface + /// + public static IntPtr GetISteamGameServerStats(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamGameServerStats(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns apps interface + /// + public static IntPtr GetISteamApps(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamApps(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// networking + /// + public static IntPtr GetISteamNetworking(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamNetworking(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// remote storage + /// + public static IntPtr GetISteamRemoteStorage(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamRemoteStorage(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// user screenshots + /// + public static IntPtr GetISteamScreenshots(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamScreenshots(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// game search + /// + public static IntPtr GetISteamGameSearch(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamGameSearch(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the number of IPC calls made since the last time this function was called + /// Used for perf debugging so you can understand how many IPC calls your game makes per frame + /// Every IPC call is at minimum a thread context switch if not a process one so you want to rate + /// control how often you do them. + /// + public static uint GetIPCCallCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamClient_GetIPCCallCount(CSteamAPIContext.GetSteamClient()); + } + + /// + /// API warning handling + /// 'int' is the severity; 0 for msg, 1 for warning + /// 'const char *' is the text of the message + /// callbacks will occur directly after the API function is called that generated the warning or message. + /// + public static void SetWarningMessageHook(SteamAPIWarningMessageHook_t pFunction) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamClient_SetWarningMessageHook(CSteamAPIContext.GetSteamClient(), pFunction); + } + + /// + /// Trigger global shutdown for the DLL + /// + public static bool BShutdownIfAllPipesClosed() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamClient_BShutdownIfAllPipesClosed(CSteamAPIContext.GetSteamClient()); + } + + /// + /// Expose HTTP interface + /// + public static IntPtr GetISteamHTTP(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamHTTP(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Exposes the ISteamController interface - deprecated in favor of Steam Input + /// + public static IntPtr GetISteamController(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamController(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// Exposes the ISteamUGC interface + /// + public static IntPtr GetISteamUGC(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamUGC(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns app list interface, only available on specially registered apps + /// + public static IntPtr GetISteamAppList(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamAppList(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// Music Player + /// + public static IntPtr GetISteamMusic(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamMusic(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Music Player Remote + /// + public static IntPtr GetISteamMusicRemote(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamMusicRemote(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// html page display + /// + public static IntPtr GetISteamHTMLSurface(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamHTMLSurface(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// inventory + /// + public static IntPtr GetISteamInventory(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamInventory(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Video + /// + public static IntPtr GetISteamVideo(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamVideo(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Parental controls + /// + public static IntPtr GetISteamParentalSettings(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamParentalSettings(CSteamAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Exposes the Steam Input interface for controller support + /// + public static IntPtr GetISteamInput(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamInput(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// Steam Parties interface + /// + public static IntPtr GetISteamParties(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamParties(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// Steam Remote Play interface + /// + public static IntPtr GetISteamRemotePlay(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableClient(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamRemotePlay(CSteamAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamclient.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamclient.cs.meta new file mode 100644 index 0000000..95aeea2 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamclient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 28457456f70c3ef4ca6c7b08a9c796bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamfriends.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamfriends.cs new file mode 100644 index 0000000..025a6ec --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamfriends.cs @@ -0,0 +1,688 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamFriends { + /// + /// returns the local players name - guaranteed to not be NULL. + /// this is the same name as on the users community profile page + /// this is stored in UTF-8 format + /// like all the other interface functions that return a char *, it's important that this pointer is not saved + /// off; it will eventually be free'd or re-allocated + /// + public static string GetPersonaName() { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetPersonaName(CSteamAPIContext.GetSteamFriends())); + } + + /// + /// Sets the player name, stores it on the server and publishes the changes to all friends who are online. + /// Changes take place locally immediately, and a PersonaStateChange_t is posted, presuming success. + /// The final results are available through the return value SteamAPICall_t, using SetPersonaNameResponse_t. + /// If the name change fails to happen on the server, then an additional global PersonaStateChange_t will be posted + /// to change the name back, in addition to the SetPersonaNameResponse_t callback. + /// + public static SteamAPICall_t SetPersonaName(string pchPersonaName) { + InteropHelp.TestIfAvailableClient(); + using (var pchPersonaName2 = new InteropHelp.UTF8StringHandle(pchPersonaName)) { + return (SteamAPICall_t)NativeMethods.ISteamFriends_SetPersonaName(CSteamAPIContext.GetSteamFriends(), pchPersonaName2); + } + } + + /// + /// gets the status of the current user + /// + public static EPersonaState GetPersonaState() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetPersonaState(CSteamAPIContext.GetSteamFriends()); + } + + /// + /// friend iteration + /// takes a set of k_EFriendFlags, and returns the number of users the client knows about who meet that criteria + /// then GetFriendByIndex() can then be used to return the id's of each of those users + /// + public static int GetFriendCount(EFriendFlags iFriendFlags) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendCount(CSteamAPIContext.GetSteamFriends(), iFriendFlags); + } + + /// + /// returns the steamID of a user + /// iFriend is a index of range [0, GetFriendCount()) + /// iFriendsFlags must be the same value as used in GetFriendCount() + /// the returned CSteamID can then be used by all the functions below to access details about the user + /// + public static CSteamID GetFriendByIndex(int iFriend, EFriendFlags iFriendFlags) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamFriends_GetFriendByIndex(CSteamAPIContext.GetSteamFriends(), iFriend, iFriendFlags); + } + + /// + /// returns a relationship to a user + /// + public static EFriendRelationship GetFriendRelationship(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendRelationship(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + /// + /// returns the current status of the specified user + /// this will only be known by the local user if steamIDFriend is in their friends list; on the same game server; in a chat room or lobby; or in a small group with the local user + /// + public static EPersonaState GetFriendPersonaState(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendPersonaState(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + /// + /// returns the name another user - guaranteed to not be NULL. + /// same rules as GetFriendPersonaState() apply as to whether or not the user knowns the name of the other user + /// note that on first joining a lobby, chat room or game server the local user will not known the name of the other users automatically; that information will arrive asyncronously + /// + public static string GetFriendPersonaName(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendPersonaName(CSteamAPIContext.GetSteamFriends(), steamIDFriend)); + } + + /// + /// returns true if the friend is actually in a game, and fills in pFriendGameInfo with an extra details + /// + public static bool GetFriendGamePlayed(CSteamID steamIDFriend, out FriendGameInfo_t pFriendGameInfo) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendGamePlayed(CSteamAPIContext.GetSteamFriends(), steamIDFriend, out pFriendGameInfo); + } + + /// + /// accesses old friends names - returns an empty string when their are no more items in the history + /// + public static string GetFriendPersonaNameHistory(CSteamID steamIDFriend, int iPersonaName) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendPersonaNameHistory(CSteamAPIContext.GetSteamFriends(), steamIDFriend, iPersonaName)); + } + + /// + /// friends steam level + /// + public static int GetFriendSteamLevel(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendSteamLevel(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + /// + /// Returns nickname the current user has set for the specified player. Returns NULL if the no nickname has been set for that player. + /// DEPRECATED: GetPersonaName follows the Steam nickname preferences, so apps shouldn't need to care about nicknames explicitly. + /// + public static string GetPlayerNickname(CSteamID steamIDPlayer) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetPlayerNickname(CSteamAPIContext.GetSteamFriends(), steamIDPlayer)); + } + + /// + /// friend grouping (tag) apis + /// returns the number of friends groups + /// + public static int GetFriendsGroupCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendsGroupCount(CSteamAPIContext.GetSteamFriends()); + } + + /// + /// returns the friends group ID for the given index (invalid indices return k_FriendsGroupID_Invalid) + /// + public static FriendsGroupID_t GetFriendsGroupIDByIndex(int iFG) { + InteropHelp.TestIfAvailableClient(); + return (FriendsGroupID_t)NativeMethods.ISteamFriends_GetFriendsGroupIDByIndex(CSteamAPIContext.GetSteamFriends(), iFG); + } + + /// + /// returns the name for the given friends group (NULL in the case of invalid friends group IDs) + /// + public static string GetFriendsGroupName(FriendsGroupID_t friendsGroupID) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendsGroupName(CSteamAPIContext.GetSteamFriends(), friendsGroupID)); + } + + /// + /// returns the number of members in a given friends group + /// + public static int GetFriendsGroupMembersCount(FriendsGroupID_t friendsGroupID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendsGroupMembersCount(CSteamAPIContext.GetSteamFriends(), friendsGroupID); + } + + /// + /// gets up to nMembersCount members of the given friends group, if fewer exist than requested those positions' SteamIDs will be invalid + /// + public static void GetFriendsGroupMembersList(FriendsGroupID_t friendsGroupID, CSteamID[] pOutSteamIDMembers, int nMembersCount) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamFriends_GetFriendsGroupMembersList(CSteamAPIContext.GetSteamFriends(), friendsGroupID, pOutSteamIDMembers, nMembersCount); + } + + /// + /// returns true if the specified user meets any of the criteria specified in iFriendFlags + /// iFriendFlags can be the union (binary or, |) of one or more k_EFriendFlags values + /// + public static bool HasFriend(CSteamID steamIDFriend, EFriendFlags iFriendFlags) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_HasFriend(CSteamAPIContext.GetSteamFriends(), steamIDFriend, iFriendFlags); + } + + /// + /// clan (group) iteration and access functions + /// + public static int GetClanCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetClanCount(CSteamAPIContext.GetSteamFriends()); + } + + public static CSteamID GetClanByIndex(int iClan) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamFriends_GetClanByIndex(CSteamAPIContext.GetSteamFriends(), iClan); + } + + public static string GetClanName(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetClanName(CSteamAPIContext.GetSteamFriends(), steamIDClan)); + } + + public static string GetClanTag(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetClanTag(CSteamAPIContext.GetSteamFriends(), steamIDClan)); + } + + /// + /// returns the most recent information we have about what's happening in a clan + /// + public static bool GetClanActivityCounts(CSteamID steamIDClan, out int pnOnline, out int pnInGame, out int pnChatting) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetClanActivityCounts(CSteamAPIContext.GetSteamFriends(), steamIDClan, out pnOnline, out pnInGame, out pnChatting); + } + + /// + /// for clans a user is a member of, they will have reasonably up-to-date information, but for others you'll have to download the info to have the latest + /// + public static SteamAPICall_t DownloadClanActivityCounts(CSteamID[] psteamIDClans, int cClansToRequest) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamFriends_DownloadClanActivityCounts(CSteamAPIContext.GetSteamFriends(), psteamIDClans, cClansToRequest); + } + + /// + /// iterators for getting users in a chat room, lobby, game server or clan + /// note that large clans that cannot be iterated by the local user + /// note that the current user must be in a lobby to retrieve CSteamIDs of other users in that lobby + /// steamIDSource can be the steamID of a group, game server, lobby or chat room + /// + public static int GetFriendCountFromSource(CSteamID steamIDSource) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendCountFromSource(CSteamAPIContext.GetSteamFriends(), steamIDSource); + } + + public static CSteamID GetFriendFromSourceByIndex(CSteamID steamIDSource, int iFriend) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamFriends_GetFriendFromSourceByIndex(CSteamAPIContext.GetSteamFriends(), steamIDSource, iFriend); + } + + /// + /// returns true if the local user can see that steamIDUser is a member or in steamIDSource + /// + public static bool IsUserInSource(CSteamID steamIDUser, CSteamID steamIDSource) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_IsUserInSource(CSteamAPIContext.GetSteamFriends(), steamIDUser, steamIDSource); + } + + /// + /// User is in a game pressing the talk button (will suppress the microphone for all voice comms from the Steam friends UI) + /// + public static void SetInGameVoiceSpeaking(CSteamID steamIDUser, bool bSpeaking) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamFriends_SetInGameVoiceSpeaking(CSteamAPIContext.GetSteamFriends(), steamIDUser, bSpeaking); + } + + /// + /// activates the game overlay, with an optional dialog to open + /// valid options include "Friends", "Community", "Players", "Settings", "OfficialGameGroup", "Stats", "Achievements", + /// "chatroomgroup/nnnn" + /// + public static void ActivateGameOverlay(string pchDialog) { + InteropHelp.TestIfAvailableClient(); + using (var pchDialog2 = new InteropHelp.UTF8StringHandle(pchDialog)) { + NativeMethods.ISteamFriends_ActivateGameOverlay(CSteamAPIContext.GetSteamFriends(), pchDialog2); + } + } + + /// + /// activates game overlay to a specific place + /// valid options are + /// "steamid" - opens the overlay web browser to the specified user or groups profile + /// "chat" - opens a chat window to the specified user, or joins the group chat + /// "jointrade" - opens a window to a Steam Trading session that was started with the ISteamEconomy/StartTrade Web API + /// "stats" - opens the overlay web browser to the specified user's stats + /// "achievements" - opens the overlay web browser to the specified user's achievements + /// "friendadd" - opens the overlay in minimal mode prompting the user to add the target user as a friend + /// "friendremove" - opens the overlay in minimal mode prompting the user to remove the target friend + /// "friendrequestaccept" - opens the overlay in minimal mode prompting the user to accept an incoming friend invite + /// "friendrequestignore" - opens the overlay in minimal mode prompting the user to ignore an incoming friend invite + /// + public static void ActivateGameOverlayToUser(string pchDialog, CSteamID steamID) { + InteropHelp.TestIfAvailableClient(); + using (var pchDialog2 = new InteropHelp.UTF8StringHandle(pchDialog)) { + NativeMethods.ISteamFriends_ActivateGameOverlayToUser(CSteamAPIContext.GetSteamFriends(), pchDialog2, steamID); + } + } + + /// + /// activates game overlay web browser directly to the specified URL + /// full address with protocol type is required, e.g. http://www.steamgames.com/ + /// + public static void ActivateGameOverlayToWebPage(string pchURL, EActivateGameOverlayToWebPageMode eMode = EActivateGameOverlayToWebPageMode.k_EActivateGameOverlayToWebPageMode_Default) { + InteropHelp.TestIfAvailableClient(); + using (var pchURL2 = new InteropHelp.UTF8StringHandle(pchURL)) { + NativeMethods.ISteamFriends_ActivateGameOverlayToWebPage(CSteamAPIContext.GetSteamFriends(), pchURL2, eMode); + } + } + + /// + /// activates game overlay to store page for app + /// + public static void ActivateGameOverlayToStore(AppId_t nAppID, EOverlayToStoreFlag eFlag) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamFriends_ActivateGameOverlayToStore(CSteamAPIContext.GetSteamFriends(), nAppID, eFlag); + } + + /// + /// Mark a target user as 'played with'. This is a client-side only feature that requires that the calling user is + /// in game + /// + public static void SetPlayedWith(CSteamID steamIDUserPlayedWith) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamFriends_SetPlayedWith(CSteamAPIContext.GetSteamFriends(), steamIDUserPlayedWith); + } + + /// + /// activates game overlay to open the invite dialog. Invitations will be sent for the provided lobby. + /// + public static void ActivateGameOverlayInviteDialog(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamFriends_ActivateGameOverlayInviteDialog(CSteamAPIContext.GetSteamFriends(), steamIDLobby); + } + + /// + /// gets the small (32x32) avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set + /// + public static int GetSmallFriendAvatar(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetSmallFriendAvatar(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + /// + /// gets the medium (64x64) avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set + /// + public static int GetMediumFriendAvatar(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetMediumFriendAvatar(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + /// + /// gets the large (184x184) avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set + /// returns -1 if this image has yet to be loaded, in this case wait for a AvatarImageLoaded_t callback and then call this again + /// + public static int GetLargeFriendAvatar(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetLargeFriendAvatar(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + /// + /// requests information about a user - persona name & avatar + /// if bRequireNameOnly is set, then the avatar of a user isn't downloaded + /// - it's a lot slower to download avatars and churns the local cache, so if you don't need avatars, don't request them + /// if returns true, it means that data is being requested, and a PersonaStateChanged_t callback will be posted when it's retrieved + /// if returns false, it means that we already have all the details about that user, and functions can be called immediately + /// + public static bool RequestUserInformation(CSteamID steamIDUser, bool bRequireNameOnly) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_RequestUserInformation(CSteamAPIContext.GetSteamFriends(), steamIDUser, bRequireNameOnly); + } + + /// + /// requests information about a clan officer list + /// when complete, data is returned in ClanOfficerListResponse_t call result + /// this makes available the calls below + /// you can only ask about clans that a user is a member of + /// note that this won't download avatars automatically; if you get an officer, + /// and no avatar image is available, call RequestUserInformation( steamID, false ) to download the avatar + /// + public static SteamAPICall_t RequestClanOfficerList(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamFriends_RequestClanOfficerList(CSteamAPIContext.GetSteamFriends(), steamIDClan); + } + + /// + /// iteration of clan officers - can only be done when a RequestClanOfficerList() call has completed + /// returns the steamID of the clan owner + /// + public static CSteamID GetClanOwner(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamFriends_GetClanOwner(CSteamAPIContext.GetSteamFriends(), steamIDClan); + } + + /// + /// returns the number of officers in a clan (including the owner) + /// + public static int GetClanOfficerCount(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetClanOfficerCount(CSteamAPIContext.GetSteamFriends(), steamIDClan); + } + + /// + /// returns the steamID of a clan officer, by index, of range [0,GetClanOfficerCount) + /// + public static CSteamID GetClanOfficerByIndex(CSteamID steamIDClan, int iOfficer) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamFriends_GetClanOfficerByIndex(CSteamAPIContext.GetSteamFriends(), steamIDClan, iOfficer); + } + + /// + /// if current user is chat restricted, he can't send or receive any text/voice chat messages. + /// the user can't see custom avatars. But the user can be online and send/recv game invites. + /// a chat restricted user can't add friends or join any groups. + /// + public static uint GetUserRestrictions() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetUserRestrictions(CSteamAPIContext.GetSteamFriends()); + } + + /// + /// Rich Presence data is automatically shared between friends who are in the same game + /// Each user has a set of Key/Value pairs + /// Note the following limits: k_cchMaxRichPresenceKeys, k_cchMaxRichPresenceKeyLength, k_cchMaxRichPresenceValueLength + /// There are five magic keys: + /// "status" - a UTF-8 string that will show up in the 'view game info' dialog in the Steam friends list + /// "connect" - a UTF-8 string that contains the command-line for how a friend can connect to a game + /// "steam_display" - Names a rich presence localization token that will be displayed in the viewing user's selected language + /// in the Steam client UI. For more info: https://partner.steamgames.com/doc/api/ISteamFriends#richpresencelocalization + /// "steam_player_group" - When set, indicates to the Steam client that the player is a member of a particular group. Players in the same group + /// may be organized together in various places in the Steam UI. + /// "steam_player_group_size" - When set, indicates the total number of players in the steam_player_group. The Steam client may use this number to + /// display additional information about a group when all of the members are not part of a user's friends list. + /// GetFriendRichPresence() returns an empty string "" if no value is set + /// SetRichPresence() to a NULL or an empty string deletes the key + /// You can iterate the current set of keys for a friend with GetFriendRichPresenceKeyCount() + /// and GetFriendRichPresenceKeyByIndex() (typically only used for debugging) + /// + public static bool SetRichPresence(string pchKey, string pchValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) + using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) { + return NativeMethods.ISteamFriends_SetRichPresence(CSteamAPIContext.GetSteamFriends(), pchKey2, pchValue2); + } + } + + public static void ClearRichPresence() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamFriends_ClearRichPresence(CSteamAPIContext.GetSteamFriends()); + } + + public static string GetFriendRichPresence(CSteamID steamIDFriend, string pchKey) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendRichPresence(CSteamAPIContext.GetSteamFriends(), steamIDFriend, pchKey2)); + } + } + + public static int GetFriendRichPresenceKeyCount(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendRichPresenceKeyCount(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + public static string GetFriendRichPresenceKeyByIndex(CSteamID steamIDFriend, int iKey) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetFriendRichPresenceKeyByIndex(CSteamAPIContext.GetSteamFriends(), steamIDFriend, iKey)); + } + + /// + /// Requests rich presence for a specific user. + /// + public static void RequestFriendRichPresence(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamFriends_RequestFriendRichPresence(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + /// + /// Rich invite support. + /// If the target accepts the invite, a GameRichPresenceJoinRequested_t callback is posted containing the connect string. + /// (Or you can configure your game so that it is passed on the command line instead. This is a deprecated path; ask us if you really need this.) + /// + public static bool InviteUserToGame(CSteamID steamIDFriend, string pchConnectString) { + InteropHelp.TestIfAvailableClient(); + using (var pchConnectString2 = new InteropHelp.UTF8StringHandle(pchConnectString)) { + return NativeMethods.ISteamFriends_InviteUserToGame(CSteamAPIContext.GetSteamFriends(), steamIDFriend, pchConnectString2); + } + } + + /// + /// recently-played-with friends iteration + /// this iterates the entire list of users recently played with, across games + /// GetFriendCoplayTime() returns as a unix time + /// + public static int GetCoplayFriendCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetCoplayFriendCount(CSteamAPIContext.GetSteamFriends()); + } + + public static CSteamID GetCoplayFriend(int iCoplayFriend) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamFriends_GetCoplayFriend(CSteamAPIContext.GetSteamFriends(), iCoplayFriend); + } + + public static int GetFriendCoplayTime(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetFriendCoplayTime(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + public static AppId_t GetFriendCoplayGame(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return (AppId_t)NativeMethods.ISteamFriends_GetFriendCoplayGame(CSteamAPIContext.GetSteamFriends(), steamIDFriend); + } + + /// + /// chat interface for games + /// this allows in-game access to group (clan) chats from in the game + /// the behavior is somewhat sophisticated, because the user may or may not be already in the group chat from outside the game or in the overlay + /// use ActivateGameOverlayToUser( "chat", steamIDClan ) to open the in-game overlay version of the chat + /// + public static SteamAPICall_t JoinClanChatRoom(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamFriends_JoinClanChatRoom(CSteamAPIContext.GetSteamFriends(), steamIDClan); + } + + public static bool LeaveClanChatRoom(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_LeaveClanChatRoom(CSteamAPIContext.GetSteamFriends(), steamIDClan); + } + + public static int GetClanChatMemberCount(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetClanChatMemberCount(CSteamAPIContext.GetSteamFriends(), steamIDClan); + } + + public static CSteamID GetChatMemberByIndex(CSteamID steamIDClan, int iUser) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamFriends_GetChatMemberByIndex(CSteamAPIContext.GetSteamFriends(), steamIDClan, iUser); + } + + public static bool SendClanChatMessage(CSteamID steamIDClanChat, string pchText) { + InteropHelp.TestIfAvailableClient(); + using (var pchText2 = new InteropHelp.UTF8StringHandle(pchText)) { + return NativeMethods.ISteamFriends_SendClanChatMessage(CSteamAPIContext.GetSteamFriends(), steamIDClanChat, pchText2); + } + } + + public static int GetClanChatMessage(CSteamID steamIDClanChat, int iMessage, out string prgchText, int cchTextMax, out EChatEntryType peChatEntryType, out CSteamID psteamidChatter) { + InteropHelp.TestIfAvailableClient(); + IntPtr prgchText2 = Marshal.AllocHGlobal(cchTextMax); + int ret = NativeMethods.ISteamFriends_GetClanChatMessage(CSteamAPIContext.GetSteamFriends(), steamIDClanChat, iMessage, prgchText2, cchTextMax, out peChatEntryType, out psteamidChatter); + prgchText = ret != 0 ? InteropHelp.PtrToStringUTF8(prgchText2) : null; + Marshal.FreeHGlobal(prgchText2); + return ret; + } + + public static bool IsClanChatAdmin(CSteamID steamIDClanChat, CSteamID steamIDUser) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_IsClanChatAdmin(CSteamAPIContext.GetSteamFriends(), steamIDClanChat, steamIDUser); + } + + /// + /// interact with the Steam (game overlay / desktop) + /// + public static bool IsClanChatWindowOpenInSteam(CSteamID steamIDClanChat) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_IsClanChatWindowOpenInSteam(CSteamAPIContext.GetSteamFriends(), steamIDClanChat); + } + + public static bool OpenClanChatWindowInSteam(CSteamID steamIDClanChat) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_OpenClanChatWindowInSteam(CSteamAPIContext.GetSteamFriends(), steamIDClanChat); + } + + public static bool CloseClanChatWindowInSteam(CSteamID steamIDClanChat) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_CloseClanChatWindowInSteam(CSteamAPIContext.GetSteamFriends(), steamIDClanChat); + } + + /// + /// peer-to-peer chat interception + /// this is so you can show P2P chats inline in the game + /// + public static bool SetListenForFriendsMessages(bool bInterceptEnabled) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_SetListenForFriendsMessages(CSteamAPIContext.GetSteamFriends(), bInterceptEnabled); + } + + public static bool ReplyToFriendMessage(CSteamID steamIDFriend, string pchMsgToSend) { + InteropHelp.TestIfAvailableClient(); + using (var pchMsgToSend2 = new InteropHelp.UTF8StringHandle(pchMsgToSend)) { + return NativeMethods.ISteamFriends_ReplyToFriendMessage(CSteamAPIContext.GetSteamFriends(), steamIDFriend, pchMsgToSend2); + } + } + + public static int GetFriendMessage(CSteamID steamIDFriend, int iMessageID, out string pvData, int cubData, out EChatEntryType peChatEntryType) { + InteropHelp.TestIfAvailableClient(); + IntPtr pvData2 = Marshal.AllocHGlobal(cubData); + int ret = NativeMethods.ISteamFriends_GetFriendMessage(CSteamAPIContext.GetSteamFriends(), steamIDFriend, iMessageID, pvData2, cubData, out peChatEntryType); + pvData = ret != 0 ? InteropHelp.PtrToStringUTF8(pvData2) : null; + Marshal.FreeHGlobal(pvData2); + return ret; + } + + /// + /// following apis + /// + public static SteamAPICall_t GetFollowerCount(CSteamID steamID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamFriends_GetFollowerCount(CSteamAPIContext.GetSteamFriends(), steamID); + } + + public static SteamAPICall_t IsFollowing(CSteamID steamID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamFriends_IsFollowing(CSteamAPIContext.GetSteamFriends(), steamID); + } + + public static SteamAPICall_t EnumerateFollowingList(uint unStartIndex) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamFriends_EnumerateFollowingList(CSteamAPIContext.GetSteamFriends(), unStartIndex); + } + + public static bool IsClanPublic(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_IsClanPublic(CSteamAPIContext.GetSteamFriends(), steamIDClan); + } + + public static bool IsClanOfficialGameGroup(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_IsClanOfficialGameGroup(CSteamAPIContext.GetSteamFriends(), steamIDClan); + } + + /// + /// / Return the number of chats (friends or chat rooms) with unread messages. + /// / A "priority" message is one that would generate some sort of toast or + /// / notification, and depends on user settings. + /// / + /// / You can register for UnreadChatMessagesChanged_t callbacks to know when this + /// / has potentially changed. + /// + public static int GetNumChatsWithUnreadPriorityMessages() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetNumChatsWithUnreadPriorityMessages(CSteamAPIContext.GetSteamFriends()); + } + + /// + /// activates game overlay to open the remote play together invite dialog. Invitations will be sent for remote play together + /// + public static void ActivateGameOverlayRemotePlayTogetherInviteDialog(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamFriends_ActivateGameOverlayRemotePlayTogetherInviteDialog(CSteamAPIContext.GetSteamFriends(), steamIDLobby); + } + + /// + /// Call this before calling ActivateGameOverlayToWebPage() to have the Steam Overlay Browser block navigations + /// to your specified protocol (scheme) uris and instead dispatch a OverlayBrowserProtocolNavigation_t callback to your game. + /// ActivateGameOverlayToWebPage() must have been called with k_EActivateGameOverlayToWebPageMode_Modal + /// + public static bool RegisterProtocolInOverlayBrowser(string pchProtocol) { + InteropHelp.TestIfAvailableClient(); + using (var pchProtocol2 = new InteropHelp.UTF8StringHandle(pchProtocol)) { + return NativeMethods.ISteamFriends_RegisterProtocolInOverlayBrowser(CSteamAPIContext.GetSteamFriends(), pchProtocol2); + } + } + + /// + /// Activates the game overlay to open an invite dialog that will send the provided Rich Presence connect string to selected friends + /// + public static void ActivateGameOverlayInviteDialogConnectString(string pchConnectString) { + InteropHelp.TestIfAvailableClient(); + using (var pchConnectString2 = new InteropHelp.UTF8StringHandle(pchConnectString)) { + NativeMethods.ISteamFriends_ActivateGameOverlayInviteDialogConnectString(CSteamAPIContext.GetSteamFriends(), pchConnectString2); + } + } + + /// + /// Steam Community items equipped by a user on their profile + /// You can register for EquippedProfileItemsChanged_t to know when a friend has changed their equipped profile items + /// + public static SteamAPICall_t RequestEquippedProfileItems(CSteamID steamID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamFriends_RequestEquippedProfileItems(CSteamAPIContext.GetSteamFriends(), steamID); + } + + public static bool BHasEquippedProfileItem(CSteamID steamID, ECommunityProfileItemType itemType) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_BHasEquippedProfileItem(CSteamAPIContext.GetSteamFriends(), steamID, itemType); + } + + public static string GetProfileItemPropertyString(CSteamID steamID, ECommunityProfileItemType itemType, ECommunityProfileItemProperty prop) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamFriends_GetProfileItemPropertyString(CSteamAPIContext.GetSteamFriends(), steamID, itemType, prop)); + } + + public static uint GetProfileItemPropertyUint(CSteamID steamID, ECommunityProfileItemType itemType, ECommunityProfileItemProperty prop) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamFriends_GetProfileItemPropertyUint(CSteamAPIContext.GetSteamFriends(), steamID, itemType, prop); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamfriends.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamfriends.cs.meta new file mode 100644 index 0000000..ec16dfe --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamfriends.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ff71573e5261b1e45a0db0451c6d7af4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserver.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserver.cs new file mode 100644 index 0000000..2a6692b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserver.cs @@ -0,0 +1,450 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServer { + /// + /// / Game product identifier. This is currently used by the master server for version checking purposes. + /// / It's a required field, but will eventually will go away, and the AppID will be used for this purpose. + /// + public static void SetProduct(string pszProduct) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszProduct2 = new InteropHelp.UTF8StringHandle(pszProduct)) { + NativeMethods.ISteamGameServer_SetProduct(CSteamGameServerAPIContext.GetSteamGameServer(), pszProduct2); + } + } + + /// + /// / Description of the game. This is a required field and is displayed in the steam server browser....for now. + /// / This is a required field, but it will go away eventually, as the data should be determined from the AppID. + /// + public static void SetGameDescription(string pszGameDescription) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszGameDescription2 = new InteropHelp.UTF8StringHandle(pszGameDescription)) { + NativeMethods.ISteamGameServer_SetGameDescription(CSteamGameServerAPIContext.GetSteamGameServer(), pszGameDescription2); + } + } + + /// + /// / If your game is a "mod," pass the string that identifies it. The default is an empty string, meaning + /// / this application is the original game, not a mod. + /// / + /// / @see k_cbMaxGameServerGameDir + /// + public static void SetModDir(string pszModDir) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszModDir2 = new InteropHelp.UTF8StringHandle(pszModDir)) { + NativeMethods.ISteamGameServer_SetModDir(CSteamGameServerAPIContext.GetSteamGameServer(), pszModDir2); + } + } + + /// + /// / Is this is a dedicated server? The default value is false. + /// + public static void SetDedicatedServer(bool bDedicated) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_SetDedicatedServer(CSteamGameServerAPIContext.GetSteamGameServer(), bDedicated); + } + + /// + /// Login + /// / Begin process to login to a persistent game server account + /// / + /// / You need to register for callbacks to determine the result of this operation. + /// / @see SteamServersConnected_t + /// / @see SteamServerConnectFailure_t + /// / @see SteamServersDisconnected_t + /// + public static void LogOn(string pszToken) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszToken2 = new InteropHelp.UTF8StringHandle(pszToken)) { + NativeMethods.ISteamGameServer_LogOn(CSteamGameServerAPIContext.GetSteamGameServer(), pszToken2); + } + } + + /// + /// / Login to a generic, anonymous account. + /// / + /// / Note: in previous versions of the SDK, this was automatically called within SteamGameServer_Init, + /// / but this is no longer the case. + /// + public static void LogOnAnonymous() { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_LogOnAnonymous(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + /// + /// / Begin process of logging game server out of steam + /// + public static void LogOff() { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_LogOff(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + /// + /// status functions + /// + public static bool BLoggedOn() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_BLoggedOn(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + public static bool BSecure() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_BSecure(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + public static CSteamID GetSteamID() { + InteropHelp.TestIfAvailableGameServer(); + return (CSteamID)NativeMethods.ISteamGameServer_GetSteamID(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + /// + /// / Returns true if the master server has requested a restart. + /// / Only returns true once per request. + /// + public static bool WasRestartRequested() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_WasRestartRequested(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + /// + /// Server state. These properties may be changed at any time. + /// / Max player count that will be reported to server browser and client queries + /// + public static void SetMaxPlayerCount(int cPlayersMax) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_SetMaxPlayerCount(CSteamGameServerAPIContext.GetSteamGameServer(), cPlayersMax); + } + + /// + /// / Number of bots. Default value is zero + /// + public static void SetBotPlayerCount(int cBotplayers) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_SetBotPlayerCount(CSteamGameServerAPIContext.GetSteamGameServer(), cBotplayers); + } + + /// + /// / Set the name of server as it will appear in the server browser + /// / + /// / @see k_cbMaxGameServerName + /// + public static void SetServerName(string pszServerName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszServerName2 = new InteropHelp.UTF8StringHandle(pszServerName)) { + NativeMethods.ISteamGameServer_SetServerName(CSteamGameServerAPIContext.GetSteamGameServer(), pszServerName2); + } + } + + /// + /// / Set name of map to report in the server browser + /// / + /// / @see k_cbMaxGameServerMapName + /// + public static void SetMapName(string pszMapName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszMapName2 = new InteropHelp.UTF8StringHandle(pszMapName)) { + NativeMethods.ISteamGameServer_SetMapName(CSteamGameServerAPIContext.GetSteamGameServer(), pszMapName2); + } + } + + /// + /// / Let people know if your server will require a password + /// + public static void SetPasswordProtected(bool bPasswordProtected) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_SetPasswordProtected(CSteamGameServerAPIContext.GetSteamGameServer(), bPasswordProtected); + } + + /// + /// / Spectator server port to advertise. The default value is zero, meaning the + /// / service is not used. If your server receives any info requests on the LAN, + /// / this is the value that will be placed into the reply for such local queries. + /// / + /// / This is also the value that will be advertised by the master server. + /// / The only exception is if your server is using a FakeIP. Then then the second + /// / fake port number (index 1) assigned to your server will be listed on the master + /// / server as the spectator port, if you set this value to any nonzero value. + /// / + /// / This function merely controls the values that are advertised -- it's up to you to + /// / configure the server to actually listen on this port and handle any spectator traffic + /// + public static void SetSpectatorPort(ushort unSpectatorPort) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_SetSpectatorPort(CSteamGameServerAPIContext.GetSteamGameServer(), unSpectatorPort); + } + + /// + /// / Name of the spectator server. (Only used if spectator port is nonzero.) + /// / + /// / @see k_cbMaxGameServerMapName + /// + public static void SetSpectatorServerName(string pszSpectatorServerName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszSpectatorServerName2 = new InteropHelp.UTF8StringHandle(pszSpectatorServerName)) { + NativeMethods.ISteamGameServer_SetSpectatorServerName(CSteamGameServerAPIContext.GetSteamGameServer(), pszSpectatorServerName2); + } + } + + /// + /// / Call this to clear the whole list of key/values that are sent in rules queries. + /// + public static void ClearAllKeyValues() { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_ClearAllKeyValues(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + /// + /// / Call this to add/update a key/value pair. + /// + public static void SetKeyValue(string pKey, string pValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pKey2 = new InteropHelp.UTF8StringHandle(pKey)) + using (var pValue2 = new InteropHelp.UTF8StringHandle(pValue)) { + NativeMethods.ISteamGameServer_SetKeyValue(CSteamGameServerAPIContext.GetSteamGameServer(), pKey2, pValue2); + } + } + + /// + /// / Sets a string defining the "gametags" for this server, this is optional, but if it is set + /// / it allows users to filter in the matchmaking/server-browser interfaces based on the value + /// / + /// / @see k_cbMaxGameServerTags + /// + public static void SetGameTags(string pchGameTags) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchGameTags2 = new InteropHelp.UTF8StringHandle(pchGameTags)) { + NativeMethods.ISteamGameServer_SetGameTags(CSteamGameServerAPIContext.GetSteamGameServer(), pchGameTags2); + } + } + + /// + /// / Sets a string defining the "gamedata" for this server, this is optional, but if it is set + /// / it allows users to filter in the matchmaking/server-browser interfaces based on the value + /// / + /// / @see k_cbMaxGameServerGameData + /// + public static void SetGameData(string pchGameData) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchGameData2 = new InteropHelp.UTF8StringHandle(pchGameData)) { + NativeMethods.ISteamGameServer_SetGameData(CSteamGameServerAPIContext.GetSteamGameServer(), pchGameData2); + } + } + + /// + /// / Region identifier. This is an optional field, the default value is empty, meaning the "world" region + /// + public static void SetRegion(string pszRegion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszRegion2 = new InteropHelp.UTF8StringHandle(pszRegion)) { + NativeMethods.ISteamGameServer_SetRegion(CSteamGameServerAPIContext.GetSteamGameServer(), pszRegion2); + } + } + + /// + /// / Indicate whether you wish to be listed on the master server list + /// / and/or respond to server browser / LAN discovery packets. + /// / The server starts with this value set to false. You should set all + /// / relevant server parameters before enabling advertisement on the server. + /// / + /// / (This function used to be named EnableHeartbeats, so if you are wondering + /// / where that function went, it's right here. It does the same thing as before, + /// / the old name was just confusing.) + /// + public static void SetAdvertiseServerActive(bool bActive) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_SetAdvertiseServerActive(CSteamGameServerAPIContext.GetSteamGameServer(), bActive); + } + + /// + /// Player list management / authentication. + /// Retrieve ticket to be sent to the entity who wishes to authenticate you ( using BeginAuthSession API ). + /// pcbTicket retrieves the length of the actual ticket. + /// SteamNetworkingIdentity is an optional parameter to hold the public IP address of the entity you are connecting to + /// if an IP address is passed Steam will only allow the ticket to be used by an entity with that IP address + /// + public static HAuthTicket GetAuthSessionTicket(byte[] pTicket, int cbMaxTicket, out uint pcbTicket, ref SteamNetworkingIdentity pSnid) { + InteropHelp.TestIfAvailableGameServer(); + return (HAuthTicket)NativeMethods.ISteamGameServer_GetAuthSessionTicket(CSteamGameServerAPIContext.GetSteamGameServer(), pTicket, cbMaxTicket, out pcbTicket, ref pSnid); + } + + /// + /// Authenticate ticket ( from GetAuthSessionTicket ) from entity steamID to be sure it is valid and isnt reused + /// Registers for callbacks if the entity goes offline or cancels the ticket ( see ValidateAuthTicketResponse_t callback and EAuthSessionResponse ) + /// + public static EBeginAuthSessionResult BeginAuthSession(byte[] pAuthTicket, int cbAuthTicket, CSteamID steamID) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_BeginAuthSession(CSteamGameServerAPIContext.GetSteamGameServer(), pAuthTicket, cbAuthTicket, steamID); + } + + /// + /// Stop tracking started by BeginAuthSession - called when no longer playing game with this entity + /// + public static void EndAuthSession(CSteamID steamID) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_EndAuthSession(CSteamGameServerAPIContext.GetSteamGameServer(), steamID); + } + + /// + /// Cancel auth ticket from GetAuthSessionTicket, called when no longer playing game with the entity you gave the ticket to + /// + public static void CancelAuthTicket(HAuthTicket hAuthTicket) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_CancelAuthTicket(CSteamGameServerAPIContext.GetSteamGameServer(), hAuthTicket); + } + + /// + /// After receiving a user's authentication data, and passing it to SendUserConnectAndAuthenticate, use this function + /// to determine if the user owns downloadable content specified by the provided AppID. + /// + public static EUserHasLicenseForAppResult UserHasLicenseForApp(CSteamID steamID, AppId_t appID) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_UserHasLicenseForApp(CSteamGameServerAPIContext.GetSteamGameServer(), steamID, appID); + } + + /// + /// Ask if a user in in the specified group, results returns async by GSUserGroupStatus_t + /// returns false if we're not connected to the steam servers and thus cannot ask + /// + public static bool RequestUserGroupStatus(CSteamID steamIDUser, CSteamID steamIDGroup) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_RequestUserGroupStatus(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDUser, steamIDGroup); + } + + /// + /// these two functions s are deprecated, and will not return results + /// they will be removed in a future version of the SDK + /// + public static void GetGameplayStats() { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_GetGameplayStats(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + public static SteamAPICall_t GetServerReputation() { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamGameServer_GetServerReputation(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + /// + /// Returns the public IP of the server according to Steam, useful when the server is + /// behind NAT and you want to advertise its IP in a lobby for other clients to directly + /// connect to + /// + public static SteamIPAddress_t GetPublicIP() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_GetPublicIP(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + /// + /// Server browser related query packet processing for shared socket mode. These are used + /// when you pass STEAMGAMESERVER_QUERY_PORT_SHARED as the query port to SteamGameServer_Init. + /// IP address and port are in host order, i.e 127.0.0.1 == 0x7f000001 + /// These are used when you've elected to multiplex the game server's UDP socket + /// rather than having the master server updater use its own sockets. + /// Source games use this to simplify the job of the server admins, so they + /// don't have to open up more ports on their firewalls. + /// Call this when a packet that starts with 0xFFFFFFFF comes in. That means + /// it's for us. + /// + public static bool HandleIncomingPacket(byte[] pData, int cbData, uint srcIP, ushort srcPort) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_HandleIncomingPacket(CSteamGameServerAPIContext.GetSteamGameServer(), pData, cbData, srcIP, srcPort); + } + + /// + /// AFTER calling HandleIncomingPacket for any packets that came in that frame, call this. + /// This gets a packet that the master server updater needs to send out on UDP. + /// It returns the length of the packet it wants to send, or 0 if there are no more packets to send. + /// Call this each frame until it returns 0. + /// + public static int GetNextOutgoingPacket(byte[] pOut, int cbMaxOut, out uint pNetAdr, out ushort pPort) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_GetNextOutgoingPacket(CSteamGameServerAPIContext.GetSteamGameServer(), pOut, cbMaxOut, out pNetAdr, out pPort); + } + + /// + /// Server clan association + /// associate this game server with this clan for the purposes of computing player compat + /// + public static SteamAPICall_t AssociateWithClan(CSteamID steamIDClan) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamGameServer_AssociateWithClan(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDClan); + } + + /// + /// ask if any of the current players dont want to play with this new player - or vice versa + /// + public static SteamAPICall_t ComputeNewPlayerCompatibility(CSteamID steamIDNewPlayer) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamGameServer_ComputeNewPlayerCompatibility(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDNewPlayer); + } + + /// + /// Handles receiving a new connection from a Steam user. This call will ask the Steam + /// servers to validate the users identity, app ownership, and VAC status. If the Steam servers + /// are off-line, then it will validate the cached ticket itself which will validate app ownership + /// and identity. The AuthBlob here should be acquired on the game client using SteamUser()->InitiateGameConnection() + /// and must then be sent up to the game server for authentication. + /// Return Value: returns true if the users ticket passes basic checks. pSteamIDUser will contain the Steam ID of this user. pSteamIDUser must NOT be NULL + /// If the call succeeds then you should expect a GSClientApprove_t or GSClientDeny_t callback which will tell you whether authentication + /// for the user has succeeded or failed (the steamid in the callback will match the one returned by this call) + /// DEPRECATED! This function will be removed from the SDK in an upcoming version. + /// Please migrate to BeginAuthSession and related functions. + /// + public static bool SendUserConnectAndAuthenticate_DEPRECATED(uint unIPClient, byte[] pvAuthBlob, uint cubAuthBlobSize, out CSteamID pSteamIDUser) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamGameServer_SendUserConnectAndAuthenticate_DEPRECATED(CSteamGameServerAPIContext.GetSteamGameServer(), unIPClient, pvAuthBlob, cubAuthBlobSize, out pSteamIDUser); + } + + /// + /// Creates a fake user (ie, a bot) which will be listed as playing on the server, but skips validation. + /// Return Value: Returns a SteamID for the user to be tracked with, you should call EndAuthSession() + /// when this user leaves the server just like you would for a real user. + /// + public static CSteamID CreateUnauthenticatedUserConnection() { + InteropHelp.TestIfAvailableGameServer(); + return (CSteamID)NativeMethods.ISteamGameServer_CreateUnauthenticatedUserConnection(CSteamGameServerAPIContext.GetSteamGameServer()); + } + + /// + /// Should be called whenever a user leaves our game server, this lets Steam internally + /// track which users are currently on which servers for the purposes of preventing a single + /// account being logged into multiple servers, showing who is currently on a server, etc. + /// DEPRECATED! This function will be removed from the SDK in an upcoming version. + /// Please migrate to BeginAuthSession and related functions. + /// + public static void SendUserDisconnect_DEPRECATED(CSteamID steamIDUser) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamGameServer_SendUserDisconnect_DEPRECATED(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDUser); + } + + /// + /// Update the data to be displayed in the server browser and matchmaking interfaces for a user + /// currently connected to the server. For regular users you must call this after you receive a + /// GSUserValidationSuccess callback. + /// Return Value: true if successful, false if failure (ie, steamIDUser wasn't for an active player) + /// + public static bool BUpdateUserData(CSteamID steamIDUser, string pchPlayerName, uint uScore) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchPlayerName2 = new InteropHelp.UTF8StringHandle(pchPlayerName)) { + return NativeMethods.ISteamGameServer_BUpdateUserData(CSteamGameServerAPIContext.GetSteamGameServer(), steamIDUser, pchPlayerName2, uScore); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserver.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserver.cs.meta new file mode 100644 index 0000000..ddc62f1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8c4257f3ef3cd614f8137738c4a58d8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverclient.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverclient.cs new file mode 100644 index 0000000..0c41cff --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverclient.cs @@ -0,0 +1,376 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerClient { + /// + /// Creates a communication pipe to the Steam client. + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static HSteamPipe CreateSteamPipe() { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamPipe)NativeMethods.ISteamClient_CreateSteamPipe(CSteamGameServerAPIContext.GetSteamClient()); + } + + /// + /// Releases a previously created communications pipe + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static bool BReleaseSteamPipe(HSteamPipe hSteamPipe) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamClient_BReleaseSteamPipe(CSteamGameServerAPIContext.GetSteamClient(), hSteamPipe); + } + + /// + /// connects to an existing global user, failing if none exists + /// used by the game to coordinate with the steamUI + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static HSteamUser ConnectToGlobalUser(HSteamPipe hSteamPipe) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamUser)NativeMethods.ISteamClient_ConnectToGlobalUser(CSteamGameServerAPIContext.GetSteamClient(), hSteamPipe); + } + + /// + /// used by game servers, create a steam user that won't be shared with anyone else + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static HSteamUser CreateLocalUser(out HSteamPipe phSteamPipe, EAccountType eAccountType) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamUser)NativeMethods.ISteamClient_CreateLocalUser(CSteamGameServerAPIContext.GetSteamClient(), out phSteamPipe, eAccountType); + } + + /// + /// removes an allocated user + /// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling + /// + public static void ReleaseUser(HSteamPipe hSteamPipe, HSteamUser hUser) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamClient_ReleaseUser(CSteamGameServerAPIContext.GetSteamClient(), hSteamPipe, hUser); + } + + /// + /// retrieves the ISteamUser interface associated with the handle + /// + public static IntPtr GetISteamUser(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamUser(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// retrieves the ISteamGameServer interface associated with the handle + /// + public static IntPtr GetISteamGameServer(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamGameServer(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// set the local IP and Port to bind to + /// this must be set before CreateLocalUser() + /// + public static void SetLocalIPBinding(ref SteamIPAddress_t unIP, ushort usPort) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamClient_SetLocalIPBinding(CSteamGameServerAPIContext.GetSteamClient(), ref unIP, usPort); + } + + /// + /// returns the ISteamFriends interface + /// + public static IntPtr GetISteamFriends(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamFriends(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamUtils interface + /// + public static IntPtr GetISteamUtils(HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamUtils(CSteamGameServerAPIContext.GetSteamClient(), hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamMatchmaking interface + /// + public static IntPtr GetISteamMatchmaking(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamMatchmaking(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamMatchmakingServers interface + /// + public static IntPtr GetISteamMatchmakingServers(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamMatchmakingServers(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the a generic interface + /// + public static IntPtr GetISteamGenericInterface(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamGenericInterface(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamUserStats interface + /// + public static IntPtr GetISteamUserStats(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamUserStats(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the ISteamGameServerStats interface + /// + public static IntPtr GetISteamGameServerStats(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamGameServerStats(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns apps interface + /// + public static IntPtr GetISteamApps(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamApps(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// networking + /// + public static IntPtr GetISteamNetworking(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamNetworking(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// remote storage + /// + public static IntPtr GetISteamRemoteStorage(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamRemoteStorage(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// user screenshots + /// + public static IntPtr GetISteamScreenshots(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamScreenshots(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// game search + /// + public static IntPtr GetISteamGameSearch(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamGameSearch(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns the number of IPC calls made since the last time this function was called + /// Used for perf debugging so you can understand how many IPC calls your game makes per frame + /// Every IPC call is at minimum a thread context switch if not a process one so you want to rate + /// control how often you do them. + /// + public static uint GetIPCCallCount() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamClient_GetIPCCallCount(CSteamGameServerAPIContext.GetSteamClient()); + } + + /// + /// API warning handling + /// 'int' is the severity; 0 for msg, 1 for warning + /// 'const char *' is the text of the message + /// callbacks will occur directly after the API function is called that generated the warning or message. + /// + public static void SetWarningMessageHook(SteamAPIWarningMessageHook_t pFunction) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamClient_SetWarningMessageHook(CSteamGameServerAPIContext.GetSteamClient(), pFunction); + } + + /// + /// Trigger global shutdown for the DLL + /// + public static bool BShutdownIfAllPipesClosed() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamClient_BShutdownIfAllPipesClosed(CSteamGameServerAPIContext.GetSteamClient()); + } + + /// + /// Expose HTTP interface + /// + public static IntPtr GetISteamHTTP(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamHTTP(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Exposes the ISteamController interface - deprecated in favor of Steam Input + /// + public static IntPtr GetISteamController(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamController(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// Exposes the ISteamUGC interface + /// + public static IntPtr GetISteamUGC(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamUGC(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// returns app list interface, only available on specially registered apps + /// + public static IntPtr GetISteamAppList(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamAppList(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// Music Player + /// + public static IntPtr GetISteamMusic(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamMusic(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Music Player Remote + /// + public static IntPtr GetISteamMusicRemote(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamMusicRemote(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// html page display + /// + public static IntPtr GetISteamHTMLSurface(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamHTMLSurface(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// inventory + /// + public static IntPtr GetISteamInventory(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamInventory(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Video + /// + public static IntPtr GetISteamVideo(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamVideo(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Parental controls + /// + public static IntPtr GetISteamParentalSettings(HSteamUser hSteamuser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamParentalSettings(CSteamGameServerAPIContext.GetSteamClient(), hSteamuser, hSteamPipe, pchVersion2); + } + } + + /// + /// Exposes the Steam Input interface for controller support + /// + public static IntPtr GetISteamInput(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamInput(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// Steam Parties interface + /// + public static IntPtr GetISteamParties(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamParties(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + + /// + /// Steam Remote Play interface + /// + public static IntPtr GetISteamRemotePlay(HSteamUser hSteamUser, HSteamPipe hSteamPipe, string pchVersion) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchVersion2 = new InteropHelp.UTF8StringHandle(pchVersion)) { + return NativeMethods.ISteamClient_GetISteamRemotePlay(CSteamGameServerAPIContext.GetSteamClient(), hSteamUser, hSteamPipe, pchVersion2); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverclient.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverclient.cs.meta new file mode 100644 index 0000000..04edd62 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverclient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b4c8a2697f638c40a8e3c70f86e5c96 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverhttp.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverhttp.cs new file mode 100644 index 0000000..010fde2 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverhttp.cs @@ -0,0 +1,277 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerHTTP { + /// + /// Initializes a new HTTP request, returning a handle to use in further operations on it. Requires + /// the method (GET or POST) and the absolute URL for the request. Both http and https are supported, + /// so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/ + /// or such. + /// + public static HTTPRequestHandle CreateHTTPRequest(EHTTPMethod eHTTPRequestMethod, string pchAbsoluteURL) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchAbsoluteURL2 = new InteropHelp.UTF8StringHandle(pchAbsoluteURL)) { + return (HTTPRequestHandle)NativeMethods.ISteamHTTP_CreateHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), eHTTPRequestMethod, pchAbsoluteURL2); + } + } + + /// + /// Set a context value for the request, which will be returned in the HTTPRequestCompleted_t callback after + /// sending the request. This is just so the caller can easily keep track of which callbacks go with which request data. + /// + public static bool SetHTTPRequestContextValue(HTTPRequestHandle hRequest, ulong ulContextValue) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_SetHTTPRequestContextValue(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, ulContextValue); + } + + /// + /// Set a timeout in seconds for the HTTP request, must be called prior to sending the request. Default + /// timeout is 60 seconds if you don't call this. Returns false if the handle is invalid, or the request + /// has already been sent. + /// + public static bool SetHTTPRequestNetworkActivityTimeout(HTTPRequestHandle hRequest, uint unTimeoutSeconds) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_SetHTTPRequestNetworkActivityTimeout(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, unTimeoutSeconds); + } + + /// + /// Set a request header value for the request, must be called prior to sending the request. Will + /// return false if the handle is invalid or the request is already sent. + /// + public static bool SetHTTPRequestHeaderValue(HTTPRequestHandle hRequest, string pchHeaderName, string pchHeaderValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) + using (var pchHeaderValue2 = new InteropHelp.UTF8StringHandle(pchHeaderValue)) { + return NativeMethods.ISteamHTTP_SetHTTPRequestHeaderValue(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, pchHeaderValue2); + } + } + + /// + /// Set a GET or POST parameter value on the request, which is set will depend on the EHTTPMethod specified + /// when creating the request. Must be called prior to sending the request. Will return false if the + /// handle is invalid or the request is already sent. + /// + public static bool SetHTTPRequestGetOrPostParameter(HTTPRequestHandle hRequest, string pchParamName, string pchParamValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchParamName2 = new InteropHelp.UTF8StringHandle(pchParamName)) + using (var pchParamValue2 = new InteropHelp.UTF8StringHandle(pchParamValue)) { + return NativeMethods.ISteamHTTP_SetHTTPRequestGetOrPostParameter(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchParamName2, pchParamValue2); + } + } + + /// + /// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on + /// asynchronous response via callback. + /// Note: If the user is in offline mode in Steam, then this will add a only-if-cached cache-control + /// header and only do a local cache lookup rather than sending any actual remote request. + /// + public static bool SendHTTPRequest(HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_SendHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out pCallHandle); + } + + /// + /// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on + /// asynchronous response via callback for completion, and listen for HTTPRequestHeadersReceived_t and + /// HTTPRequestDataReceived_t callbacks while streaming. + /// + public static bool SendHTTPRequestAndStreamResponse(HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_SendHTTPRequestAndStreamResponse(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out pCallHandle); + } + + /// + /// Defers a request you have sent, the actual HTTP client code may have many requests queued, and this will move + /// the specified request to the tail of the queue. Returns false on invalid handle, or if the request is not yet sent. + /// + public static bool DeferHTTPRequest(HTTPRequestHandle hRequest) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_DeferHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest); + } + + /// + /// Prioritizes a request you have sent, the actual HTTP client code may have many requests queued, and this will move + /// the specified request to the head of the queue. Returns false on invalid handle, or if the request is not yet sent. + /// + public static bool PrioritizeHTTPRequest(HTTPRequestHandle hRequest) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_PrioritizeHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest); + } + + /// + /// Checks if a response header is present in a HTTP response given a handle from HTTPRequestCompleted_t, also + /// returns the size of the header value if present so the caller and allocate a correctly sized buffer for + /// GetHTTPResponseHeaderValue. + /// + public static bool GetHTTPResponseHeaderSize(HTTPRequestHandle hRequest, string pchHeaderName, out uint unResponseHeaderSize) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) { + return NativeMethods.ISteamHTTP_GetHTTPResponseHeaderSize(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, out unResponseHeaderSize); + } + } + + /// + /// Gets header values from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the + /// header is not present or if your buffer is too small to contain it's value. You should first call + /// BGetHTTPResponseHeaderSize to check for the presence of the header and to find out the size buffer needed. + /// + public static bool GetHTTPResponseHeaderValue(HTTPRequestHandle hRequest, string pchHeaderName, byte[] pHeaderValueBuffer, uint unBufferSize) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) { + return NativeMethods.ISteamHTTP_GetHTTPResponseHeaderValue(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, pHeaderValueBuffer, unBufferSize); + } + } + + /// + /// Gets the size of the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the + /// handle is invalid. + /// + public static bool GetHTTPResponseBodySize(HTTPRequestHandle hRequest, out uint unBodySize) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_GetHTTPResponseBodySize(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out unBodySize); + } + + /// + /// Gets the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the + /// handle is invalid or is to a streaming response, or if the provided buffer is not the correct size. Use BGetHTTPResponseBodySize first to find out + /// the correct buffer size to use. + /// + public static bool GetHTTPResponseBodyData(HTTPRequestHandle hRequest, byte[] pBodyDataBuffer, uint unBufferSize) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_GetHTTPResponseBodyData(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pBodyDataBuffer, unBufferSize); + } + + /// + /// Gets the body data from a streaming HTTP response given a handle from HTTPRequestDataReceived_t. Will return false if the + /// handle is invalid or is to a non-streaming response (meaning it wasn't sent with SendHTTPRequestAndStreamResponse), or if the buffer size and offset + /// do not match the size and offset sent in HTTPRequestDataReceived_t. + /// + public static bool GetHTTPStreamingResponseBodyData(HTTPRequestHandle hRequest, uint cOffset, byte[] pBodyDataBuffer, uint unBufferSize) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_GetHTTPStreamingResponseBodyData(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, cOffset, pBodyDataBuffer, unBufferSize); + } + + /// + /// Releases an HTTP response handle, should always be called to free resources after receiving a HTTPRequestCompleted_t + /// callback and finishing using the response. + /// + public static bool ReleaseHTTPRequest(HTTPRequestHandle hRequest) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_ReleaseHTTPRequest(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest); + } + + /// + /// Gets progress on downloading the body for the request. This will be zero unless a response header has already been + /// received which included a content-length field. For responses that contain no content-length it will report + /// zero for the duration of the request as the size is unknown until the connection closes. + /// + public static bool GetHTTPDownloadProgressPct(HTTPRequestHandle hRequest, out float pflPercentOut) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_GetHTTPDownloadProgressPct(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out pflPercentOut); + } + + /// + /// Sets the body for an HTTP Post request. Will fail and return false on a GET request, and will fail if POST params + /// have already been set for the request. Setting this raw body makes it the only contents for the post, the pchContentType + /// parameter will set the content-type header for the request so the server may know how to interpret the body. + /// + public static bool SetHTTPRequestRawPostBody(HTTPRequestHandle hRequest, string pchContentType, byte[] pubBody, uint unBodyLen) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchContentType2 = new InteropHelp.UTF8StringHandle(pchContentType)) { + return NativeMethods.ISteamHTTP_SetHTTPRequestRawPostBody(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchContentType2, pubBody, unBodyLen); + } + } + + /// + /// Creates a cookie container handle which you must later free with ReleaseCookieContainer(). If bAllowResponsesToModify=true + /// than any response to your requests using this cookie container may add new cookies which may be transmitted with + /// future requests. If bAllowResponsesToModify=false than only cookies you explicitly set will be sent. This API is just for + /// during process lifetime, after steam restarts no cookies are persisted and you have no way to access the cookie container across + /// repeat executions of your process. + /// + public static HTTPCookieContainerHandle CreateCookieContainer(bool bAllowResponsesToModify) { + InteropHelp.TestIfAvailableGameServer(); + return (HTTPCookieContainerHandle)NativeMethods.ISteamHTTP_CreateCookieContainer(CSteamGameServerAPIContext.GetSteamHTTP(), bAllowResponsesToModify); + } + + /// + /// Release a cookie container you are finished using, freeing it's memory + /// + public static bool ReleaseCookieContainer(HTTPCookieContainerHandle hCookieContainer) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_ReleaseCookieContainer(CSteamGameServerAPIContext.GetSteamHTTP(), hCookieContainer); + } + + /// + /// Adds a cookie to the specified cookie container that will be used with future requests. + /// + public static bool SetCookie(HTTPCookieContainerHandle hCookieContainer, string pchHost, string pchUrl, string pchCookie) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchHost2 = new InteropHelp.UTF8StringHandle(pchHost)) + using (var pchUrl2 = new InteropHelp.UTF8StringHandle(pchUrl)) + using (var pchCookie2 = new InteropHelp.UTF8StringHandle(pchCookie)) { + return NativeMethods.ISteamHTTP_SetCookie(CSteamGameServerAPIContext.GetSteamHTTP(), hCookieContainer, pchHost2, pchUrl2, pchCookie2); + } + } + + /// + /// Set the cookie container to use for a HTTP request + /// + public static bool SetHTTPRequestCookieContainer(HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_SetHTTPRequestCookieContainer(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, hCookieContainer); + } + + /// + /// Set the extra user agent info for a request, this doesn't clobber the normal user agent, it just adds the extra info on the end + /// + public static bool SetHTTPRequestUserAgentInfo(HTTPRequestHandle hRequest, string pchUserAgentInfo) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchUserAgentInfo2 = new InteropHelp.UTF8StringHandle(pchUserAgentInfo)) { + return NativeMethods.ISteamHTTP_SetHTTPRequestUserAgentInfo(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, pchUserAgentInfo2); + } + } + + /// + /// Disable or re-enable verification of SSL/TLS certificates. + /// By default, certificates are checked for all HTTPS requests. + /// + public static bool SetHTTPRequestRequiresVerifiedCertificate(HTTPRequestHandle hRequest, bool bRequireVerifiedCertificate) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_SetHTTPRequestRequiresVerifiedCertificate(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, bRequireVerifiedCertificate); + } + + /// + /// Set an absolute timeout on the HTTP request, this is just a total time timeout different than the network activity timeout + /// which can bump everytime we get more data + /// + public static bool SetHTTPRequestAbsoluteTimeoutMS(HTTPRequestHandle hRequest, uint unMilliseconds) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_SetHTTPRequestAbsoluteTimeoutMS(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, unMilliseconds); + } + + /// + /// Check if the reason the request failed was because we timed it out (rather than some harder failure) + /// + public static bool GetHTTPRequestWasTimedOut(HTTPRequestHandle hRequest, out bool pbWasTimedOut) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamHTTP_GetHTTPRequestWasTimedOut(CSteamGameServerAPIContext.GetSteamHTTP(), hRequest, out pbWasTimedOut); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverhttp.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverhttp.cs.meta new file mode 100644 index 0000000..d5a2fa6 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverhttp.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5a78311cd8781b041a4f4cc4990719ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverinventory.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverinventory.cs new file mode 100644 index 0000000..608216b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverinventory.cs @@ -0,0 +1,478 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerInventory { + /// + /// INVENTORY ASYNC RESULT MANAGEMENT + /// Asynchronous inventory queries always output a result handle which can be used with + /// GetResultStatus, GetResultItems, etc. A SteamInventoryResultReady_t callback will + /// be triggered when the asynchronous result becomes ready (or fails). + /// Find out the status of an asynchronous inventory result handle. Possible values: + /// k_EResultPending - still in progress + /// k_EResultOK - done, result ready + /// k_EResultExpired - done, result ready, maybe out of date (see DeserializeResult) + /// k_EResultInvalidParam - ERROR: invalid API call parameters + /// k_EResultServiceUnavailable - ERROR: service temporarily down, you may retry later + /// k_EResultLimitExceeded - ERROR: operation would exceed per-user inventory limits + /// k_EResultFail - ERROR: unknown / generic error + /// + public static EResult GetResultStatus(SteamInventoryResult_t resultHandle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_GetResultStatus(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle); + } + + /// + /// Copies the contents of a result set into a flat array. The specific + /// contents of the result set depend on which query which was used. + /// + public static bool GetResultItems(SteamInventoryResult_t resultHandle, SteamItemDetails_t[] pOutItemsArray, ref uint punOutItemsArraySize) { + InteropHelp.TestIfAvailableGameServer(); + if (pOutItemsArray != null && pOutItemsArray.Length != punOutItemsArraySize) { + throw new System.ArgumentException("pOutItemsArray must be the same size as punOutItemsArraySize!"); + } + return NativeMethods.ISteamInventory_GetResultItems(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle, pOutItemsArray, ref punOutItemsArraySize); + } + + /// + /// In combination with GetResultItems, you can use GetResultItemProperty to retrieve + /// dynamic string properties for a given item returned in the result set. + /// Property names are always composed of ASCII letters, numbers, and/or underscores. + /// Pass a NULL pointer for pchPropertyName to get a comma - separated list of available + /// property names. + /// If pchValueBuffer is NULL, *punValueBufferSize will contain the + /// suggested buffer size. Otherwise it will be the number of bytes actually copied + /// to pchValueBuffer. If the results do not fit in the given buffer, partial + /// results may be copied. + /// + public static bool GetResultItemProperty(SteamInventoryResult_t resultHandle, uint unItemIndex, string pchPropertyName, out string pchValueBuffer, ref uint punValueBufferSizeOut) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchValueBuffer2 = Marshal.AllocHGlobal((int)punValueBufferSizeOut); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + bool ret = NativeMethods.ISteamInventory_GetResultItemProperty(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle, unItemIndex, pchPropertyName2, pchValueBuffer2, ref punValueBufferSizeOut); + pchValueBuffer = ret ? InteropHelp.PtrToStringUTF8(pchValueBuffer2) : null; + Marshal.FreeHGlobal(pchValueBuffer2); + return ret; + } + } + + /// + /// Returns the server time at which the result was generated. Compare against + /// the value of IClientUtils::GetServerRealTime() to determine age. + /// + public static uint GetResultTimestamp(SteamInventoryResult_t resultHandle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_GetResultTimestamp(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle); + } + + /// + /// Returns true if the result belongs to the target steam ID, false if the + /// result does not. This is important when using DeserializeResult, to verify + /// that a remote player is not pretending to have a different user's inventory. + /// + public static bool CheckResultSteamID(SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_CheckResultSteamID(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle, steamIDExpected); + } + + /// + /// Destroys a result handle and frees all associated memory. + /// + public static void DestroyResult(SteamInventoryResult_t resultHandle) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamInventory_DestroyResult(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle); + } + + /// + /// INVENTORY ASYNC QUERY + /// Captures the entire state of the current user's Steam inventory. + /// You must call DestroyResult on this handle when you are done with it. + /// Returns false and sets *pResultHandle to zero if inventory is unavailable. + /// Note: calls to this function are subject to rate limits and may return + /// cached results if called too frequently. It is suggested that you call + /// this function only when you are about to display the user's full inventory, + /// or if you expect that the inventory may have changed. + /// + public static bool GetAllItems(out SteamInventoryResult_t pResultHandle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_GetAllItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle); + } + + /// + /// Captures the state of a subset of the current user's Steam inventory, + /// identified by an array of item instance IDs. The results from this call + /// can be serialized and passed to other players to "prove" that the current + /// user owns specific items, without exposing the user's entire inventory. + /// For example, you could call GetItemsByID with the IDs of the user's + /// currently equipped cosmetic items and serialize this to a buffer, and + /// then transmit this buffer to other players upon joining a game. + /// + public static bool GetItemsByID(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t[] pInstanceIDs, uint unCountInstanceIDs) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_GetItemsByID(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pInstanceIDs, unCountInstanceIDs); + } + + /// + /// RESULT SERIALIZATION AND AUTHENTICATION + /// Serialized result sets contain a short signature which can't be forged + /// or replayed across different game sessions. A result set can be serialized + /// on the local client, transmitted to other players via your game networking, + /// and deserialized by the remote players. This is a secure way of preventing + /// hackers from lying about posessing rare/high-value items. + /// Serializes a result set with signature bytes to an output buffer. Pass + /// NULL as an output buffer to get the required size via punOutBufferSize. + /// The size of a serialized result depends on the number items which are being + /// serialized. When securely transmitting items to other players, it is + /// recommended to use "GetItemsByID" first to create a minimal result set. + /// Results have a built-in timestamp which will be considered "expired" after + /// an hour has elapsed. See DeserializeResult for expiration handling. + /// + public static bool SerializeResult(SteamInventoryResult_t resultHandle, byte[] pOutBuffer, out uint punOutBufferSize) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_SerializeResult(CSteamGameServerAPIContext.GetSteamInventory(), resultHandle, pOutBuffer, out punOutBufferSize); + } + + /// + /// Deserializes a result set and verifies the signature bytes. Returns false + /// if bRequireFullOnlineVerify is set but Steam is running in Offline mode. + /// Otherwise returns true and then delivers error codes via GetResultStatus. + /// The bRESERVED_MUST_BE_FALSE flag is reserved for future use and should not + /// be set to true by your game at this time. + /// DeserializeResult has a potential soft-failure mode where the handle status + /// is set to k_EResultExpired. GetResultItems() still succeeds in this mode. + /// The "expired" result could indicate that the data may be out of date - not + /// just due to timed expiration (one hour), but also because one of the items + /// in the result set may have been traded or consumed since the result set was + /// generated. You could compare the timestamp from GetResultTimestamp() to + /// ISteamUtils::GetServerRealTime() to determine how old the data is. You could + /// simply ignore the "expired" result code and continue as normal, or you + /// could challenge the player with expired data to send an updated result set. + /// + public static bool DeserializeResult(out SteamInventoryResult_t pOutResultHandle, byte[] pBuffer, uint unBufferSize, bool bRESERVED_MUST_BE_FALSE = false) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_DeserializeResult(CSteamGameServerAPIContext.GetSteamInventory(), out pOutResultHandle, pBuffer, unBufferSize, bRESERVED_MUST_BE_FALSE); + } + + /// + /// INVENTORY ASYNC MODIFICATION + /// GenerateItems() creates one or more items and then generates a SteamInventoryCallback_t + /// notification with a matching nCallbackContext parameter. This API is only intended + /// for prototyping - it is only usable by Steam accounts that belong to the publisher group + /// for your game. + /// If punArrayQuantity is not NULL, it should be the same length as pArrayItems and should + /// describe the quantity of each item to generate. + /// + public static bool GenerateItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayItemDefs, uint[] punArrayQuantity, uint unArrayLength) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_GenerateItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pArrayItemDefs, punArrayQuantity, unArrayLength); + } + + /// + /// GrantPromoItems() checks the list of promotional items for which the user may be eligible + /// and grants the items (one time only). On success, the result set will include items which + /// were granted, if any. If no items were granted because the user isn't eligible for any + /// promotions, this is still considered a success. + /// + public static bool GrantPromoItems(out SteamInventoryResult_t pResultHandle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_GrantPromoItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle); + } + + /// + /// AddPromoItem() / AddPromoItems() are restricted versions of GrantPromoItems(). Instead of + /// scanning for all eligible promotional items, the check is restricted to a single item + /// definition or set of item definitions. This can be useful if your game has custom UI for + /// showing a specific promo item to the user. + /// + public static bool AddPromoItem(out SteamInventoryResult_t pResultHandle, SteamItemDef_t itemDef) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_AddPromoItem(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, itemDef); + } + + public static bool AddPromoItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayItemDefs, uint unArrayLength) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_AddPromoItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pArrayItemDefs, unArrayLength); + } + + /// + /// ConsumeItem() removes items from the inventory, permanently. They cannot be recovered. + /// Not for the faint of heart - if your game implements item removal at all, a high-friction + /// UI confirmation process is highly recommended. + /// + public static bool ConsumeItem(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemConsume, uint unQuantity) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_ConsumeItem(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, itemConsume, unQuantity); + } + + /// + /// ExchangeItems() is an atomic combination of item generation and consumption. + /// It can be used to implement crafting recipes or transmutations, or items which unpack + /// themselves into other items (e.g., a chest). + /// Exchange recipes are defined in the ItemDef, and explicitly list the required item + /// types and resulting generated type. + /// Exchange recipes are evaluated atomically by the Inventory Service; if the supplied + /// components do not match the recipe, or do not contain sufficient quantity, the + /// exchange will fail. + /// + public static bool ExchangeItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayGenerate, uint[] punArrayGenerateQuantity, uint unArrayGenerateLength, SteamItemInstanceID_t[] pArrayDestroy, uint[] punArrayDestroyQuantity, uint unArrayDestroyLength) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_ExchangeItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pArrayGenerate, punArrayGenerateQuantity, unArrayGenerateLength, pArrayDestroy, punArrayDestroyQuantity, unArrayDestroyLength); + } + + /// + /// TransferItemQuantity() is intended for use with items which are "stackable" (can have + /// quantity greater than one). It can be used to split a stack into two, or to transfer + /// quantity from one stack into another stack of identical items. To split one stack into + /// two, pass k_SteamItemInstanceIDInvalid for itemIdDest and a new item will be generated. + /// + public static bool TransferItemQuantity(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemIdSource, uint unQuantity, SteamItemInstanceID_t itemIdDest) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_TransferItemQuantity(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, itemIdSource, unQuantity, itemIdDest); + } + + /// + /// TIMED DROPS AND PLAYTIME CREDIT + /// Deprecated. Calling this method is not required for proper playtime accounting. + /// + public static void SendItemDropHeartbeat() { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamInventory_SendItemDropHeartbeat(CSteamGameServerAPIContext.GetSteamInventory()); + } + + /// + /// Playtime credit must be consumed and turned into item drops by your game. Only item + /// definitions which are marked as "playtime item generators" can be spawned. The call + /// will return an empty result set if there is not enough playtime credit for a drop. + /// Your game should call TriggerItemDrop at an appropriate time for the user to receive + /// new items, such as between rounds or while the player is dead. Note that players who + /// hack their clients could modify the value of "dropListDefinition", so do not use it + /// to directly control rarity. + /// See your Steamworks configuration to set playtime drop rates for individual itemdefs. + /// The client library will suppress too-frequent calls to this method. + /// + public static bool TriggerItemDrop(out SteamInventoryResult_t pResultHandle, SteamItemDef_t dropListDefinition) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_TriggerItemDrop(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, dropListDefinition); + } + + /// + /// Deprecated. This method is not supported. + /// + public static bool TradeItems(out SteamInventoryResult_t pResultHandle, CSteamID steamIDTradePartner, SteamItemInstanceID_t[] pArrayGive, uint[] pArrayGiveQuantity, uint nArrayGiveLength, SteamItemInstanceID_t[] pArrayGet, uint[] pArrayGetQuantity, uint nArrayGetLength) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_TradeItems(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, steamIDTradePartner, pArrayGive, pArrayGiveQuantity, nArrayGiveLength, pArrayGet, pArrayGetQuantity, nArrayGetLength); + } + + /// + /// ITEM DEFINITIONS + /// Item definitions are a mapping of "definition IDs" (integers between 1 and 1000000) + /// to a set of string properties. Some of these properties are required to display items + /// on the Steam community web site. Other properties can be defined by applications. + /// Use of these functions is optional; there is no reason to call LoadItemDefinitions + /// if your game hardcodes the numeric definition IDs (eg, purple face mask = 20, blue + /// weapon mod = 55) and does not allow for adding new item types without a client patch. + /// LoadItemDefinitions triggers the automatic load and refresh of item definitions. + /// Every time new item definitions are available (eg, from the dynamic addition of new + /// item types while players are still in-game), a SteamInventoryDefinitionUpdate_t + /// callback will be fired. + /// + public static bool LoadItemDefinitions() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_LoadItemDefinitions(CSteamGameServerAPIContext.GetSteamInventory()); + } + + /// + /// GetItemDefinitionIDs returns the set of all defined item definition IDs (which are + /// defined via Steamworks configuration, and not necessarily contiguous integers). + /// If pItemDefIDs is null, the call will return true and *punItemDefIDsArraySize will + /// contain the total size necessary for a subsequent call. Otherwise, the call will + /// return false if and only if there is not enough space in the output array. + /// + public static bool GetItemDefinitionIDs(SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize) { + InteropHelp.TestIfAvailableGameServer(); + if (pItemDefIDs != null && pItemDefIDs.Length != punItemDefIDsArraySize) { + throw new System.ArgumentException("pItemDefIDs must be the same size as punItemDefIDsArraySize!"); + } + return NativeMethods.ISteamInventory_GetItemDefinitionIDs(CSteamGameServerAPIContext.GetSteamInventory(), pItemDefIDs, ref punItemDefIDsArraySize); + } + + /// + /// GetItemDefinitionProperty returns a string property from a given item definition. + /// Note that some properties (for example, "name") may be localized and will depend + /// on the current Steam language settings (see ISteamApps::GetCurrentGameLanguage). + /// Property names are always composed of ASCII letters, numbers, and/or underscores. + /// Pass a NULL pointer for pchPropertyName to get a comma - separated list of available + /// property names. If pchValueBuffer is NULL, *punValueBufferSize will contain the + /// suggested buffer size. Otherwise it will be the number of bytes actually copied + /// to pchValueBuffer. If the results do not fit in the given buffer, partial + /// results may be copied. + /// + public static bool GetItemDefinitionProperty(SteamItemDef_t iDefinition, string pchPropertyName, out string pchValueBuffer, ref uint punValueBufferSizeOut) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchValueBuffer2 = Marshal.AllocHGlobal((int)punValueBufferSizeOut); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + bool ret = NativeMethods.ISteamInventory_GetItemDefinitionProperty(CSteamGameServerAPIContext.GetSteamInventory(), iDefinition, pchPropertyName2, pchValueBuffer2, ref punValueBufferSizeOut); + pchValueBuffer = ret ? InteropHelp.PtrToStringUTF8(pchValueBuffer2) : null; + Marshal.FreeHGlobal(pchValueBuffer2); + return ret; + } + } + + /// + /// Request the list of "eligible" promo items that can be manually granted to the given + /// user. These are promo items of type "manual" that won't be granted automatically. + /// An example usage of this is an item that becomes available every week. + /// + public static SteamAPICall_t RequestEligiblePromoItemDefinitionsIDs(CSteamID steamID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamInventory_RequestEligiblePromoItemDefinitionsIDs(CSteamGameServerAPIContext.GetSteamInventory(), steamID); + } + + /// + /// After handling a SteamInventoryEligiblePromoItemDefIDs_t call result, use this + /// function to pull out the list of item definition ids that the user can be + /// manually granted via the AddPromoItems() call. + /// + public static bool GetEligiblePromoItemDefinitionIDs(CSteamID steamID, SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize) { + InteropHelp.TestIfAvailableGameServer(); + if (pItemDefIDs != null && pItemDefIDs.Length != punItemDefIDsArraySize) { + throw new System.ArgumentException("pItemDefIDs must be the same size as punItemDefIDsArraySize!"); + } + return NativeMethods.ISteamInventory_GetEligiblePromoItemDefinitionIDs(CSteamGameServerAPIContext.GetSteamInventory(), steamID, pItemDefIDs, ref punItemDefIDsArraySize); + } + + /// + /// Starts the purchase process for the given item definitions. The callback SteamInventoryStartPurchaseResult_t + /// will be posted if Steam was able to initialize the transaction. + /// Once the purchase has been authorized and completed by the user, the callback SteamInventoryResultReady_t + /// will be posted. + /// + public static SteamAPICall_t StartPurchase(SteamItemDef_t[] pArrayItemDefs, uint[] punArrayQuantity, uint unArrayLength) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamInventory_StartPurchase(CSteamGameServerAPIContext.GetSteamInventory(), pArrayItemDefs, punArrayQuantity, unArrayLength); + } + + /// + /// Request current prices for all applicable item definitions + /// + public static SteamAPICall_t RequestPrices() { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamInventory_RequestPrices(CSteamGameServerAPIContext.GetSteamInventory()); + } + + /// + /// Returns the number of items with prices. Need to call RequestPrices() first. + /// + public static uint GetNumItemsWithPrices() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_GetNumItemsWithPrices(CSteamGameServerAPIContext.GetSteamInventory()); + } + + /// + /// Returns item definition ids and their prices in the user's local currency. + /// Need to call RequestPrices() first. + /// + public static bool GetItemsWithPrices(SteamItemDef_t[] pArrayItemDefs, ulong[] pCurrentPrices, ulong[] pBasePrices, uint unArrayLength) { + InteropHelp.TestIfAvailableGameServer(); + if (pArrayItemDefs != null && pArrayItemDefs.Length != unArrayLength) { + throw new System.ArgumentException("pArrayItemDefs must be the same size as unArrayLength!"); + } + if (pCurrentPrices != null && pCurrentPrices.Length != unArrayLength) { + throw new System.ArgumentException("pCurrentPrices must be the same size as unArrayLength!"); + } + if (pBasePrices != null && pBasePrices.Length != unArrayLength) { + throw new System.ArgumentException("pBasePrices must be the same size as unArrayLength!"); + } + return NativeMethods.ISteamInventory_GetItemsWithPrices(CSteamGameServerAPIContext.GetSteamInventory(), pArrayItemDefs, pCurrentPrices, pBasePrices, unArrayLength); + } + + /// + /// Retrieves the price for the item definition id + /// Returns false if there is no price stored for the item definition. + /// + public static bool GetItemPrice(SteamItemDef_t iDefinition, out ulong pCurrentPrice, out ulong pBasePrice) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_GetItemPrice(CSteamGameServerAPIContext.GetSteamInventory(), iDefinition, out pCurrentPrice, out pBasePrice); + } + + /// + /// Create a request to update properties on items + /// + public static SteamInventoryUpdateHandle_t StartUpdateProperties() { + InteropHelp.TestIfAvailableGameServer(); + return (SteamInventoryUpdateHandle_t)NativeMethods.ISteamInventory_StartUpdateProperties(CSteamGameServerAPIContext.GetSteamInventory()); + } + + /// + /// Remove the property on the item + /// + public static bool RemoveProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + return NativeMethods.ISteamInventory_RemoveProperty(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2); + } + } + + /// + /// Accessor methods to set properties on items + /// + public static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, string pchPropertyValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) + using (var pchPropertyValue2 = new InteropHelp.UTF8StringHandle(pchPropertyValue)) { + return NativeMethods.ISteamInventory_SetPropertyString(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, pchPropertyValue2); + } + } + + public static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, bool bValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + return NativeMethods.ISteamInventory_SetPropertyBool(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, bValue); + } + } + + public static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, long nValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + return NativeMethods.ISteamInventory_SetPropertyInt64(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, nValue); + } + } + + public static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, float flValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + return NativeMethods.ISteamInventory_SetPropertyFloat(CSteamGameServerAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, flValue); + } + } + + /// + /// Submit the update request by handle + /// + public static bool SubmitUpdateProperties(SteamInventoryUpdateHandle_t handle, out SteamInventoryResult_t pResultHandle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamInventory_SubmitUpdateProperties(CSteamGameServerAPIContext.GetSteamInventory(), handle, out pResultHandle); + } + + public static bool InspectItem(out SteamInventoryResult_t pResultHandle, string pchItemToken) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchItemToken2 = new InteropHelp.UTF8StringHandle(pchItemToken)) { + return NativeMethods.ISteamInventory_InspectItem(CSteamGameServerAPIContext.GetSteamInventory(), out pResultHandle, pchItemToken2); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverinventory.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverinventory.cs.meta new file mode 100644 index 0000000..052902e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverinventory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 10c74c5b7d1df524ab3ad296b9efe267 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworking.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworking.cs new file mode 100644 index 0000000..5a8f341 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworking.cs @@ -0,0 +1,270 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerNetworking { + /// + /// ////////////////////////////////////////////////////////////////////////////////////////// + /// UDP-style (connectionless) networking interface. These functions send messages using + /// an API organized around the destination. Reliable and unreliable messages are supported. + /// For a more TCP-style interface (meaning you have a connection handle), see the functions below. + /// Both interface styles can send both reliable and unreliable messages. + /// Automatically establishes NAT-traversing or Relay server connections + /// These APIs are deprecated, and may be removed in a future version of the Steamworks + /// SDK. See ISteamNetworkingMessages. + /// Sends a P2P packet to the specified user + /// UDP-like, unreliable and a max packet size of 1200 bytes + /// the first packet send may be delayed as the NAT-traversal code runs + /// if we can't get through to the user, an error will be posted via the callback P2PSessionConnectFail_t + /// see EP2PSend enum above for the descriptions of the different ways of sending packets + /// nChannel is a routing number you can use to help route message to different systems - you'll have to call ReadP2PPacket() + /// with the same channel number in order to retrieve the data on the other end + /// using different channels to talk to the same user will still use the same underlying p2p connection, saving on resources + /// + public static bool SendP2PPacket(CSteamID steamIDRemote, byte[] pubData, uint cubData, EP2PSend eP2PSendType, int nChannel = 0) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_SendP2PPacket(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote, pubData, cubData, eP2PSendType, nChannel); + } + + /// + /// returns true if any data is available for read, and the amount of data that will need to be read + /// + public static bool IsP2PPacketAvailable(out uint pcubMsgSize, int nChannel = 0) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_IsP2PPacketAvailable(CSteamGameServerAPIContext.GetSteamNetworking(), out pcubMsgSize, nChannel); + } + + /// + /// reads in a packet that has been sent from another user via SendP2PPacket() + /// returns the size of the message and the steamID of the user who sent it in the last two parameters + /// if the buffer passed in is too small, the message will be truncated + /// this call is not blocking, and will return false if no data is available + /// + public static bool ReadP2PPacket(byte[] pubDest, uint cubDest, out uint pcubMsgSize, out CSteamID psteamIDRemote, int nChannel = 0) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_ReadP2PPacket(CSteamGameServerAPIContext.GetSteamNetworking(), pubDest, cubDest, out pcubMsgSize, out psteamIDRemote, nChannel); + } + + /// + /// AcceptP2PSessionWithUser() should only be called in response to a P2PSessionRequest_t callback + /// P2PSessionRequest_t will be posted if another user tries to send you a packet that you haven't talked to yet + /// if you don't want to talk to the user, just ignore the request + /// if the user continues to send you packets, another P2PSessionRequest_t will be posted periodically + /// this may be called multiple times for a single user + /// (if you've called SendP2PPacket() on the other user, this implicitly accepts the session request) + /// + public static bool AcceptP2PSessionWithUser(CSteamID steamIDRemote) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_AcceptP2PSessionWithUser(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote); + } + + /// + /// call CloseP2PSessionWithUser() when you're done talking to a user, will free up resources under-the-hood + /// if the remote user tries to send data to you again, another P2PSessionRequest_t callback will be posted + /// + public static bool CloseP2PSessionWithUser(CSteamID steamIDRemote) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_CloseP2PSessionWithUser(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote); + } + + /// + /// call CloseP2PChannelWithUser() when you're done talking to a user on a specific channel. Once all channels + /// open channels to a user have been closed, the open session to the user will be closed and new data from this + /// user will trigger a P2PSessionRequest_t callback + /// + public static bool CloseP2PChannelWithUser(CSteamID steamIDRemote, int nChannel) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_CloseP2PChannelWithUser(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote, nChannel); + } + + /// + /// fills out P2PSessionState_t structure with details about the underlying connection to the user + /// should only needed for debugging purposes + /// returns false if no connection exists to the specified user + /// + public static bool GetP2PSessionState(CSteamID steamIDRemote, out P2PSessionState_t pConnectionState) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_GetP2PSessionState(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDRemote, out pConnectionState); + } + + /// + /// Allow P2P connections to fall back to being relayed through the Steam servers if a direct connection + /// or NAT-traversal cannot be established. Only applies to connections created after setting this value, + /// or to existing connections that need to automatically reconnect after this value is set. + /// P2P packet relay is allowed by default + /// NOTE: This function is deprecated and may be removed in a future version of the SDK. For + /// security purposes, we may decide to relay the traffic to certain peers, even if you pass false + /// to this function, to prevent revealing the client's IP address top another peer. + /// + public static bool AllowP2PPacketRelay(bool bAllow) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_AllowP2PPacketRelay(CSteamGameServerAPIContext.GetSteamNetworking(), bAllow); + } + + /// + /// ////////////////////////////////////////////////////////////////////////////////////////// + /// LISTEN / CONNECT connection-oriented interface functions + /// These functions are more like a client-server TCP API. One side is the "server" + /// and "listens" for incoming connections, which then must be "accepted." The "client" + /// initiates a connection by "connecting." Sending and receiving is done through a + /// connection handle. + /// For a more UDP-style interface, where you do not track connection handles but + /// simply send messages to a SteamID, use the UDP-style functions above. + /// Both methods can send both reliable and unreliable methods. + /// These APIs are deprecated, and may be removed in a future version of the Steamworks + /// SDK. See ISteamNetworkingSockets. + /// ////////////////////////////////////////////////////////////////////////////////////////// + /// creates a socket and listens others to connect + /// will trigger a SocketStatusCallback_t callback on another client connecting + /// nVirtualP2PPort is the unique ID that the client will connect to, in case you have multiple ports + /// this can usually just be 0 unless you want multiple sets of connections + /// unIP is the local IP address to bind to + /// pass in 0 if you just want the default local IP + /// unPort is the port to use + /// pass in 0 if you don't want users to be able to connect via IP/Port, but expect to be always peer-to-peer connections only + /// + public static SNetListenSocket_t CreateListenSocket(int nVirtualP2PPort, SteamIPAddress_t nIP, ushort nPort, bool bAllowUseOfPacketRelay) { + InteropHelp.TestIfAvailableGameServer(); + return (SNetListenSocket_t)NativeMethods.ISteamNetworking_CreateListenSocket(CSteamGameServerAPIContext.GetSteamNetworking(), nVirtualP2PPort, nIP, nPort, bAllowUseOfPacketRelay); + } + + /// + /// creates a socket and begin connection to a remote destination + /// can connect via a known steamID (client or game server), or directly to an IP + /// on success will trigger a SocketStatusCallback_t callback + /// on failure or timeout will trigger a SocketStatusCallback_t callback with a failure code in m_eSNetSocketState + /// + public static SNetSocket_t CreateP2PConnectionSocket(CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay) { + InteropHelp.TestIfAvailableGameServer(); + return (SNetSocket_t)NativeMethods.ISteamNetworking_CreateP2PConnectionSocket(CSteamGameServerAPIContext.GetSteamNetworking(), steamIDTarget, nVirtualPort, nTimeoutSec, bAllowUseOfPacketRelay); + } + + public static SNetSocket_t CreateConnectionSocket(SteamIPAddress_t nIP, ushort nPort, int nTimeoutSec) { + InteropHelp.TestIfAvailableGameServer(); + return (SNetSocket_t)NativeMethods.ISteamNetworking_CreateConnectionSocket(CSteamGameServerAPIContext.GetSteamNetworking(), nIP, nPort, nTimeoutSec); + } + + /// + /// disconnects the connection to the socket, if any, and invalidates the handle + /// any unread data on the socket will be thrown away + /// if bNotifyRemoteEnd is set, socket will not be completely destroyed until the remote end acknowledges the disconnect + /// + public static bool DestroySocket(SNetSocket_t hSocket, bool bNotifyRemoteEnd) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_DestroySocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, bNotifyRemoteEnd); + } + + /// + /// destroying a listen socket will automatically kill all the regular sockets generated from it + /// + public static bool DestroyListenSocket(SNetListenSocket_t hSocket, bool bNotifyRemoteEnd) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_DestroyListenSocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, bNotifyRemoteEnd); + } + + /// + /// sending data + /// must be a handle to a connected socket + /// data is all sent via UDP, and thus send sizes are limited to 1200 bytes; after this, many routers will start dropping packets + /// use the reliable flag with caution; although the resend rate is pretty aggressive, + /// it can still cause stalls in receiving data (like TCP) + /// + public static bool SendDataOnSocket(SNetSocket_t hSocket, byte[] pubData, uint cubData, bool bReliable) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_SendDataOnSocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, pubData, cubData, bReliable); + } + + /// + /// receiving data + /// returns false if there is no data remaining + /// fills out *pcubMsgSize with the size of the next message, in bytes + /// + public static bool IsDataAvailableOnSocket(SNetSocket_t hSocket, out uint pcubMsgSize) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_IsDataAvailableOnSocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, out pcubMsgSize); + } + + /// + /// fills in pubDest with the contents of the message + /// messages are always complete, of the same size as was sent (i.e. packetized, not streaming) + /// if *pcubMsgSize < cubDest, only partial data is written + /// returns false if no data is available + /// + public static bool RetrieveDataFromSocket(SNetSocket_t hSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_RetrieveDataFromSocket(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, pubDest, cubDest, out pcubMsgSize); + } + + /// + /// checks for data from any socket that has been connected off this listen socket + /// returns false if there is no data remaining + /// fills out *pcubMsgSize with the size of the next message, in bytes + /// fills out *phSocket with the socket that data is available on + /// + public static bool IsDataAvailable(SNetListenSocket_t hListenSocket, out uint pcubMsgSize, out SNetSocket_t phSocket) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_IsDataAvailable(CSteamGameServerAPIContext.GetSteamNetworking(), hListenSocket, out pcubMsgSize, out phSocket); + } + + /// + /// retrieves data from any socket that has been connected off this listen socket + /// fills in pubDest with the contents of the message + /// messages are always complete, of the same size as was sent (i.e. packetized, not streaming) + /// if *pcubMsgSize < cubDest, only partial data is written + /// returns false if no data is available + /// fills out *phSocket with the socket that data is available on + /// + public static bool RetrieveData(SNetListenSocket_t hListenSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize, out SNetSocket_t phSocket) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_RetrieveData(CSteamGameServerAPIContext.GetSteamNetworking(), hListenSocket, pubDest, cubDest, out pcubMsgSize, out phSocket); + } + + /// + /// returns information about the specified socket, filling out the contents of the pointers + /// + public static bool GetSocketInfo(SNetSocket_t hSocket, out CSteamID pSteamIDRemote, out int peSocketStatus, out SteamIPAddress_t punIPRemote, out ushort punPortRemote) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_GetSocketInfo(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket, out pSteamIDRemote, out peSocketStatus, out punIPRemote, out punPortRemote); + } + + /// + /// returns which local port the listen socket is bound to + /// *pnIP and *pnPort will be 0 if the socket is set to listen for P2P connections only + /// + public static bool GetListenSocketInfo(SNetListenSocket_t hListenSocket, out SteamIPAddress_t pnIP, out ushort pnPort) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_GetListenSocketInfo(CSteamGameServerAPIContext.GetSteamNetworking(), hListenSocket, out pnIP, out pnPort); + } + + /// + /// returns true to describe how the socket ended up connecting + /// + public static ESNetSocketConnectionType GetSocketConnectionType(SNetSocket_t hSocket) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_GetSocketConnectionType(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket); + } + + /// + /// max packet size, in bytes + /// + public static int GetMaxPacketSize(SNetSocket_t hSocket) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworking_GetMaxPacketSize(CSteamGameServerAPIContext.GetSteamNetworking(), hSocket); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworking.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworking.cs.meta new file mode 100644 index 0000000..1071e59 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb8e260012cb01949bdbff38c366d4d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingsockets.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingsockets.cs new file mode 100644 index 0000000..dacad4a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingsockets.cs @@ -0,0 +1,1111 @@ +#define STEAMNETWORKINGSOCKETS_ENABLE_SDR +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerNetworkingSockets { + /// + /// / Creates a "server" socket that listens for clients to connect to by + /// / calling ConnectByIPAddress, over ordinary UDP (IPv4 or IPv6) + /// / + /// / You must select a specific local port to listen on and set it + /// / the port field of the local address. + /// / + /// / Usually you will set the IP portion of the address to zero (SteamNetworkingIPAddr::Clear()). + /// / This means that you will not bind to any particular local interface (i.e. the same + /// / as INADDR_ANY in plain socket code). Furthermore, if possible the socket will be bound + /// / in "dual stack" mode, which means that it can accept both IPv4 and IPv6 client connections. + /// / If you really do wish to bind a particular interface, then set the local address to the + /// / appropriate IPv4 or IPv6 IP. + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// / + /// / When a client attempts to connect, a SteamNetConnectionStatusChangedCallback_t + /// / will be posted. The connection will be in the connecting state. + /// + public static HSteamListenSocket CreateListenSocketIP(ref SteamNetworkingIPAddr localAddress, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamListenSocket)NativeMethods.ISteamNetworkingSockets_CreateListenSocketIP(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), ref localAddress, nOptions, pOptions); + } + + /// + /// / Creates a connection and begins talking to a "server" over UDP at the + /// / given IPv4 or IPv6 address. The remote host must be listening with a + /// / matching call to CreateListenSocketIP on the specified port. + /// / + /// / A SteamNetConnectionStatusChangedCallback_t callback will be triggered when we start + /// / connecting, and then another one on either timeout or successful connection. + /// / + /// / If the server does not have any identity configured, then their network address + /// / will be the only identity in use. Or, the network host may provide a platform-specific + /// / identity with or without a valid certificate to authenticate that identity. (These + /// / details will be contained in the SteamNetConnectionStatusChangedCallback_t.) It's + /// / up to your application to decide whether to allow the connection. + /// / + /// / By default, all connections will get basic encryption sufficient to prevent + /// / casual eavesdropping. But note that without certificates (or a shared secret + /// / distributed through some other out-of-band mechanism), you don't have any + /// / way of knowing who is actually on the other end, and thus are vulnerable to + /// / man-in-the-middle attacks. + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamNetConnection ConnectByIPAddress(ref SteamNetworkingIPAddr address, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamNetConnection)NativeMethods.ISteamNetworkingSockets_ConnectByIPAddress(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), ref address, nOptions, pOptions); + } + + /// + /// / Like CreateListenSocketIP, but clients will connect using ConnectP2P. + /// / + /// / nLocalVirtualPort specifies how clients can connect to this socket using + /// / ConnectP2P. It's very common for applications to only have one listening socket; + /// / in that case, use zero. If you need to open multiple listen sockets and have clients + /// / be able to connect to one or the other, then nLocalVirtualPort should be a small + /// / integer (<1000) unique to each listen socket you create. + /// / + /// / If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess() + /// / when your app initializes. + /// / + /// / If you are listening on a dedicated servers in known data center, + /// / then you can listen using this function instead of CreateHostedDedicatedServerListenSocket, + /// / to allow clients to connect without a ticket. Any user that owns + /// / the app and is signed into Steam will be able to attempt to connect to + /// / your server. Also, a connection attempt may require the client to + /// / be connected to Steam, which is one more moving part that may fail. When + /// / tickets are used, then once a ticket is obtained, a client can connect to + /// / your server even if they got disconnected from Steam or Steam is offline. + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamListenSocket CreateListenSocketP2P(int nLocalVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamListenSocket)NativeMethods.ISteamNetworkingSockets_CreateListenSocketP2P(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), nLocalVirtualPort, nOptions, pOptions); + } + + /// + /// / Begin connecting to a peer that is identified using a platform-specific identifier. + /// / This uses the default rendezvous service, which depends on the platform and library + /// / configuration. (E.g. on Steam, it goes through the steam backend.) + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// / + /// / To use your own signaling service, see: + /// / - ConnectP2PCustomSignaling + /// / - k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling + /// + public static HSteamNetConnection ConnectP2P(ref SteamNetworkingIdentity identityRemote, int nRemoteVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamNetConnection)NativeMethods.ISteamNetworkingSockets_ConnectP2P(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), ref identityRemote, nRemoteVirtualPort, nOptions, pOptions); + } + + /// + /// / Accept an incoming connection that has been received on a listen socket. + /// / + /// / When a connection attempt is received (perhaps after a few basic handshake + /// / packets have been exchanged to prevent trivial spoofing), a connection interface + /// / object is created in the k_ESteamNetworkingConnectionState_Connecting state + /// / and a SteamNetConnectionStatusChangedCallback_t is posted. At this point, your + /// / application MUST either accept or close the connection. (It may not ignore it.) + /// / Accepting the connection will transition it either into the connected state, + /// / or the finding route state, depending on the connection type. + /// / + /// / You should take action within a second or two, because accepting the connection is + /// / what actually sends the reply notifying the client that they are connected. If you + /// / delay taking action, from the client's perspective it is the same as the network + /// / being unresponsive, and the client may timeout the connection attempt. In other + /// / words, the client cannot distinguish between a delay caused by network problems + /// / and a delay caused by the application. + /// / + /// / This means that if your application goes for more than a few seconds without + /// / processing callbacks (for example, while loading a map), then there is a chance + /// / that a client may attempt to connect in that interval and fail due to timeout. + /// / + /// / If the application does not respond to the connection attempt in a timely manner, + /// / and we stop receiving communication from the client, the connection attempt will + /// / be timed out locally, transitioning the connection to the + /// / k_ESteamNetworkingConnectionState_ProblemDetectedLocally state. The client may also + /// / close the connection before it is accepted, and a transition to the + /// / k_ESteamNetworkingConnectionState_ClosedByPeer is also possible depending the exact + /// / sequence of events. + /// / + /// / Returns k_EResultInvalidParam if the handle is invalid. + /// / Returns k_EResultInvalidState if the connection is not in the appropriate state. + /// / (Remember that the connection state could change in between the time that the + /// / notification being posted to the queue and when it is received by the application.) + /// / + /// / A note about connection configuration options. If you need to set any configuration + /// / options that are common to all connections accepted through a particular listen + /// / socket, consider setting the options on the listen socket, since such options are + /// / inherited automatically. If you really do need to set options that are connection + /// / specific, it is safe to set them on the connection before accepting the connection. + /// + public static EResult AcceptConnection(HSteamNetConnection hConn) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_AcceptConnection(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn); + } + + /// + /// / Disconnects from the remote host and invalidates the connection handle. + /// / Any unread data on the connection is discarded. + /// / + /// / nReason is an application defined code that will be received on the other + /// / end and recorded (when possible) in backend analytics. The value should + /// / come from a restricted range. (See ESteamNetConnectionEnd.) If you don't need + /// / to communicate any information to the remote host, and do not want analytics to + /// / be able to distinguish "normal" connection terminations from "exceptional" ones, + /// / You may pass zero, in which case the generic value of + /// / k_ESteamNetConnectionEnd_App_Generic will be used. + /// / + /// / pszDebug is an optional human-readable diagnostic string that will be received + /// / by the remote host and recorded (when possible) in backend analytics. + /// / + /// / If you wish to put the socket into a "linger" state, where an attempt is made to + /// / flush any remaining sent data, use bEnableLinger=true. Otherwise reliable data + /// / is not flushed. + /// / + /// / If the connection has already ended and you are just freeing up the + /// / connection interface, the reason code, debug string, and linger flag are + /// / ignored. + /// + public static bool CloseConnection(HSteamNetConnection hPeer, int nReason, string pszDebug, bool bEnableLinger) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszDebug2 = new InteropHelp.UTF8StringHandle(pszDebug)) { + return NativeMethods.ISteamNetworkingSockets_CloseConnection(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hPeer, nReason, pszDebug2, bEnableLinger); + } + } + + /// + /// / Destroy a listen socket. All the connections that were accepting on the listen + /// / socket are closed ungracefully. + /// + public static bool CloseListenSocket(HSteamListenSocket hSocket) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_CloseListenSocket(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hSocket); + } + + /// + /// / Set connection user data. the data is returned in the following places + /// / - You can query it using GetConnectionUserData. + /// / - The SteamNetworkingmessage_t structure. + /// / - The SteamNetConnectionInfo_t structure. + /// / (Which is a member of SteamNetConnectionStatusChangedCallback_t -- but see WARNINGS below!!!!) + /// / + /// / Do you need to set this atomically when the connection is created? + /// / See k_ESteamNetworkingConfig_ConnectionUserData. + /// / + /// / WARNING: Be *very careful* when using the value provided in callbacks structs. + /// / Callbacks are queued, and the value that you will receive in your + /// / callback is the userdata that was effective at the time the callback + /// / was queued. There are subtle race conditions that can hapen if you + /// / don't understand this! + /// / + /// / If any incoming messages for this connection are queued, the userdata + /// / field is updated, so that when when you receive messages (e.g. with + /// / ReceiveMessagesOnConnection), they will always have the very latest + /// / userdata. So the tricky race conditions that can happen with callbacks + /// / do not apply to retrieving messages. + /// / + /// / Returns false if the handle is invalid. + /// + public static bool SetConnectionUserData(HSteamNetConnection hPeer, long nUserData) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_SetConnectionUserData(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hPeer, nUserData); + } + + /// + /// / Fetch connection user data. Returns -1 if handle is invalid + /// / or if you haven't set any userdata on the connection. + /// + public static long GetConnectionUserData(HSteamNetConnection hPeer) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetConnectionUserData(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hPeer); + } + + /// + /// / Set a name for the connection, used mostly for debugging + /// + public static void SetConnectionName(HSteamNetConnection hPeer, string pszName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszName2 = new InteropHelp.UTF8StringHandle(pszName)) { + NativeMethods.ISteamNetworkingSockets_SetConnectionName(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hPeer, pszName2); + } + } + + /// + /// / Fetch connection name. Returns false if handle is invalid + /// + public static bool GetConnectionName(HSteamNetConnection hPeer, out string pszName, int nMaxLen) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pszName2 = Marshal.AllocHGlobal(nMaxLen); + bool ret = NativeMethods.ISteamNetworkingSockets_GetConnectionName(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hPeer, pszName2, nMaxLen); + pszName = ret ? InteropHelp.PtrToStringUTF8(pszName2) : null; + Marshal.FreeHGlobal(pszName2); + return ret; + } + + /// + /// / Send a message to the remote host on the specified connection. + /// / + /// / nSendFlags determines the delivery guarantees that will be provided, + /// / when data should be buffered, etc. E.g. k_nSteamNetworkingSend_Unreliable + /// / + /// / Note that the semantics we use for messages are not precisely + /// / the same as the semantics of a standard "stream" socket. + /// / (SOCK_STREAM) For an ordinary stream socket, the boundaries + /// / between chunks are not considered relevant, and the sizes of + /// / the chunks of data written will not necessarily match up to + /// / the sizes of the chunks that are returned by the reads on + /// / the other end. The remote host might read a partial chunk, + /// / or chunks might be coalesced. For the message semantics + /// / used here, however, the sizes WILL match. Each send call + /// / will match a successful read call on the remote host + /// / one-for-one. If you are porting existing stream-oriented + /// / code to the semantics of reliable messages, your code should + /// / work the same, since reliable message semantics are more + /// / strict than stream semantics. The only caveat is related to + /// / performance: there is per-message overhead to retain the + /// / message sizes, and so if your code sends many small chunks + /// / of data, performance will suffer. Any code based on stream + /// / sockets that does not write excessively small chunks will + /// / work without any changes. + /// / + /// / The pOutMessageNumber is an optional pointer to receive the + /// / message number assigned to the message, if sending was successful. + /// / + /// / Returns: + /// / - k_EResultInvalidParam: invalid connection handle, or the individual message is too big. + /// / (See k_cbMaxSteamNetworkingSocketsMessageSizeSend) + /// / - k_EResultInvalidState: connection is in an invalid state + /// / - k_EResultNoConnection: connection has ended + /// / - k_EResultIgnored: You used k_nSteamNetworkingSend_NoDelay, and the message was dropped because + /// / we were not ready to send it. + /// / - k_EResultLimitExceeded: there was already too much data queued to be sent. + /// / (See k_ESteamNetworkingConfig_SendBufferSize) + /// + public static EResult SendMessageToConnection(HSteamNetConnection hConn, IntPtr pData, uint cbData, int nSendFlags, out long pOutMessageNumber) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_SendMessageToConnection(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn, pData, cbData, nSendFlags, out pOutMessageNumber); + } + + /// + /// / Send one or more messages without copying the message payload. + /// / This is the most efficient way to send messages. To use this + /// / function, you must first allocate a message object using + /// / ISteamNetworkingUtils::AllocateMessage. (Do not declare one + /// / on the stack or allocate your own.) + /// / + /// / You should fill in the message payload. You can either let + /// / it allocate the buffer for you and then fill in the payload, + /// / or if you already have a buffer allocated, you can just point + /// / m_pData at your buffer and set the callback to the appropriate function + /// / to free it. Note that if you use your own buffer, it MUST remain valid + /// / until the callback is executed. And also note that your callback can be + /// / invoked at any time from any thread (perhaps even before SendMessages + /// / returns!), so it MUST be fast and threadsafe. + /// / + /// / You MUST also fill in: + /// / - m_conn - the handle of the connection to send the message to + /// / - m_nFlags - bitmask of k_nSteamNetworkingSend_xxx flags. + /// / + /// / All other fields are currently reserved and should not be modified. + /// / + /// / The library will take ownership of the message structures. They may + /// / be modified or become invalid at any time, so you must not read them + /// / after passing them to this function. + /// / + /// / pOutMessageNumberOrResult is an optional array that will receive, + /// / for each message, the message number that was assigned to the message + /// / if sending was successful. If sending failed, then a negative EResult + /// / value is placed into the array. For example, the array will hold + /// / -k_EResultInvalidState if the connection was in an invalid state. + /// / See ISteamNetworkingSockets::SendMessageToConnection for possible + /// / failure codes. + /// + public static void SendMessages(int nMessages, SteamNetworkingMessage_t[] pMessages, long[] pOutMessageNumberOrResult) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamNetworkingSockets_SendMessages(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), nMessages, pMessages, pOutMessageNumberOrResult); + } + + /// + /// / Flush any messages waiting on the Nagle timer and send them + /// / at the next transmission opportunity (often that means right now). + /// / + /// / If Nagle is enabled (it's on by default) then when calling + /// / SendMessageToConnection the message will be buffered, up to the Nagle time + /// / before being sent, to merge small messages into the same packet. + /// / (See k_ESteamNetworkingConfig_NagleTime) + /// / + /// / Returns: + /// / k_EResultInvalidParam: invalid connection handle + /// / k_EResultInvalidState: connection is in an invalid state + /// / k_EResultNoConnection: connection has ended + /// / k_EResultIgnored: We weren't (yet) connected, so this operation has no effect. + /// + public static EResult FlushMessagesOnConnection(HSteamNetConnection hConn) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_FlushMessagesOnConnection(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn); + } + + /// + /// / Fetch the next available message(s) from the connection, if any. + /// / Returns the number of messages returned into your array, up to nMaxMessages. + /// / If the connection handle is invalid, -1 is returned. + /// / + /// / The order of the messages returned in the array is relevant. + /// / Reliable messages will be received in the order they were sent (and with the + /// / same sizes --- see SendMessageToConnection for on this subtle difference from a stream socket). + /// / + /// / Unreliable messages may be dropped, or delivered out of order with respect to + /// / each other or with respect to reliable messages. The same unreliable message + /// / may be received multiple times. + /// / + /// / If any messages are returned, you MUST call SteamNetworkingMessage_t::Release() on each + /// / of them free up resources after you are done. It is safe to keep the object alive for + /// / a little while (put it into some queue, etc), and you may call Release() from any thread. + /// + public static int ReceiveMessagesOnConnection(HSteamNetConnection hConn, IntPtr[] ppOutMessages, int nMaxMessages) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_ReceiveMessagesOnConnection(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn, ppOutMessages, nMaxMessages); + } + + /// + /// / Returns basic information about the high-level state of the connection. + /// + public static bool GetConnectionInfo(HSteamNetConnection hConn, out SteamNetConnectionInfo_t pInfo) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetConnectionInfo(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn, out pInfo); + } + + /// + /// / Returns a small set of information about the real-time state of the connection + /// / and the queue status of each lane. + /// / + /// / - pStatus may be NULL if the information is not desired. (E.g. you are only interested + /// / in the lane information.) + /// / - On entry, nLanes specifies the length of the pLanes array. This may be 0 + /// / if you do not wish to receive any lane data. It's OK for this to be smaller than + /// / the total number of configured lanes. + /// / - pLanes points to an array that will receive lane-specific info. It can be NULL + /// / if this is not needed. + /// / + /// / Return value: + /// / - k_EResultNoConnection - connection handle is invalid or connection has been closed. + /// / - k_EResultInvalidParam - nLanes is bad + /// + public static EResult GetConnectionRealTimeStatus(HSteamNetConnection hConn, ref SteamNetConnectionRealTimeStatus_t pStatus, int nLanes, ref SteamNetConnectionRealTimeLaneStatus_t pLanes) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetConnectionRealTimeStatus(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn, ref pStatus, nLanes, ref pLanes); + } + + /// + /// / Returns detailed connection stats in text format. Useful + /// / for dumping to a log, etc. + /// / + /// / Returns: + /// / -1 failure (bad connection handle) + /// / 0 OK, your buffer was filled in and '\0'-terminated + /// / >0 Your buffer was either nullptr, or it was too small and the text got truncated. + /// / Try again with a buffer of at least N bytes. + /// + public static int GetDetailedConnectionStatus(HSteamNetConnection hConn, out string pszBuf, int cbBuf) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pszBuf2 = Marshal.AllocHGlobal(cbBuf); + int ret = NativeMethods.ISteamNetworkingSockets_GetDetailedConnectionStatus(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn, pszBuf2, cbBuf); + pszBuf = ret != -1 ? InteropHelp.PtrToStringUTF8(pszBuf2) : null; + Marshal.FreeHGlobal(pszBuf2); + return ret; + } + + /// + /// / Returns local IP and port that a listen socket created using CreateListenSocketIP is bound to. + /// / + /// / An IPv6 address of ::0 means "any IPv4 or IPv6" + /// / An IPv6 address of ::ffff:0000:0000 means "any IPv4" + /// + public static bool GetListenSocketAddress(HSteamListenSocket hSocket, out SteamNetworkingIPAddr address) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetListenSocketAddress(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hSocket, out address); + } + + /// + /// / Create a pair of connections that are talking to each other, e.g. a loopback connection. + /// / This is very useful for testing, or so that your client/server code can work the same + /// / even when you are running a local "server". + /// / + /// / The two connections will immediately be placed into the connected state, and no callbacks + /// / will be posted immediately. After this, if you close either connection, the other connection + /// / will receive a callback, exactly as if they were communicating over the network. You must + /// / close *both* sides in order to fully clean up the resources! + /// / + /// / By default, internal buffers are used, completely bypassing the network, the chopping up of + /// / messages into packets, encryption, copying the payload, etc. This means that loopback + /// / packets, by default, will not simulate lag or loss. Passing true for bUseNetworkLoopback will + /// / cause the socket pair to send packets through the local network loopback device (127.0.0.1) + /// / on ephemeral ports. Fake lag and loss are supported in this case, and CPU time is expended + /// / to encrypt and decrypt. + /// / + /// / If you wish to assign a specific identity to either connection, you may pass a particular + /// / identity. Otherwise, if you pass nullptr, the respective connection will assume a generic + /// / "localhost" identity. If you use real network loopback, this might be translated to the + /// / actual bound loopback port. Otherwise, the port will be zero. + /// + public static bool CreateSocketPair(out HSteamNetConnection pOutConnection1, out HSteamNetConnection pOutConnection2, bool bUseNetworkLoopback, ref SteamNetworkingIdentity pIdentity1, ref SteamNetworkingIdentity pIdentity2) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_CreateSocketPair(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), out pOutConnection1, out pOutConnection2, bUseNetworkLoopback, ref pIdentity1, ref pIdentity2); + } + + /// + /// / Configure multiple outbound messages streams ("lanes") on a connection, and + /// / control head-of-line blocking between them. Messages within a given lane + /// / are always sent in the order they are queued, but messages from different + /// / lanes may be sent out of order. Each lane has its own message number + /// / sequence. The first message sent on each lane will be assigned the number 1. + /// / + /// / Each lane has a "priority". Lower priority lanes will only be processed + /// / when all higher-priority lanes are empty. The magnitudes of the priority + /// / values are not relevant, only their sort order. Higher numeric values + /// / take priority over lower numeric values. + /// / + /// / Each lane also is assigned a weight, which controls the approximate proportion + /// / of the bandwidth that will be consumed by the lane, relative to other lanes + /// / of the same priority. (This is assuming the lane stays busy. An idle lane + /// / does not build up "credits" to be be spent once a message is queued.) + /// / This value is only meaningful as a proportion, relative to other lanes with + /// / the same priority. For lanes with different priorities, the strict priority + /// / order will prevail, and their weights relative to each other are not relevant. + /// / Thus, if a lane has a unique priority value, the weight value for that lane is + /// / not relevant. + /// / + /// / Example: 3 lanes, with priorities [ 0, 10, 10 ] and weights [ (NA), 20, 5 ]. + /// / Messages sent on the first will always be sent first, before messages in the + /// / other two lanes. Its weight value is irrelevant, since there are no other + /// / lanes with priority=0. The other two lanes will share bandwidth, with the second + /// / and third lanes sharing bandwidth using a ratio of approximately 4:1. + /// / (The weights [ NA, 4, 1 ] would be equivalent.) + /// / + /// / Notes: + /// / - At the time of this writing, some code has performance cost that is linear + /// / in the number of lanes, so keep the number of lanes to an absolute minimum. + /// / 3 or so is fine; >8 is a lot. The max number of lanes on Steam is 255, + /// / which is a very large number and not recommended! If you are compiling this + /// / library from source, see STEAMNETWORKINGSOCKETS_MAX_LANES.) + /// / - Lane priority values may be any int. Their absolute value is not relevant, + /// / only the order matters. + /// / - Weights must be positive, and due to implementation details, they are restricted + /// / to 16-bit values. The absolute magnitudes don't matter, just the proportions. + /// / - Messages sent on a lane index other than 0 have a small overhead on the wire, + /// / so for maximum wire efficiency, lane 0 should be the "most common" lane, regardless + /// / of priorities or weights. + /// / - A connection has a single lane by default. Calling this function with + /// / nNumLanes=1 is legal, but pointless, since the priority and weight values are + /// / irrelevant in that case. + /// / - You may reconfigure connection lanes at any time, however reducing the number of + /// / lanes is not allowed. + /// / - Reconfiguring lanes might restart any bandwidth sharing balancing. Usually you + /// / will call this function once, near the start of the connection, perhaps after + /// / exchanging a few messages. + /// / - To assign all lanes the same priority, you may use pLanePriorities=NULL. + /// / - If you wish all lanes with the same priority to share bandwidth equally (or + /// / if no two lanes have the same priority value, and thus priority values are + /// / irrelevant), you may use pLaneWeights=NULL + /// / - Priorities and weights determine the order that messages are SENT on the wire. + /// / There are NO GUARANTEES on the order that messages are RECEIVED! Due to packet + /// / loss, out-of-order delivery, and subtle details of packet serialization, messages + /// / might still be received slightly out-of-order! The *only* strong guarantee is that + /// / *reliable* messages on the *same lane* will be delivered in the order they are sent. + /// / - Each host configures the lanes for the packets they send; the lanes for the flow + /// / in one direction are completely unrelated to the lanes in the opposite direction. + /// / + /// / Return value: + /// / - k_EResultNoConnection - bad hConn + /// / - k_EResultInvalidParam - Invalid number of lanes, bad weights, or you tried to reduce the number of lanes + /// / - k_EResultInvalidState - Connection is already dead, etc + /// / + /// / See also: + /// / SteamNetworkingMessage_t::m_idxLane + /// + public static EResult ConfigureConnectionLanes(HSteamNetConnection hConn, int nNumLanes, out int pLanePriorities, out ushort pLaneWeights) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_ConfigureConnectionLanes(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn, nNumLanes, out pLanePriorities, out pLaneWeights); + } + + /// + /// Identity and authentication + /// / Get the identity assigned to this interface. + /// / E.g. on Steam, this is the user's SteamID, or for the gameserver interface, the SteamID assigned + /// / to the gameserver. Returns false and sets the result to an invalid identity if we don't know + /// / our identity yet. (E.g. GameServer has not logged in. On Steam, the user will know their SteamID + /// / even if they are not signed into Steam.) + /// + public static bool GetIdentity(out SteamNetworkingIdentity pIdentity) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetIdentity(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), out pIdentity); + } + + /// + /// / Indicate our desire to be ready participate in authenticated communications. + /// / If we are currently not ready, then steps will be taken to obtain the necessary + /// / certificates. (This includes a certificate for us, as well as any CA certificates + /// / needed to authenticate peers.) + /// / + /// / You can call this at program init time if you know that you are going to + /// / be making authenticated connections, so that we will be ready immediately when + /// / those connections are attempted. (Note that essentially all connections require + /// / authentication, with the exception of ordinary UDP connections with authentication + /// / disabled using k_ESteamNetworkingConfig_IP_AllowWithoutAuth.) If you don't call + /// / this function, we will wait until a feature is utilized that that necessitates + /// / these resources. + /// / + /// / You can also call this function to force a retry, if failure has occurred. + /// / Once we make an attempt and fail, we will not automatically retry. + /// / In this respect, the behavior of the system after trying and failing is the same + /// / as before the first attempt: attempting authenticated communication or calling + /// / this function will call the system to attempt to acquire the necessary resources. + /// / + /// / You can use GetAuthenticationStatus or listen for SteamNetAuthenticationStatus_t + /// / to monitor the status. + /// / + /// / Returns the current value that would be returned from GetAuthenticationStatus. + /// + public static ESteamNetworkingAvailability InitAuthentication() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_InitAuthentication(CSteamGameServerAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// / Query our readiness to participate in authenticated communications. A + /// / SteamNetAuthenticationStatus_t callback is posted any time this status changes, + /// / but you can use this function to query it at any time. + /// / + /// / The value of SteamNetAuthenticationStatus_t::m_eAvail is returned. If you only + /// / want this high level status, you can pass NULL for pDetails. If you want further + /// / details, pass non-NULL to receive them. + /// + public static ESteamNetworkingAvailability GetAuthenticationStatus(out SteamNetAuthenticationStatus_t pDetails) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetAuthenticationStatus(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), out pDetails); + } + + /// + /// Poll groups. A poll group is a set of connections that can be polled efficiently. + /// (In our API, to "poll" a connection means to retrieve all pending messages. We + /// actually don't have an API to "poll" the connection *state*, like BSD sockets.) + /// / Create a new poll group. + /// / + /// / You should destroy the poll group when you are done using DestroyPollGroup + /// + public static HSteamNetPollGroup CreatePollGroup() { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamNetPollGroup)NativeMethods.ISteamNetworkingSockets_CreatePollGroup(CSteamGameServerAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// / Destroy a poll group created with CreatePollGroup(). + /// / + /// / If there are any connections in the poll group, they are removed from the group, + /// / and left in a state where they are not part of any poll group. + /// / Returns false if passed an invalid poll group handle. + /// + public static bool DestroyPollGroup(HSteamNetPollGroup hPollGroup) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_DestroyPollGroup(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hPollGroup); + } + + /// + /// / Assign a connection to a poll group. Note that a connection may only belong to a + /// / single poll group. Adding a connection to a poll group implicitly removes it from + /// / any other poll group it is in. + /// / + /// / You can pass k_HSteamNetPollGroup_Invalid to remove a connection from its current + /// / poll group without adding it to a new poll group. + /// / + /// / If there are received messages currently pending on the connection, an attempt + /// / is made to add them to the queue of messages for the poll group in approximately + /// / the order that would have applied if the connection was already part of the poll + /// / group at the time that the messages were received. + /// / + /// / Returns false if the connection handle is invalid, or if the poll group handle + /// / is invalid (and not k_HSteamNetPollGroup_Invalid). + /// + public static bool SetConnectionPollGroup(HSteamNetConnection hConn, HSteamNetPollGroup hPollGroup) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_SetConnectionPollGroup(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn, hPollGroup); + } + + /// + /// / Same as ReceiveMessagesOnConnection, but will return the next messages available + /// / on any connection in the poll group. Examine SteamNetworkingMessage_t::m_conn + /// / to know which connection. (SteamNetworkingMessage_t::m_nConnUserData might also + /// / be useful.) + /// / + /// / Delivery order of messages among different connections will usually match the + /// / order that the last packet was received which completed the message. But this + /// / is not a strong guarantee, especially for packets received right as a connection + /// / is being assigned to poll group. + /// / + /// / Delivery order of messages on the same connection is well defined and the + /// / same guarantees are present as mentioned in ReceiveMessagesOnConnection. + /// / (But the messages are not grouped by connection, so they will not necessarily + /// / appear consecutively in the list; they may be interleaved with messages for + /// / other connections.) + /// + public static int ReceiveMessagesOnPollGroup(HSteamNetPollGroup hPollGroup, IntPtr[] ppOutMessages, int nMaxMessages) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_ReceiveMessagesOnPollGroup(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hPollGroup, ppOutMessages, nMaxMessages); + } + + /// + /// Clients connecting to dedicated servers hosted in a data center, + /// using tickets issued by your game coordinator. If you are not + /// issuing your own tickets to restrict who can attempt to connect + /// to your server, then you won't use these functions. + /// / Call this when you receive a ticket from your backend / matchmaking system. Puts the + /// / ticket into a persistent cache, and optionally returns the parsed ticket. + /// / + /// / See stamdatagram_ticketgen.h for more details. + /// + public static bool ReceivedRelayAuthTicket(IntPtr pvTicket, int cbTicket, out SteamDatagramRelayAuthTicket pOutParsedTicket) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_ReceivedRelayAuthTicket(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), pvTicket, cbTicket, out pOutParsedTicket); + } + + /// + /// / Search cache for a ticket to talk to the server on the specified virtual port. + /// / If found, returns the number of seconds until the ticket expires, and optionally + /// / the complete cracked ticket. Returns 0 if we don't have a ticket. + /// / + /// / Typically this is useful just to confirm that you have a ticket, before you + /// / call ConnectToHostedDedicatedServer to connect to the server. + /// + public static int FindRelayAuthTicketForServer(ref SteamNetworkingIdentity identityGameServer, int nRemoteVirtualPort, out SteamDatagramRelayAuthTicket pOutParsedTicket) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_FindRelayAuthTicketForServer(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), ref identityGameServer, nRemoteVirtualPort, out pOutParsedTicket); + } + + /// + /// / Client call to connect to a server hosted in a Valve data center, on the specified virtual + /// / port. You must have placed a ticket for this server into the cache, or else this connect + /// / attempt will fail! If you are not issuing your own tickets, then to connect to a dedicated + /// / server via SDR in auto-ticket mode, use ConnectP2P. (The server must be configured to allow + /// / this type of connection by listening using CreateListenSocketP2P.) + /// / + /// / You may wonder why tickets are stored in a cache, instead of simply being passed as an argument + /// / here. The reason is to make reconnection to a gameserver robust, even if the client computer loses + /// / connection to Steam or the central backend, or the app is restarted or crashes, etc. + /// / + /// / If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess() + /// / when your app initializes + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamNetConnection ConnectToHostedDedicatedServer(ref SteamNetworkingIdentity identityTarget, int nRemoteVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamNetConnection)NativeMethods.ISteamNetworkingSockets_ConnectToHostedDedicatedServer(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), ref identityTarget, nRemoteVirtualPort, nOptions, pOptions); + } + + /// + /// Servers hosted in data centers known to the Valve relay network + /// / Returns the value of the SDR_LISTEN_PORT environment variable. This + /// / is the UDP server your server will be listening on. This will + /// / configured automatically for you in production environments. + /// / + /// / In development, you'll need to set it yourself. See + /// / https://partner.steamgames.com/doc/api/ISteamNetworkingSockets + /// / for more information on how to configure dev environments. + /// + public static ushort GetHostedDedicatedServerPort() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetHostedDedicatedServerPort(CSteamGameServerAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// / Returns 0 if SDR_LISTEN_PORT is not set. Otherwise, returns the data center the server + /// / is running in. This will be k_SteamDatagramPOPID_dev in non-production environment. + /// + public static SteamNetworkingPOPID GetHostedDedicatedServerPOPID() { + InteropHelp.TestIfAvailableGameServer(); + return (SteamNetworkingPOPID)NativeMethods.ISteamNetworkingSockets_GetHostedDedicatedServerPOPID(CSteamGameServerAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// / Return info about the hosted server. This contains the PoPID of the server, + /// / and opaque routing information that can be used by the relays to send traffic + /// / to your server. + /// / + /// / You will need to send this information to your backend, and put it in tickets, + /// / so that the relays will know how to forward traffic from + /// / clients to your server. See SteamDatagramRelayAuthTicket for more info. + /// / + /// / Also, note that the routing information is contained in SteamDatagramGameCoordinatorServerLogin, + /// / so if possible, it's preferred to use GetGameCoordinatorServerLogin to send this info + /// / to your game coordinator service, and also login securely at the same time. + /// / + /// / On a successful exit, k_EResultOK is returned + /// / + /// / Unsuccessful exit: + /// / - Something other than k_EResultOK is returned. + /// / - k_EResultInvalidState: We are not configured to listen for SDR (SDR_LISTEN_SOCKET + /// / is not set.) + /// / - k_EResultPending: we do not (yet) have the authentication information needed. + /// / (See GetAuthenticationStatus.) If you use environment variables to pre-fetch + /// / the network config, this data should always be available immediately. + /// / - A non-localized diagnostic debug message will be placed in m_data that describes + /// / the cause of the failure. + /// / + /// / NOTE: The returned blob is not encrypted. Send it to your backend, but don't + /// / directly share it with clients. + /// + public static EResult GetHostedDedicatedServerAddress(out SteamDatagramHostedAddress pRouting) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetHostedDedicatedServerAddress(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), out pRouting); + } + + /// + /// / Create a listen socket on the specified virtual port. The physical UDP port to use + /// / will be determined by the SDR_LISTEN_PORT environment variable. If a UDP port is not + /// / configured, this call will fail. + /// / + /// / This call MUST be made through the SteamGameServerNetworkingSockets() interface. + /// / + /// / This function should be used when you are using the ticket generator library + /// / to issue your own tickets. Clients connecting to the server on this virtual + /// / port will need a ticket, and they must connect using ConnectToHostedDedicatedServer. + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamListenSocket CreateHostedDedicatedServerListenSocket(int nLocalVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamListenSocket)NativeMethods.ISteamNetworkingSockets_CreateHostedDedicatedServerListenSocket(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), nLocalVirtualPort, nOptions, pOptions); + } + + /// + /// / Generate an authentication blob that can be used to securely login with + /// / your backend, using SteamDatagram_ParseHostedServerLogin. (See + /// / steamdatagram_gamecoordinator.h) + /// / + /// / Before calling the function: + /// / - Populate the app data in pLoginInfo (m_cbAppData and m_appData). You can leave + /// / all other fields uninitialized. + /// / - *pcbSignedBlob contains the size of the buffer at pBlob. (It should be + /// / at least k_cbMaxSteamDatagramGameCoordinatorServerLoginSerialized.) + /// / + /// / On a successful exit: + /// / - k_EResultOK is returned + /// / - All of the remaining fields of pLoginInfo will be filled out. + /// / - *pcbSignedBlob contains the size of the serialized blob that has been + /// / placed into pBlob. + /// / + /// / Unsuccessful exit: + /// / - Something other than k_EResultOK is returned. + /// / - k_EResultNotLoggedOn: you are not logged in (yet) + /// / - See GetHostedDedicatedServerAddress for more potential failure return values. + /// / - A non-localized diagnostic debug message will be placed in pBlob that describes + /// / the cause of the failure. + /// / + /// / This works by signing the contents of the SteamDatagramGameCoordinatorServerLogin + /// / with the cert that is issued to this server. In dev environments, it's OK if you do + /// / not have a cert. (You will need to enable insecure dev login in SteamDatagram_ParseHostedServerLogin.) + /// / Otherwise, you will need a signed cert. + /// / + /// / NOTE: The routing blob returned here is not encrypted. Send it to your backend + /// / and don't share it directly with clients. + /// + public static EResult GetGameCoordinatorServerLogin(IntPtr pLoginInfo, out int pcbSignedBlob, IntPtr pBlob) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetGameCoordinatorServerLogin(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), pLoginInfo, out pcbSignedBlob, pBlob); + } + + /// + /// Relayed connections using custom signaling protocol + /// This is used if you have your own method of sending out-of-band + /// signaling / rendezvous messages through a mutually trusted channel. + /// / Create a P2P "client" connection that does signaling over a custom + /// / rendezvous/signaling channel. + /// / + /// / pSignaling points to a new object that you create just for this connection. + /// / It must stay valid until Release() is called. Once you pass the + /// / object to this function, it assumes ownership. Release() will be called + /// / from within the function call if the call fails. Furthermore, until Release() + /// / is called, you should be prepared for methods to be invoked on your + /// / object from any thread! You need to make sure your object is threadsafe! + /// / Furthermore, you should make sure that dispatching the methods is done + /// / as quickly as possible. + /// / + /// / This function will immediately construct a connection in the "connecting" + /// / state. Soon after (perhaps before this function returns, perhaps in another thread), + /// / the connection will begin sending signaling messages by calling + /// / ISteamNetworkingConnectionSignaling::SendSignal. + /// / + /// / When the remote peer accepts the connection (See + /// / ISteamNetworkingSignalingRecvContext::OnConnectRequest), + /// / it will begin sending signaling messages. When these messages are received, + /// / you can pass them to the connection using ReceivedP2PCustomSignal. + /// / + /// / If you know the identity of the peer that you expect to be on the other end, + /// / you can pass their identity to improve debug output or just detect bugs. + /// / If you don't know their identity yet, you can pass NULL, and their + /// / identity will be established in the connection handshake. + /// / + /// / If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess() + /// / when your app initializes + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamNetConnection ConnectP2PCustomSignaling(out ISteamNetworkingConnectionSignaling pSignaling, ref SteamNetworkingIdentity pPeerIdentity, int nRemoteVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamNetConnection)NativeMethods.ISteamNetworkingSockets_ConnectP2PCustomSignaling(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), out pSignaling, ref pPeerIdentity, nRemoteVirtualPort, nOptions, pOptions); + } + + /// + /// / Called when custom signaling has received a message. When your + /// / signaling channel receives a message, it should save off whatever + /// / routing information was in the envelope into the context object, + /// / and then pass the payload to this function. + /// / + /// / A few different things can happen next, depending on the message: + /// / + /// / - If the signal is associated with existing connection, it is dealt + /// / with immediately. If any replies need to be sent, they will be + /// / dispatched using the ISteamNetworkingConnectionSignaling + /// / associated with the connection. + /// / - If the message represents a connection request (and the request + /// / is not redundant for an existing connection), a new connection + /// / will be created, and ReceivedConnectRequest will be called on your + /// / context object to determine how to proceed. + /// / - Otherwise, the message is for a connection that does not + /// / exist (anymore). In this case, we *may* call SendRejectionReply + /// / on your context object. + /// / + /// / In any case, we will not save off pContext or access it after this + /// / function returns. + /// / + /// / Returns true if the message was parsed and dispatched without anything + /// / unusual or suspicious happening. Returns false if there was some problem + /// / with the message that prevented ordinary handling. (Debug output will + /// / usually have more information.) + /// / + /// / If you expect to be using relayed connections, then you probably want + /// / to call ISteamNetworkingUtils::InitRelayNetworkAccess() when your app initializes + /// + public static bool ReceivedP2PCustomSignal(IntPtr pMsg, int cbMsg, out ISteamNetworkingSignalingRecvContext pContext) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_ReceivedP2PCustomSignal(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), pMsg, cbMsg, out pContext); + } + + /// + /// Certificate provision by the application. On Steam, we normally handle all this automatically + /// and you will not need to use these advanced functions. + /// / Get blob that describes a certificate request. You can send this to your game coordinator. + /// / Upon entry, *pcbBlob should contain the size of the buffer. On successful exit, it will + /// / return the number of bytes that were populated. You can pass pBlob=NULL to query for the required + /// / size. (512 bytes is a conservative estimate.) + /// / + /// / Pass this blob to your game coordinator and call SteamDatagram_CreateCert. + /// + public static bool GetCertificateRequest(out int pcbBlob, IntPtr pBlob, out SteamNetworkingErrMsg errMsg) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetCertificateRequest(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), out pcbBlob, pBlob, out errMsg); + } + + /// + /// / Set the certificate. The certificate blob should be the output of + /// / SteamDatagram_CreateCert. + /// + public static bool SetCertificate(IntPtr pCertificate, int cbCertificate, out SteamNetworkingErrMsg errMsg) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_SetCertificate(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), pCertificate, cbCertificate, out errMsg); + } + + /// + /// / Reset the identity associated with this instance. + /// / Any open connections are closed. Any previous certificates, etc are discarded. + /// / You can pass a specific identity that you want to use, or you can pass NULL, + /// / in which case the identity will be invalid until you set it using SetCertificate + /// / + /// / NOTE: This function is not actually supported on Steam! It is included + /// / for use on other platforms where the active user can sign out and + /// / a new user can sign in. + /// + public static void ResetIdentity(ref SteamNetworkingIdentity pIdentity) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamNetworkingSockets_ResetIdentity(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), ref pIdentity); + } + + /// + /// Misc + /// / Invoke all callback functions queued for this interface. + /// / See k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, etc + /// / + /// / You don't need to call this if you are using Steam's callback dispatch + /// / mechanism (SteamAPI_RunCallbacks and SteamGameserver_RunCallbacks). + /// + public static void RunCallbacks() { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamNetworkingSockets_RunCallbacks(CSteamGameServerAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// "FakeIP" system. + /// A FakeIP is essentially a temporary, arbitrary identifier that + /// happens to be a valid IPv4 address. The purpose of this system is to make it + /// easy to integrate with existing code that identifies hosts using IPv4 addresses. + /// The FakeIP address will never actually be used to send or receive any packets + /// on the Internet, it is strictly an identifier. + /// FakeIP addresses are designed to (hopefully) pass through existing code as + /// transparently as possible, while conflicting with "real" addresses that might + /// be in use on networks (both the Internet and LANs) in the same code as little + /// as possible. At the time this comment is being written, they come from the + /// 169.254.0.0/16 range, and the port number will always be >1024. HOWEVER, + /// this is subject to change! Do not make assumptions about these addresses, + /// or your code might break in the future. In particular, you should use + /// functions such as ISteamNetworkingUtils::IsFakeIP to determine if an IP + /// address is a "fake" one used by this system. + /// / Begin asynchronous process of allocating a fake IPv4 address that other + /// / peers can use to contact us via P2P. IP addresses returned by this + /// / function are globally unique for a given appid. + /// / + /// / nNumPorts is the numbers of ports you wish to reserve. This is useful + /// / for the same reason that listening on multiple UDP ports is useful for + /// / different types of traffic. Because these allocations come from a global + /// / namespace, there is a relatively strict limit on the maximum number of + /// / ports you may request. (At the time of this writing, the limit is 4.) + /// / The Port assignments are *not* guaranteed to have any particular order + /// / or relationship! Do *not* assume they are contiguous, even though that + /// / may often occur in practice. + /// / + /// / Returns false if a request was already in progress, true if a new request + /// / was started. A SteamNetworkingFakeIPResult_t will be posted when the request + /// / completes. + /// / + /// / For gameservers, you *must* call this after initializing the SDK but before + /// / beginning login. Steam needs to know in advance that FakeIP will be used. + /// / Everywhere your public IP would normally appear (such as the server browser) will be + /// / replaced by the FakeIP, and the fake port at index 0. The request is actually queued + /// / until the logon completes, so you must not wait until the allocation completes + /// / before logging in. Except for trivial failures that can be detected locally + /// / (e.g. invalid parameter), a SteamNetworkingFakeIPResult_t callback (whether success or + /// / failure) will not be posted until after we have logged in. Furthermore, it is assumed + /// / that FakeIP allocation is essential for your application to function, and so failure + /// / will not be reported until *several* retries have been attempted. This process may + /// / last several minutes. It is *highly* recommended to treat failure as fatal. + /// / + /// / To communicate using a connection-oriented (TCP-style) API: + /// / - Server creates a listen socket using CreateListenSocketP2PFakeIP + /// / - Client connects using ConnectByIPAddress, passing in the FakeIP address. + /// / - The connection will behave mostly like a P2P connection. The identities + /// / that appear in SteamNetConnectionInfo_t will be the FakeIP identity until + /// / we know the real identity. Then it will be the real identity. If the + /// / SteamNetConnectionInfo_t::m_addrRemote is valid, it will be a real IPv4 + /// / address of a NAT-punched connection. Otherwise, it will not be valid. + /// / + /// / To communicate using an ad-hoc sendto/recv from (UDP-style) API, + /// / use CreateFakeUDPPort. + /// + public static bool BeginAsyncRequestFakeIP(int nNumPorts) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_BeginAsyncRequestFakeIP(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), nNumPorts); + } + + /// + /// / Return info about the FakeIP and port(s) that we have been assigned, + /// / if any. idxFirstPort is currently reserved and must be zero. + /// / Make sure and check SteamNetworkingFakeIPResult_t::m_eResult + /// + public static void GetFakeIP(int idxFirstPort, out SteamNetworkingFakeIPResult_t pInfo) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamNetworkingSockets_GetFakeIP(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), idxFirstPort, out pInfo); + } + + /// + /// / Create a listen socket that will listen for P2P connections sent + /// / to our FakeIP. A peer can initiate connections to this listen + /// / socket by calling ConnectByIPAddress. + /// / + /// / idxFakePort refers to the *index* of the fake port requested, + /// / not the actual port number. For example, pass 0 to refer to the + /// / first port in the reservation. You must call this only after calling + /// / BeginAsyncRequestFakeIP. However, you do not need to wait for the + /// / request to complete before creating the listen socket. + /// + public static HSteamListenSocket CreateListenSocketP2PFakeIP(int idxFakePort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableGameServer(); + return (HSteamListenSocket)NativeMethods.ISteamNetworkingSockets_CreateListenSocketP2PFakeIP(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), idxFakePort, nOptions, pOptions); + } + + /// + /// / If the connection was initiated using the "FakeIP" system, then we + /// / we can get an IP address for the remote host. If the remote host had + /// / a global FakeIP at the time the connection was established, this + /// / function will return that global IP. Otherwise, a FakeIP that is + /// / unique locally will be allocated from the local FakeIP address space, + /// / and that will be returned. + /// / + /// / The allocation of local FakeIPs attempts to assign addresses in + /// / a consistent manner. If multiple connections are made to the + /// / same remote host, they *probably* will return the same FakeIP. + /// / However, since the namespace is limited, this cannot be guaranteed. + /// / + /// / On failure, returns: + /// / - k_EResultInvalidParam: invalid connection handle + /// / - k_EResultIPNotFound: This connection wasn't made using FakeIP system + /// + public static EResult GetRemoteFakeIPForConnection(HSteamNetConnection hConn, out SteamNetworkingIPAddr pOutAddr) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_GetRemoteFakeIPForConnection(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), hConn, out pOutAddr); + } + + /// + /// / Get an interface that can be used like a UDP port to send/receive + /// / datagrams to a FakeIP address. This is intended to make it easy + /// / to port existing UDP-based code to take advantage of SDR. + /// / + /// / idxFakeServerPort refers to the *index* of the port allocated using + /// / BeginAsyncRequestFakeIP and is used to create "server" ports. You may + /// / call this before the allocation has completed. However, any attempts + /// / to send packets will fail until the allocation has succeeded. When + /// / the peer receives packets sent from this interface, the from address + /// / of the packet will be the globally-unique FakeIP. If you call this + /// / function multiple times and pass the same (nonnegative) fake port index, + /// / the same object will be returned, and this object is not reference counted. + /// / + /// / To create a "client" port (e.g. the equivalent of an ephemeral UDP port) + /// / pass -1. In this case, a distinct object will be returned for each call. + /// / When the peer receives packets sent from this interface, the peer will + /// / assign a FakeIP from its own locally-controlled namespace. + /// + public static IntPtr CreateFakeUDPPort(int idxFakeServerPort) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingSockets_CreateFakeUDPPort(CSteamGameServerAPIContext.GetSteamNetworkingSockets(), idxFakeServerPort); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingsockets.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingsockets.cs.meta new file mode 100644 index 0000000..85d200d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingsockets.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 175e632ae8fecc24e902fada780c39dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingutils.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingutils.cs new file mode 100644 index 0000000..0ec90d0 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingutils.cs @@ -0,0 +1,444 @@ +#define STEAMNETWORKINGSOCKETS_ENABLE_SDR +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerNetworkingUtils { + /// + /// Efficient message sending + /// / Allocate and initialize a message object. Usually the reason + /// / you call this is to pass it to ISteamNetworkingSockets::SendMessages. + /// / The returned object will have all of the relevant fields cleared to zero. + /// / + /// / Optionally you can also request that this system allocate space to + /// / hold the payload itself. If cbAllocateBuffer is nonzero, the system + /// / will allocate memory to hold a payload of at least cbAllocateBuffer bytes. + /// / m_pData will point to the allocated buffer, m_cbSize will be set to the + /// / size, and m_pfnFreeData will be set to the proper function to free up + /// / the buffer. + /// / + /// / If cbAllocateBuffer=0, then no buffer is allocated. m_pData will be NULL, + /// / m_cbSize will be zero, and m_pfnFreeData will be NULL. You will need to + /// / set each of these. + /// + public static IntPtr AllocateMessage(int cbAllocateBuffer) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_AllocateMessage(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), cbAllocateBuffer); + } + + /// + /// Access to Steam Datagram Relay (SDR) network + /// Initialization and status check + /// / If you know that you are going to be using the relay network (for example, + /// / because you anticipate making P2P connections), call this to initialize the + /// / relay network. If you do not call this, the initialization will + /// / be delayed until the first time you use a feature that requires access + /// / to the relay network, which will delay that first access. + /// / + /// / You can also call this to force a retry if the previous attempt has failed. + /// / Performing any action that requires access to the relay network will also + /// / trigger a retry, and so calling this function is never strictly necessary, + /// / but it can be useful to call it a program launch time, if access to the + /// / relay network is anticipated. + /// / + /// / Use GetRelayNetworkStatus or listen for SteamRelayNetworkStatus_t + /// / callbacks to know when initialization has completed. + /// / Typically initialization completes in a few seconds. + /// / + /// / Note: dedicated servers hosted in known data centers do *not* need + /// / to call this, since they do not make routing decisions. However, if + /// / the dedicated server will be using P2P functionality, it will act as + /// / a "client" and this should be called. + /// + public static void InitRelayNetworkAccess() { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamNetworkingUtils_InitRelayNetworkAccess(CSteamGameServerAPIContext.GetSteamNetworkingUtils()); + } + + /// + /// / Fetch current status of the relay network. + /// / + /// / SteamRelayNetworkStatus_t is also a callback. It will be triggered on + /// / both the user and gameserver interfaces any time the status changes, or + /// / ping measurement starts or stops. + /// / + /// / SteamRelayNetworkStatus_t::m_eAvail is returned. If you want + /// / more details, you can pass a non-NULL value. + /// + public static ESteamNetworkingAvailability GetRelayNetworkStatus(out SteamRelayNetworkStatus_t pDetails) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetRelayNetworkStatus(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), out pDetails); + } + + /// + /// "Ping location" functions + /// We use the ping times to the valve relays deployed worldwide to + /// generate a "marker" that describes the location of an Internet host. + /// Given two such markers, we can estimate the network latency between + /// two hosts, without sending any packets. The estimate is based on the + /// optimal route that is found through the Valve network. If you are + /// using the Valve network to carry the traffic, then this is precisely + /// the ping you want. If you are not, then the ping time will probably + /// still be a reasonable estimate. + /// This is extremely useful to select peers for matchmaking! + /// The markers can also be converted to a string, so they can be transmitted. + /// We have a separate library you can use on your app's matchmaking/coordinating + /// server to manipulate these objects. (See steamdatagram_gamecoordinator.h) + /// / Return location info for the current host. Returns the approximate + /// / age of the data, in seconds, or -1 if no data is available. + /// / + /// / It takes a few seconds to initialize access to the relay network. If + /// / you call this very soon after calling InitRelayNetworkAccess, + /// / the data may not be available yet. + /// / + /// / This always return the most up-to-date information we have available + /// / right now, even if we are in the middle of re-calculating ping times. + /// + public static float GetLocalPingLocation(out SteamNetworkPingLocation_t result) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetLocalPingLocation(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), out result); + } + + /// + /// / Estimate the round-trip latency between two arbitrary locations, in + /// / milliseconds. This is a conservative estimate, based on routing through + /// / the relay network. For most basic relayed connections, this ping time + /// / will be pretty accurate, since it will be based on the route likely to + /// / be actually used. + /// / + /// / If a direct IP route is used (perhaps via NAT traversal), then the route + /// / will be different, and the ping time might be better. Or it might actually + /// / be a bit worse! Standard IP routing is frequently suboptimal! + /// / + /// / But even in this case, the estimate obtained using this method is a + /// / reasonable upper bound on the ping time. (Also it has the advantage + /// / of returning immediately and not sending any packets.) + /// / + /// / In a few cases we might not able to estimate the route. In this case + /// / a negative value is returned. k_nSteamNetworkingPing_Failed means + /// / the reason was because of some networking difficulty. (Failure to + /// / ping, etc) k_nSteamNetworkingPing_Unknown is returned if we cannot + /// / currently answer the question for some other reason. + /// / + /// / Do you need to be able to do this from a backend/matchmaking server? + /// / You are looking for the "game coordinator" library. + /// + public static int EstimatePingTimeBetweenTwoLocations(ref SteamNetworkPingLocation_t location1, ref SteamNetworkPingLocation_t location2) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_EstimatePingTimeBetweenTwoLocations(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), ref location1, ref location2); + } + + /// + /// / Same as EstimatePingTime, but assumes that one location is the local host. + /// / This is a bit faster, especially if you need to calculate a bunch of + /// / these in a loop to find the fastest one. + /// / + /// / In rare cases this might return a slightly different estimate than combining + /// / GetLocalPingLocation with EstimatePingTimeBetweenTwoLocations. That's because + /// / this function uses a slightly more complete set of information about what + /// / route would be taken. + /// + public static int EstimatePingTimeFromLocalHost(ref SteamNetworkPingLocation_t remoteLocation) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_EstimatePingTimeFromLocalHost(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), ref remoteLocation); + } + + /// + /// / Convert a ping location into a text format suitable for sending over the wire. + /// / The format is a compact and human readable. However, it is subject to change + /// / so please do not parse it yourself. Your buffer must be at least + /// / k_cchMaxSteamNetworkingPingLocationString bytes. + /// + public static void ConvertPingLocationToString(ref SteamNetworkPingLocation_t location, out string pszBuf, int cchBufSize) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pszBuf2 = Marshal.AllocHGlobal(cchBufSize); + NativeMethods.ISteamNetworkingUtils_ConvertPingLocationToString(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), ref location, pszBuf2, cchBufSize); + pszBuf = InteropHelp.PtrToStringUTF8(pszBuf2); + Marshal.FreeHGlobal(pszBuf2); + } + + /// + /// / Parse back SteamNetworkPingLocation_t string. Returns false if we couldn't understand + /// / the string. + /// + public static bool ParsePingLocationString(string pszString, out SteamNetworkPingLocation_t result) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszString2 = new InteropHelp.UTF8StringHandle(pszString)) { + return NativeMethods.ISteamNetworkingUtils_ParsePingLocationString(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), pszString2, out result); + } + } + + /// + /// / Check if the ping data of sufficient recency is available, and if + /// / it's too old, start refreshing it. + /// / + /// / Please only call this function when you *really* do need to force an + /// / immediate refresh of the data. (For example, in response to a specific + /// / user input to refresh this information.) Don't call it "just in case", + /// / before every connection, etc. That will cause extra traffic to be sent + /// / for no benefit. The library will automatically refresh the information + /// / as needed. + /// / + /// / Returns true if sufficiently recent data is already available. + /// / + /// / Returns false if sufficiently recent data is not available. In this + /// / case, ping measurement is initiated, if it is not already active. + /// / (You cannot restart a measurement already in progress.) + /// / + /// / You can use GetRelayNetworkStatus or listen for SteamRelayNetworkStatus_t + /// / to know when ping measurement completes. + /// + public static bool CheckPingDataUpToDate(float flMaxAgeSeconds) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_CheckPingDataUpToDate(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), flMaxAgeSeconds); + } + + /// + /// List of Valve data centers, and ping times to them. This might + /// be useful to you if you are use our hosting, or just need to measure + /// latency to a cloud data center where we are running relays. + /// / Fetch ping time of best available relayed route from this host to + /// / the specified data center. + /// + public static int GetPingToDataCenter(SteamNetworkingPOPID popID, out SteamNetworkingPOPID pViaRelayPoP) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetPingToDataCenter(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), popID, out pViaRelayPoP); + } + + /// + /// / Get *direct* ping time to the relays at the data center. + /// + public static int GetDirectPingToPOP(SteamNetworkingPOPID popID) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetDirectPingToPOP(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), popID); + } + + /// + /// / Get number of network points of presence in the config + /// + public static int GetPOPCount() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetPOPCount(CSteamGameServerAPIContext.GetSteamNetworkingUtils()); + } + + /// + /// / Get list of all POP IDs. Returns the number of entries that were filled into + /// / your list. + /// + public static int GetPOPList(out SteamNetworkingPOPID list, int nListSz) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetPOPList(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), out list, nListSz); + } + + /// + /// Misc + /// / Fetch current timestamp. This timer has the following properties: + /// / + /// / - Monotonicity is guaranteed. + /// / - The initial value will be at least 24*3600*30*1e6, i.e. about + /// / 30 days worth of microseconds. In this way, the timestamp value of + /// / 0 will always be at least "30 days ago". Also, negative numbers + /// / will never be returned. + /// / - Wraparound / overflow is not a practical concern. + /// / + /// / If you are running under the debugger and stop the process, the clock + /// / might not advance the full wall clock time that has elapsed between + /// / calls. If the process is not blocked from normal operation, the + /// / timestamp values will track wall clock time, even if you don't call + /// / the function frequently. + /// / + /// / The value is only meaningful for this run of the process. Don't compare + /// / it to values obtained on another computer, or other runs of the same process. + /// + public static SteamNetworkingMicroseconds GetLocalTimestamp() { + InteropHelp.TestIfAvailableGameServer(); + return (SteamNetworkingMicroseconds)NativeMethods.ISteamNetworkingUtils_GetLocalTimestamp(CSteamGameServerAPIContext.GetSteamNetworkingUtils()); + } + + /// + /// / Set a function to receive network-related information that is useful for debugging. + /// / This can be very useful during development, but it can also be useful for troubleshooting + /// / problems with tech savvy end users. If you have a console or other log that customers + /// / can examine, these log messages can often be helpful to troubleshoot network issues. + /// / (Especially any warning/error messages.) + /// / + /// / The detail level indicates what message to invoke your callback on. Lower numeric + /// / value means more important, and the value you pass is the lowest priority (highest + /// / numeric value) you wish to receive callbacks for. + /// / + /// / The value here controls the detail level for most messages. You can control the + /// / detail level for various subsystems (perhaps only for certain connections) by + /// / adjusting the configuration values k_ESteamNetworkingConfig_LogLevel_Xxxxx. + /// / + /// / Except when debugging, you should only use k_ESteamNetworkingSocketsDebugOutputType_Msg + /// / or k_ESteamNetworkingSocketsDebugOutputType_Warning. For best performance, do NOT + /// / request a high detail level and then filter out messages in your callback. This incurs + /// / all of the expense of formatting the messages, which are then discarded. Setting a high + /// / priority value (low numeric value) here allows the library to avoid doing this work. + /// / + /// / IMPORTANT: This may be called from a service thread, while we own a mutex, etc. + /// / Your output function must be threadsafe and fast! Do not make any other + /// / Steamworks calls from within the handler. + /// + public static void SetDebugOutputFunction(ESteamNetworkingSocketsDebugOutputType eDetailLevel, FSteamNetworkingSocketsDebugOutput pfnFunc) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamNetworkingUtils_SetDebugOutputFunction(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), eDetailLevel, pfnFunc); + } + + /// + /// Fake IP + /// Useful for interfacing with code that assumes peers are identified using an IPv4 address + /// / Return true if an IPv4 address is one that might be used as a "fake" one. + /// / This function is fast; it just does some logical tests on the IP and does + /// / not need to do any lookup operations. + /// + public static bool IsFakeIPv4(uint nIPv4) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_IsFakeIPv4(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), nIPv4); + } + + public static ESteamNetworkingFakeIPType GetIPv4FakeIPType(uint nIPv4) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetIPv4FakeIPType(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), nIPv4); + } + + /// + /// / Get the real identity associated with a given FakeIP. + /// / + /// / On failure, returns: + /// / - k_EResultInvalidParam: the IP is not a FakeIP. + /// / - k_EResultNoMatch: we don't recognize that FakeIP and don't know the corresponding identity. + /// / + /// / FakeIP's used by active connections, or the FakeIPs assigned to local identities, + /// / will always work. FakeIPs for recently destroyed connections will continue to + /// / return results for a little while, but not forever. At some point, we will forget + /// / FakeIPs to save space. It's reasonably safe to assume that you can read back the + /// / real identity of a connection very soon after it is destroyed. But do not wait + /// / indefinitely. + /// + public static EResult GetRealIdentityForFakeIP(ref SteamNetworkingIPAddr fakeIP, out SteamNetworkingIdentity pOutRealIdentity) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetRealIdentityForFakeIP(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), ref fakeIP, out pOutRealIdentity); + } + + /// + /// Set and get configuration values, see ESteamNetworkingConfigValue for individual descriptions. + /// Shortcuts for common cases. (Implemented as inline functions below) + /// Set global callbacks. If you do not want to use Steam's callback dispatch mechanism and you + /// want to use the same callback on all (or most) listen sockets and connections, then + /// simply install these callbacks first thing, and you are good to go. + /// See ISteamNetworkingSockets::RunCallbacks + /// / Set a configuration value. + /// / - eValue: which value is being set + /// / - eScope: Onto what type of object are you applying the setting? + /// / - scopeArg: Which object you want to change? (Ignored for global scope). E.g. connection handle, listen socket handle, interface pointer, etc. + /// / - eDataType: What type of data is in the buffer at pValue? This must match the type of the variable exactly! + /// / - pArg: Value to set it to. You can pass NULL to remove a non-global setting at this scope, + /// / causing the value for that object to use global defaults. Or at global scope, passing NULL + /// / will reset any custom value and restore it to the system default. + /// / NOTE: When setting pointers (e.g. callback functions), do not pass the function pointer directly. + /// / Your argument should be a pointer to a function pointer. + /// + public static bool SetConfigValue(ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigScope eScopeType, IntPtr scopeObj, ESteamNetworkingConfigDataType eDataType, IntPtr pArg) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_SetConfigValue(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), eValue, eScopeType, scopeObj, eDataType, pArg); + } + + /// + /// / Set a configuration value, using a struct to pass the value. + /// / (This is just a convenience shortcut; see below for the implementation and + /// / a little insight into how SteamNetworkingConfigValue_t is used when + /// / setting config options during listen socket and connection creation.) + /// / Get a configuration value. + /// / - eValue: which value to fetch + /// / - eScopeType: query setting on what type of object + /// / - eScopeArg: the object to query the setting for + /// / - pOutDataType: If non-NULL, the data type of the value is returned. + /// / - pResult: Where to put the result. Pass NULL to query the required buffer size. (k_ESteamNetworkingGetConfigValue_BufferTooSmall will be returned.) + /// / - cbResult: IN: the size of your buffer. OUT: the number of bytes filled in or required. + /// + public static ESteamNetworkingGetConfigValueResult GetConfigValue(ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigScope eScopeType, IntPtr scopeObj, out ESteamNetworkingConfigDataType pOutDataType, IntPtr pResult, ref ulong cbResult) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_GetConfigValue(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), eValue, eScopeType, scopeObj, out pOutDataType, pResult, ref cbResult); + } + + /// + /// / Get info about a configuration value. Returns the name of the value, + /// / or NULL if the value doesn't exist. Other output parameters can be NULL + /// / if you do not need them. + /// + public static string GetConfigValueInfo(ESteamNetworkingConfigValue eValue, out ESteamNetworkingConfigDataType pOutDataType, out ESteamNetworkingConfigScope pOutScope) { + InteropHelp.TestIfAvailableGameServer(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamNetworkingUtils_GetConfigValueInfo(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), eValue, out pOutDataType, out pOutScope)); + } + + /// + /// / Iterate the list of all configuration values in the current environment that it might + /// / be possible to display or edit using a generic UI. To get the first iterable value, + /// / pass k_ESteamNetworkingConfig_Invalid. Returns k_ESteamNetworkingConfig_Invalid + /// / to signal end of list. + /// / + /// / The bEnumerateDevVars argument can be used to include "dev" vars. These are vars that + /// / are recommended to only be editable in "debug" or "dev" mode and typically should not be + /// / shown in a retail environment where a malicious local user might use this to cheat. + /// + public static ESteamNetworkingConfigValue IterateGenericEditableConfigValues(ESteamNetworkingConfigValue eCurrent, bool bEnumerateDevVars) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_IterateGenericEditableConfigValues(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), eCurrent, bEnumerateDevVars); + } + + /// + /// String conversions. You'll usually access these using the respective + /// inline methods. + /// + public static void SteamNetworkingIPAddr_ToString(ref SteamNetworkingIPAddr addr, out string buf, uint cbBuf, bool bWithPort) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr buf2 = Marshal.AllocHGlobal((int)cbBuf); + NativeMethods.ISteamNetworkingUtils_SteamNetworkingIPAddr_ToString(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), ref addr, buf2, cbBuf, bWithPort); + buf = InteropHelp.PtrToStringUTF8(buf2); + Marshal.FreeHGlobal(buf2); + } + + public static bool SteamNetworkingIPAddr_ParseString(out SteamNetworkingIPAddr pAddr, string pszStr) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszStr2 = new InteropHelp.UTF8StringHandle(pszStr)) { + return NativeMethods.ISteamNetworkingUtils_SteamNetworkingIPAddr_ParseString(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), out pAddr, pszStr2); + } + } + + public static ESteamNetworkingFakeIPType SteamNetworkingIPAddr_GetFakeIPType(ref SteamNetworkingIPAddr addr) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamNetworkingUtils_SteamNetworkingIPAddr_GetFakeIPType(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), ref addr); + } + + public static void SteamNetworkingIdentity_ToString(ref SteamNetworkingIdentity identity, out string buf, uint cbBuf) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr buf2 = Marshal.AllocHGlobal((int)cbBuf); + NativeMethods.ISteamNetworkingUtils_SteamNetworkingIdentity_ToString(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), ref identity, buf2, cbBuf); + buf = InteropHelp.PtrToStringUTF8(buf2); + Marshal.FreeHGlobal(buf2); + } + + public static bool SteamNetworkingIdentity_ParseString(out SteamNetworkingIdentity pIdentity, string pszStr) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszStr2 = new InteropHelp.UTF8StringHandle(pszStr)) { + return NativeMethods.ISteamNetworkingUtils_SteamNetworkingIdentity_ParseString(CSteamGameServerAPIContext.GetSteamNetworkingUtils(), out pIdentity, pszStr2); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingutils.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingutils.cs.meta new file mode 100644 index 0000000..9235e03 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingutils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fe59eea1e63d61e439d63c8e54f5cfdf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverstats.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverstats.cs new file mode 100644 index 0000000..9899f72 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverstats.cs @@ -0,0 +1,110 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerStats { + /// + /// downloads stats for the user + /// returns a GSStatsReceived_t callback when completed + /// if the user has no stats, GSStatsReceived_t.m_eResult will be set to k_EResultFail + /// these stats will only be auto-updated for clients playing on the server. For other + /// users you'll need to call RequestUserStats() again to refresh any data + /// + public static SteamAPICall_t RequestUserStats(CSteamID steamIDUser) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamGameServerStats_RequestUserStats(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser); + } + + /// + /// requests stat information for a user, usable after a successful call to RequestUserStats() + /// + public static bool GetUserStat(CSteamID steamIDUser, string pchName, out int pData) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamGameServerStats_GetUserStatInt32(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, out pData); + } + } + + public static bool GetUserStat(CSteamID steamIDUser, string pchName, out float pData) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamGameServerStats_GetUserStatFloat(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, out pData); + } + } + + public static bool GetUserAchievement(CSteamID steamIDUser, string pchName, out bool pbAchieved) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamGameServerStats_GetUserAchievement(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, out pbAchieved); + } + } + + /// + /// Set / update stats and achievements. + /// Note: These updates will work only on stats game servers are allowed to edit and only for + /// game servers that have been declared as officially controlled by the game creators. + /// Set the IP range of your official servers on the Steamworks page + /// + public static bool SetUserStat(CSteamID steamIDUser, string pchName, int nData) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamGameServerStats_SetUserStatInt32(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, nData); + } + } + + public static bool SetUserStat(CSteamID steamIDUser, string pchName, float fData) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamGameServerStats_SetUserStatFloat(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, fData); + } + } + + public static bool UpdateUserAvgRateStat(CSteamID steamIDUser, string pchName, float flCountThisSession, double dSessionLength) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamGameServerStats_UpdateUserAvgRateStat(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2, flCountThisSession, dSessionLength); + } + } + + public static bool SetUserAchievement(CSteamID steamIDUser, string pchName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamGameServerStats_SetUserAchievement(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2); + } + } + + public static bool ClearUserAchievement(CSteamID steamIDUser, string pchName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamGameServerStats_ClearUserAchievement(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser, pchName2); + } + } + + /// + /// Store the current data on the server, will get a GSStatsStored_t callback when set. + /// If the callback has a result of k_EResultInvalidParam, one or more stats + /// uploaded has been rejected, either because they broke constraints + /// or were out of date. In this case the server sends back updated values. + /// The stats should be re-iterated to keep in sync. + /// + public static SteamAPICall_t StoreUserStats(CSteamID steamIDUser) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamGameServerStats_StoreUserStats(CSteamGameServerAPIContext.GetSteamGameServerStats(), steamIDUser); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverstats.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverstats.cs.meta new file mode 100644 index 0000000..48bd888 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverstats.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07e74d4ac4bacfc489a00ec4e2a049a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverugc.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverugc.cs new file mode 100644 index 0000000..5f6a098 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverugc.cs @@ -0,0 +1,709 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerUGC { + /// + /// Query UGC associated with a user. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1. + /// + public static UGCQueryHandle_t CreateQueryUserUGCRequest(AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage) { + InteropHelp.TestIfAvailableGameServer(); + return (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryUserUGCRequest(CSteamGameServerAPIContext.GetSteamUGC(), unAccountID, eListType, eMatchingUGCType, eSortOrder, nCreatorAppID, nConsumerAppID, unPage); + } + + /// + /// Query for all matching UGC. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1. + /// + public static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage) { + InteropHelp.TestIfAvailableGameServer(); + return (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryAllUGCRequestPage(CSteamGameServerAPIContext.GetSteamUGC(), eQueryType, eMatchingeMatchingUGCTypeFileType, nCreatorAppID, nConsumerAppID, unPage); + } + + /// + /// Query for all matching UGC using the new deep paging interface. Creator app id or consumer app id must be valid and be set to the current running app. pchCursor should be set to NULL or "*" to get the first result set. + /// + public static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, string pchCursor = null) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchCursor2 = new InteropHelp.UTF8StringHandle(pchCursor)) { + return (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryAllUGCRequestCursor(CSteamGameServerAPIContext.GetSteamUGC(), eQueryType, eMatchingeMatchingUGCTypeFileType, nCreatorAppID, nConsumerAppID, pchCursor2); + } + } + + /// + /// Query for the details of the given published file ids (the RequestUGCDetails call is deprecated and replaced with this) + /// + public static UGCQueryHandle_t CreateQueryUGCDetailsRequest(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) { + InteropHelp.TestIfAvailableGameServer(); + return (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryUGCDetailsRequest(CSteamGameServerAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs); + } + + /// + /// Send the query to Steam + /// + public static SteamAPICall_t SendQueryUGCRequest(UGCQueryHandle_t handle) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_SendQueryUGCRequest(CSteamGameServerAPIContext.GetSteamUGC(), handle); + } + + /// + /// Retrieve an individual result after receiving the callback for querying UGC + /// + public static bool GetQueryUGCResult(UGCQueryHandle_t handle, uint index, out SteamUGCDetails_t pDetails) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetQueryUGCResult(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, out pDetails); + } + + public static uint GetQueryUGCNumTags(UGCQueryHandle_t handle, uint index) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetQueryUGCNumTags(CSteamGameServerAPIContext.GetSteamUGC(), handle, index); + } + + public static bool GetQueryUGCTag(UGCQueryHandle_t handle, uint index, uint indexTag, out string pchValue, uint cchValueSize) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, indexTag, pchValue2, cchValueSize); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + + public static bool GetQueryUGCTagDisplayName(UGCQueryHandle_t handle, uint index, uint indexTag, out string pchValue, uint cchValueSize) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCTagDisplayName(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, indexTag, pchValue2, cchValueSize); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + + public static bool GetQueryUGCPreviewURL(UGCQueryHandle_t handle, uint index, out string pchURL, uint cchURLSize) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchURL2 = Marshal.AllocHGlobal((int)cchURLSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCPreviewURL(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pchURL2, cchURLSize); + pchURL = ret ? InteropHelp.PtrToStringUTF8(pchURL2) : null; + Marshal.FreeHGlobal(pchURL2); + return ret; + } + + public static bool GetQueryUGCMetadata(UGCQueryHandle_t handle, uint index, out string pchMetadata, uint cchMetadatasize) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchMetadata2 = Marshal.AllocHGlobal((int)cchMetadatasize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCMetadata(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pchMetadata2, cchMetadatasize); + pchMetadata = ret ? InteropHelp.PtrToStringUTF8(pchMetadata2) : null; + Marshal.FreeHGlobal(pchMetadata2); + return ret; + } + + public static bool GetQueryUGCChildren(UGCQueryHandle_t handle, uint index, PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetQueryUGCChildren(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pvecPublishedFileID, cMaxEntries); + } + + public static bool GetQueryUGCStatistic(UGCQueryHandle_t handle, uint index, EItemStatistic eStatType, out ulong pStatValue) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetQueryUGCStatistic(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, eStatType, out pStatValue); + } + + public static uint GetQueryUGCNumAdditionalPreviews(UGCQueryHandle_t handle, uint index) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetQueryUGCNumAdditionalPreviews(CSteamGameServerAPIContext.GetSteamUGC(), handle, index); + } + + public static bool GetQueryUGCAdditionalPreview(UGCQueryHandle_t handle, uint index, uint previewIndex, out string pchURLOrVideoID, uint cchURLSize, out string pchOriginalFileName, uint cchOriginalFileNameSize, out EItemPreviewType pPreviewType) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchURLOrVideoID2 = Marshal.AllocHGlobal((int)cchURLSize); + IntPtr pchOriginalFileName2 = Marshal.AllocHGlobal((int)cchOriginalFileNameSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCAdditionalPreview(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, previewIndex, pchURLOrVideoID2, cchURLSize, pchOriginalFileName2, cchOriginalFileNameSize, out pPreviewType); + pchURLOrVideoID = ret ? InteropHelp.PtrToStringUTF8(pchURLOrVideoID2) : null; + Marshal.FreeHGlobal(pchURLOrVideoID2); + pchOriginalFileName = ret ? InteropHelp.PtrToStringUTF8(pchOriginalFileName2) : null; + Marshal.FreeHGlobal(pchOriginalFileName2); + return ret; + } + + public static uint GetQueryUGCNumKeyValueTags(UGCQueryHandle_t handle, uint index) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetQueryUGCNumKeyValueTags(CSteamGameServerAPIContext.GetSteamUGC(), handle, index); + } + + public static bool GetQueryUGCKeyValueTag(UGCQueryHandle_t handle, uint index, uint keyValueTagIndex, out string pchKey, uint cchKeySize, out string pchValue, uint cchValueSize) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchKey2 = Marshal.AllocHGlobal((int)cchKeySize); + IntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCKeyValueTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, keyValueTagIndex, pchKey2, cchKeySize, pchValue2, cchValueSize); + pchKey = ret ? InteropHelp.PtrToStringUTF8(pchKey2) : null; + Marshal.FreeHGlobal(pchKey2); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + + /// + /// Return the first value matching the pchKey. Note that a key may map to multiple values. Returns false if there was an error or no matching value was found. + /// + public static bool GetQueryUGCKeyValueTag(UGCQueryHandle_t handle, uint index, string pchKey, out string pchValue, uint cchValueSize) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + bool ret = NativeMethods.ISteamUGC_GetQueryFirstUGCKeyValueTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pchKey2, pchValue2, cchValueSize); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + } + + public static uint GetQueryUGCContentDescriptors(UGCQueryHandle_t handle, uint index, out EUGCContentDescriptorID pvecDescriptors, uint cMaxEntries) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetQueryUGCContentDescriptors(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, out pvecDescriptors, cMaxEntries); + } + + /// + /// Release the request to free up memory, after retrieving results + /// + public static bool ReleaseQueryUGCRequest(UGCQueryHandle_t handle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_ReleaseQueryUGCRequest(CSteamGameServerAPIContext.GetSteamUGC(), handle); + } + + /// + /// Options to set for querying UGC + /// + public static bool AddRequiredTag(UGCQueryHandle_t handle, string pTagName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pTagName2 = new InteropHelp.UTF8StringHandle(pTagName)) { + return NativeMethods.ISteamUGC_AddRequiredTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, pTagName2); + } + } + + /// + /// match any of the tags in this group + /// + public static bool AddRequiredTagGroup(UGCQueryHandle_t handle, System.Collections.Generic.IList pTagGroups) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_AddRequiredTagGroup(CSteamGameServerAPIContext.GetSteamUGC(), handle, new InteropHelp.SteamParamStringArray(pTagGroups)); + } + + public static bool AddExcludedTag(UGCQueryHandle_t handle, string pTagName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pTagName2 = new InteropHelp.UTF8StringHandle(pTagName)) { + return NativeMethods.ISteamUGC_AddExcludedTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, pTagName2); + } + } + + public static bool SetReturnOnlyIDs(UGCQueryHandle_t handle, bool bReturnOnlyIDs) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetReturnOnlyIDs(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnOnlyIDs); + } + + public static bool SetReturnKeyValueTags(UGCQueryHandle_t handle, bool bReturnKeyValueTags) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetReturnKeyValueTags(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnKeyValueTags); + } + + public static bool SetReturnLongDescription(UGCQueryHandle_t handle, bool bReturnLongDescription) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetReturnLongDescription(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnLongDescription); + } + + public static bool SetReturnMetadata(UGCQueryHandle_t handle, bool bReturnMetadata) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetReturnMetadata(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnMetadata); + } + + public static bool SetReturnChildren(UGCQueryHandle_t handle, bool bReturnChildren) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetReturnChildren(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnChildren); + } + + public static bool SetReturnAdditionalPreviews(UGCQueryHandle_t handle, bool bReturnAdditionalPreviews) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetReturnAdditionalPreviews(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnAdditionalPreviews); + } + + public static bool SetReturnTotalOnly(UGCQueryHandle_t handle, bool bReturnTotalOnly) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetReturnTotalOnly(CSteamGameServerAPIContext.GetSteamUGC(), handle, bReturnTotalOnly); + } + + public static bool SetReturnPlaytimeStats(UGCQueryHandle_t handle, uint unDays) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetReturnPlaytimeStats(CSteamGameServerAPIContext.GetSteamUGC(), handle, unDays); + } + + public static bool SetLanguage(UGCQueryHandle_t handle, string pchLanguage) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchLanguage2 = new InteropHelp.UTF8StringHandle(pchLanguage)) { + return NativeMethods.ISteamUGC_SetLanguage(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchLanguage2); + } + } + + public static bool SetAllowCachedResponse(UGCQueryHandle_t handle, uint unMaxAgeSeconds) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetAllowCachedResponse(CSteamGameServerAPIContext.GetSteamUGC(), handle, unMaxAgeSeconds); + } + + /// + /// Options only for querying user UGC + /// + public static bool SetCloudFileNameFilter(UGCQueryHandle_t handle, string pMatchCloudFileName) { + InteropHelp.TestIfAvailableGameServer(); + using (var pMatchCloudFileName2 = new InteropHelp.UTF8StringHandle(pMatchCloudFileName)) { + return NativeMethods.ISteamUGC_SetCloudFileNameFilter(CSteamGameServerAPIContext.GetSteamUGC(), handle, pMatchCloudFileName2); + } + } + + /// + /// Options only for querying all UGC + /// + public static bool SetMatchAnyTag(UGCQueryHandle_t handle, bool bMatchAnyTag) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetMatchAnyTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, bMatchAnyTag); + } + + public static bool SetSearchText(UGCQueryHandle_t handle, string pSearchText) { + InteropHelp.TestIfAvailableGameServer(); + using (var pSearchText2 = new InteropHelp.UTF8StringHandle(pSearchText)) { + return NativeMethods.ISteamUGC_SetSearchText(CSteamGameServerAPIContext.GetSteamUGC(), handle, pSearchText2); + } + } + + public static bool SetRankedByTrendDays(UGCQueryHandle_t handle, uint unDays) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetRankedByTrendDays(CSteamGameServerAPIContext.GetSteamUGC(), handle, unDays); + } + + public static bool SetTimeCreatedDateRange(UGCQueryHandle_t handle, uint rtStart, uint rtEnd) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetTimeCreatedDateRange(CSteamGameServerAPIContext.GetSteamUGC(), handle, rtStart, rtEnd); + } + + public static bool SetTimeUpdatedDateRange(UGCQueryHandle_t handle, uint rtStart, uint rtEnd) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetTimeUpdatedDateRange(CSteamGameServerAPIContext.GetSteamUGC(), handle, rtStart, rtEnd); + } + + public static bool AddRequiredKeyValueTag(UGCQueryHandle_t handle, string pKey, string pValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pKey2 = new InteropHelp.UTF8StringHandle(pKey)) + using (var pValue2 = new InteropHelp.UTF8StringHandle(pValue)) { + return NativeMethods.ISteamUGC_AddRequiredKeyValueTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, pKey2, pValue2); + } + } + + /// + /// DEPRECATED - Use CreateQueryUGCDetailsRequest call above instead! + /// + public static SteamAPICall_t RequestUGCDetails(PublishedFileId_t nPublishedFileID, uint unMaxAgeSeconds) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_RequestUGCDetails(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, unMaxAgeSeconds); + } + + /// + /// Steam Workshop Creator API + /// create new item for this app with no content attached yet + /// + public static SteamAPICall_t CreateItem(AppId_t nConsumerAppId, EWorkshopFileType eFileType) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_CreateItem(CSteamGameServerAPIContext.GetSteamUGC(), nConsumerAppId, eFileType); + } + + /// + /// start an UGC item update. Set changed properties before commiting update with CommitItemUpdate() + /// + public static UGCUpdateHandle_t StartItemUpdate(AppId_t nConsumerAppId, PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (UGCUpdateHandle_t)NativeMethods.ISteamUGC_StartItemUpdate(CSteamGameServerAPIContext.GetSteamUGC(), nConsumerAppId, nPublishedFileID); + } + + /// + /// change the title of an UGC item + /// + public static bool SetItemTitle(UGCUpdateHandle_t handle, string pchTitle) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle)) { + return NativeMethods.ISteamUGC_SetItemTitle(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchTitle2); + } + } + + /// + /// change the description of an UGC item + /// + public static bool SetItemDescription(UGCUpdateHandle_t handle, string pchDescription) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) { + return NativeMethods.ISteamUGC_SetItemDescription(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchDescription2); + } + } + + /// + /// specify the language of the title or description that will be set + /// + public static bool SetItemUpdateLanguage(UGCUpdateHandle_t handle, string pchLanguage) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchLanguage2 = new InteropHelp.UTF8StringHandle(pchLanguage)) { + return NativeMethods.ISteamUGC_SetItemUpdateLanguage(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchLanguage2); + } + } + + /// + /// change the metadata of an UGC item (max = k_cchDeveloperMetadataMax) + /// + public static bool SetItemMetadata(UGCUpdateHandle_t handle, string pchMetaData) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchMetaData2 = new InteropHelp.UTF8StringHandle(pchMetaData)) { + return NativeMethods.ISteamUGC_SetItemMetadata(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchMetaData2); + } + } + + /// + /// change the visibility of an UGC item + /// + public static bool SetItemVisibility(UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility eVisibility) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetItemVisibility(CSteamGameServerAPIContext.GetSteamUGC(), handle, eVisibility); + } + + /// + /// change the tags of an UGC item + /// + public static bool SetItemTags(UGCUpdateHandle_t updateHandle, System.Collections.Generic.IList pTags) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetItemTags(CSteamGameServerAPIContext.GetSteamUGC(), updateHandle, new InteropHelp.SteamParamStringArray(pTags)); + } + + /// + /// update item content from this local folder + /// + public static bool SetItemContent(UGCUpdateHandle_t handle, string pszContentFolder) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszContentFolder2 = new InteropHelp.UTF8StringHandle(pszContentFolder)) { + return NativeMethods.ISteamUGC_SetItemContent(CSteamGameServerAPIContext.GetSteamUGC(), handle, pszContentFolder2); + } + } + + /// + /// change preview image file for this item. pszPreviewFile points to local image file, which must be under 1MB in size + /// + public static bool SetItemPreview(UGCUpdateHandle_t handle, string pszPreviewFile) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) { + return NativeMethods.ISteamUGC_SetItemPreview(CSteamGameServerAPIContext.GetSteamUGC(), handle, pszPreviewFile2); + } + } + + /// + /// use legacy upload for a single small file. The parameter to SetItemContent() should either be a directory with one file or the full path to the file. The file must also be less than 10MB in size. + /// + public static bool SetAllowLegacyUpload(UGCUpdateHandle_t handle, bool bAllowLegacyUpload) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_SetAllowLegacyUpload(CSteamGameServerAPIContext.GetSteamUGC(), handle, bAllowLegacyUpload); + } + + /// + /// remove all existing key-value tags (you can add new ones via the AddItemKeyValueTag function) + /// + public static bool RemoveAllItemKeyValueTags(UGCUpdateHandle_t handle) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_RemoveAllItemKeyValueTags(CSteamGameServerAPIContext.GetSteamUGC(), handle); + } + + /// + /// remove any existing key-value tags with the specified key + /// + public static bool RemoveItemKeyValueTags(UGCUpdateHandle_t handle, string pchKey) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + return NativeMethods.ISteamUGC_RemoveItemKeyValueTags(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchKey2); + } + } + + /// + /// add new key-value tags for the item. Note that there can be multiple values for a tag. + /// + public static bool AddItemKeyValueTag(UGCUpdateHandle_t handle, string pchKey, string pchValue) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) + using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) { + return NativeMethods.ISteamUGC_AddItemKeyValueTag(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchKey2, pchValue2); + } + } + + /// + /// add preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size + /// + public static bool AddItemPreviewFile(UGCUpdateHandle_t handle, string pszPreviewFile, EItemPreviewType type) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) { + return NativeMethods.ISteamUGC_AddItemPreviewFile(CSteamGameServerAPIContext.GetSteamUGC(), handle, pszPreviewFile2, type); + } + } + + /// + /// add preview video for this item + /// + public static bool AddItemPreviewVideo(UGCUpdateHandle_t handle, string pszVideoID) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszVideoID2 = new InteropHelp.UTF8StringHandle(pszVideoID)) { + return NativeMethods.ISteamUGC_AddItemPreviewVideo(CSteamGameServerAPIContext.GetSteamUGC(), handle, pszVideoID2); + } + } + + /// + /// updates an existing preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size + /// + public static bool UpdateItemPreviewFile(UGCUpdateHandle_t handle, uint index, string pszPreviewFile) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) { + return NativeMethods.ISteamUGC_UpdateItemPreviewFile(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pszPreviewFile2); + } + } + + /// + /// updates an existing preview video for this item + /// + public static bool UpdateItemPreviewVideo(UGCUpdateHandle_t handle, uint index, string pszVideoID) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszVideoID2 = new InteropHelp.UTF8StringHandle(pszVideoID)) { + return NativeMethods.ISteamUGC_UpdateItemPreviewVideo(CSteamGameServerAPIContext.GetSteamUGC(), handle, index, pszVideoID2); + } + } + + /// + /// remove a preview by index starting at 0 (previews are sorted) + /// + public static bool RemoveItemPreview(UGCUpdateHandle_t handle, uint index) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_RemoveItemPreview(CSteamGameServerAPIContext.GetSteamUGC(), handle, index); + } + + public static bool AddContentDescriptor(UGCUpdateHandle_t handle, EUGCContentDescriptorID descid) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_AddContentDescriptor(CSteamGameServerAPIContext.GetSteamUGC(), handle, descid); + } + + public static bool RemoveContentDescriptor(UGCUpdateHandle_t handle, EUGCContentDescriptorID descid) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_RemoveContentDescriptor(CSteamGameServerAPIContext.GetSteamUGC(), handle, descid); + } + + /// + /// commit update process started with StartItemUpdate() + /// + public static SteamAPICall_t SubmitItemUpdate(UGCUpdateHandle_t handle, string pchChangeNote) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchChangeNote2 = new InteropHelp.UTF8StringHandle(pchChangeNote)) { + return (SteamAPICall_t)NativeMethods.ISteamUGC_SubmitItemUpdate(CSteamGameServerAPIContext.GetSteamUGC(), handle, pchChangeNote2); + } + } + + public static EItemUpdateStatus GetItemUpdateProgress(UGCUpdateHandle_t handle, out ulong punBytesProcessed, out ulong punBytesTotal) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetItemUpdateProgress(CSteamGameServerAPIContext.GetSteamUGC(), handle, out punBytesProcessed, out punBytesTotal); + } + + /// + /// Steam Workshop Consumer API + /// + public static SteamAPICall_t SetUserItemVote(PublishedFileId_t nPublishedFileID, bool bVoteUp) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_SetUserItemVote(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, bVoteUp); + } + + public static SteamAPICall_t GetUserItemVote(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_GetUserItemVote(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID); + } + + public static SteamAPICall_t AddItemToFavorites(AppId_t nAppId, PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_AddItemToFavorites(CSteamGameServerAPIContext.GetSteamUGC(), nAppId, nPublishedFileID); + } + + public static SteamAPICall_t RemoveItemFromFavorites(AppId_t nAppId, PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveItemFromFavorites(CSteamGameServerAPIContext.GetSteamUGC(), nAppId, nPublishedFileID); + } + + /// + /// subscribe to this item, will be installed ASAP + /// + public static SteamAPICall_t SubscribeItem(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_SubscribeItem(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// unsubscribe from this item, will be uninstalled after game quits + /// + public static SteamAPICall_t UnsubscribeItem(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_UnsubscribeItem(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// number of subscribed items + /// + public static uint GetNumSubscribedItems() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetNumSubscribedItems(CSteamGameServerAPIContext.GetSteamUGC()); + } + + /// + /// all subscribed item PublishFileIDs + /// + public static uint GetSubscribedItems(PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetSubscribedItems(CSteamGameServerAPIContext.GetSteamUGC(), pvecPublishedFileID, cMaxEntries); + } + + /// + /// get EItemState flags about item on this client + /// + public static uint GetItemState(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetItemState(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// get info about currently installed content on disc for items that have k_EItemStateInstalled set + /// if k_EItemStateLegacyItem is set, pchFolder contains the path to the legacy file itself (not a folder) + /// + public static bool GetItemInstallInfo(PublishedFileId_t nPublishedFileID, out ulong punSizeOnDisk, out string pchFolder, uint cchFolderSize, out uint punTimeStamp) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchFolder2 = Marshal.AllocHGlobal((int)cchFolderSize); + bool ret = NativeMethods.ISteamUGC_GetItemInstallInfo(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, out punSizeOnDisk, pchFolder2, cchFolderSize, out punTimeStamp); + pchFolder = ret ? InteropHelp.PtrToStringUTF8(pchFolder2) : null; + Marshal.FreeHGlobal(pchFolder2); + return ret; + } + + /// + /// get info about pending update for items that have k_EItemStateNeedsUpdate set. punBytesTotal will be valid after download started once + /// + public static bool GetItemDownloadInfo(PublishedFileId_t nPublishedFileID, out ulong punBytesDownloaded, out ulong punBytesTotal) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_GetItemDownloadInfo(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, out punBytesDownloaded, out punBytesTotal); + } + + /// + /// download new or update already installed item. If function returns true, wait for DownloadItemResult_t. If the item is already installed, + /// then files on disk should not be used until callback received. If item is not subscribed to, it will be cached for some time. + /// If bHighPriority is set, any other item download will be suspended and this item downloaded ASAP. + /// + public static bool DownloadItem(PublishedFileId_t nPublishedFileID, bool bHighPriority) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_DownloadItem(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, bHighPriority); + } + + /// + /// game servers can set a specific workshop folder before issuing any UGC commands. + /// This is helpful if you want to support multiple game servers running out of the same install folder + /// + public static bool BInitWorkshopForGameServer(DepotId_t unWorkshopDepotID, string pszFolder) { + InteropHelp.TestIfAvailableGameServer(); + using (var pszFolder2 = new InteropHelp.UTF8StringHandle(pszFolder)) { + return NativeMethods.ISteamUGC_BInitWorkshopForGameServer(CSteamGameServerAPIContext.GetSteamUGC(), unWorkshopDepotID, pszFolder2); + } + } + + /// + /// SuspendDownloads( true ) will suspend all workshop downloads until SuspendDownloads( false ) is called or the game ends + /// + public static void SuspendDownloads(bool bSuspend) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamUGC_SuspendDownloads(CSteamGameServerAPIContext.GetSteamUGC(), bSuspend); + } + + /// + /// usage tracking + /// + public static SteamAPICall_t StartPlaytimeTracking(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_StartPlaytimeTracking(CSteamGameServerAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs); + } + + public static SteamAPICall_t StopPlaytimeTracking(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_StopPlaytimeTracking(CSteamGameServerAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs); + } + + public static SteamAPICall_t StopPlaytimeTrackingForAllItems() { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_StopPlaytimeTrackingForAllItems(CSteamGameServerAPIContext.GetSteamUGC()); + } + + /// + /// parent-child relationship or dependency management + /// + public static SteamAPICall_t AddDependency(PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_AddDependency(CSteamGameServerAPIContext.GetSteamUGC(), nParentPublishedFileID, nChildPublishedFileID); + } + + public static SteamAPICall_t RemoveDependency(PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveDependency(CSteamGameServerAPIContext.GetSteamUGC(), nParentPublishedFileID, nChildPublishedFileID); + } + + /// + /// add/remove app dependence/requirements (usually DLC) + /// + public static SteamAPICall_t AddAppDependency(PublishedFileId_t nPublishedFileID, AppId_t nAppID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_AddAppDependency(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, nAppID); + } + + public static SteamAPICall_t RemoveAppDependency(PublishedFileId_t nPublishedFileID, AppId_t nAppID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveAppDependency(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID, nAppID); + } + + /// + /// request app dependencies. note that whatever callback you register for GetAppDependenciesResult_t may be called multiple times + /// until all app dependencies have been returned + /// + public static SteamAPICall_t GetAppDependencies(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_GetAppDependencies(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// delete the item without prompting the user + /// + public static SteamAPICall_t DeleteItem(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_DeleteItem(CSteamGameServerAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// Show the app's latest Workshop EULA to the user in an overlay window, where they can accept it or not + /// + public static bool ShowWorkshopEULA() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUGC_ShowWorkshopEULA(CSteamGameServerAPIContext.GetSteamUGC()); + } + + /// + /// Retrieve information related to the user's acceptance or not of the app's specific Workshop EULA + /// + public static SteamAPICall_t GetWorkshopEULAStatus() { + InteropHelp.TestIfAvailableGameServer(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_GetWorkshopEULAStatus(CSteamGameServerAPIContext.GetSteamUGC()); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverugc.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverugc.cs.meta new file mode 100644 index 0000000..67ed663 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverugc.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d9d587bbccfa08f44bce4b14c0826e27 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverutils.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverutils.cs new file mode 100644 index 0000000..bfd7e52 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverutils.cs @@ -0,0 +1,356 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamGameServerUtils { + /// + /// return the number of seconds since the user + /// + public static uint GetSecondsSinceAppActive() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetSecondsSinceAppActive(CSteamGameServerAPIContext.GetSteamUtils()); + } + + public static uint GetSecondsSinceComputerActive() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetSecondsSinceComputerActive(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// the universe this client is connecting to + /// + public static EUniverse GetConnectedUniverse() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetConnectedUniverse(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Steam server time. Number of seconds since January 1, 1970, GMT (i.e unix time) + /// + public static uint GetServerRealTime() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetServerRealTime(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via an IP-to-location database) + /// e.g "US" or "UK". + /// + public static string GetIPCountry() { + InteropHelp.TestIfAvailableGameServer(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUtils_GetIPCountry(CSteamGameServerAPIContext.GetSteamUtils())); + } + + /// + /// returns true if the image exists, and valid sizes were filled out + /// + public static bool GetImageSize(int iImage, out uint pnWidth, out uint pnHeight) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetImageSize(CSteamGameServerAPIContext.GetSteamUtils(), iImage, out pnWidth, out pnHeight); + } + + /// + /// returns true if the image exists, and the buffer was successfully filled out + /// results are returned in RGBA format + /// the destination buffer size should be 4 * height * width * sizeof(char) + /// + public static bool GetImageRGBA(int iImage, byte[] pubDest, int nDestBufferSize) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetImageRGBA(CSteamGameServerAPIContext.GetSteamUtils(), iImage, pubDest, nDestBufferSize); + } + + /// + /// return the amount of battery power left in the current system in % [0..100], 255 for being on AC power + /// + public static byte GetCurrentBatteryPower() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetCurrentBatteryPower(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// returns the appID of the current process + /// + public static AppId_t GetAppID() { + InteropHelp.TestIfAvailableGameServer(); + return (AppId_t)NativeMethods.ISteamUtils_GetAppID(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Sets the position where the overlay instance for the currently calling game should show notifications. + /// This position is per-game and if this function is called from outside of a game context it will do nothing. + /// + public static void SetOverlayNotificationPosition(ENotificationPosition eNotificationPosition) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamUtils_SetOverlayNotificationPosition(CSteamGameServerAPIContext.GetSteamUtils(), eNotificationPosition); + } + + /// + /// API asynchronous call results + /// can be used directly, but more commonly used via the callback dispatch API (see steam_api.h) + /// + public static bool IsAPICallCompleted(SteamAPICall_t hSteamAPICall, out bool pbFailed) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_IsAPICallCompleted(CSteamGameServerAPIContext.GetSteamUtils(), hSteamAPICall, out pbFailed); + } + + public static ESteamAPICallFailure GetAPICallFailureReason(SteamAPICall_t hSteamAPICall) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetAPICallFailureReason(CSteamGameServerAPIContext.GetSteamUtils(), hSteamAPICall); + } + + public static bool GetAPICallResult(SteamAPICall_t hSteamAPICall, IntPtr pCallback, int cubCallback, int iCallbackExpected, out bool pbFailed) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetAPICallResult(CSteamGameServerAPIContext.GetSteamUtils(), hSteamAPICall, pCallback, cubCallback, iCallbackExpected, out pbFailed); + } + + /// + /// returns the number of IPC calls made since the last time this function was called + /// Used for perf debugging so you can understand how many IPC calls your game makes per frame + /// Every IPC call is at minimum a thread context switch if not a process one so you want to rate + /// control how often you do them. + /// + public static uint GetIPCCallCount() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetIPCCallCount(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// API warning handling + /// 'int' is the severity; 0 for msg, 1 for warning + /// 'const char *' is the text of the message + /// callbacks will occur directly after the API function is called that generated the warning or message + /// + public static void SetWarningMessageHook(SteamAPIWarningMessageHook_t pFunction) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamUtils_SetWarningMessageHook(CSteamGameServerAPIContext.GetSteamUtils(), pFunction); + } + + /// + /// Returns true if the overlay is running & the user can access it. The overlay process could take a few seconds to + /// start & hook the game process, so this function will initially return false while the overlay is loading. + /// + public static bool IsOverlayEnabled() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_IsOverlayEnabled(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Normally this call is unneeded if your game has a constantly running frame loop that calls the + /// D3D Present API, or OGL SwapBuffers API every frame. + /// However, if you have a game that only refreshes the screen on an event driven basis then that can break + /// the overlay, as it uses your Present/SwapBuffers calls to drive it's internal frame loop and it may also + /// need to Present() to the screen any time an even needing a notification happens or when the overlay is + /// brought up over the game by a user. You can use this API to ask the overlay if it currently need a present + /// in that case, and then you can check for this periodically (roughly 33hz is desirable) and make sure you + /// refresh the screen with Present or SwapBuffers to allow the overlay to do it's work. + /// + public static bool BOverlayNeedsPresent() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_BOverlayNeedsPresent(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Asynchronous call to check if an executable file has been signed using the public key set on the signing tab + /// of the partner site, for example to refuse to load modified executable files. + /// The result is returned in CheckFileSignature_t. + /// k_ECheckFileSignatureNoSignaturesFoundForThisApp - This app has not been configured on the signing tab of the partner site to enable this function. + /// k_ECheckFileSignatureNoSignaturesFoundForThisFile - This file is not listed on the signing tab for the partner site. + /// k_ECheckFileSignatureFileNotFound - The file does not exist on disk. + /// k_ECheckFileSignatureInvalidSignature - The file exists, and the signing tab has been set for this file, but the file is either not signed or the signature does not match. + /// k_ECheckFileSignatureValidSignature - The file is signed and the signature is valid. + /// + public static SteamAPICall_t CheckFileSignature(string szFileName) { + InteropHelp.TestIfAvailableGameServer(); + using (var szFileName2 = new InteropHelp.UTF8StringHandle(szFileName)) { + return (SteamAPICall_t)NativeMethods.ISteamUtils_CheckFileSignature(CSteamGameServerAPIContext.GetSteamUtils(), szFileName2); + } + } + + /// + /// Activates the full-screen text input dialog which takes a initial text string and returns the text the user has typed + /// + public static bool ShowGamepadTextInput(EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, string pchDescription, uint unCharMax, string pchExistingText) { + InteropHelp.TestIfAvailableGameServer(); + using (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) + using (var pchExistingText2 = new InteropHelp.UTF8StringHandle(pchExistingText)) { + return NativeMethods.ISteamUtils_ShowGamepadTextInput(CSteamGameServerAPIContext.GetSteamUtils(), eInputMode, eLineInputMode, pchDescription2, unCharMax, pchExistingText2); + } + } + + /// + /// Returns previously entered text & length + /// + public static uint GetEnteredGamepadTextLength() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetEnteredGamepadTextLength(CSteamGameServerAPIContext.GetSteamUtils()); + } + + public static bool GetEnteredGamepadTextInput(out string pchText, uint cchText) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchText2 = Marshal.AllocHGlobal((int)cchText); + bool ret = NativeMethods.ISteamUtils_GetEnteredGamepadTextInput(CSteamGameServerAPIContext.GetSteamUtils(), pchText2, cchText); + pchText = ret ? InteropHelp.PtrToStringUTF8(pchText2) : null; + Marshal.FreeHGlobal(pchText2); + return ret; + } + + /// + /// returns the language the steam client is running in, you probably want ISteamApps::GetCurrentGameLanguage instead, this is for very special usage cases + /// + public static string GetSteamUILanguage() { + InteropHelp.TestIfAvailableGameServer(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUtils_GetSteamUILanguage(CSteamGameServerAPIContext.GetSteamUtils())); + } + + /// + /// returns true if Steam itself is running in VR mode + /// + public static bool IsSteamRunningInVR() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_IsSteamRunningInVR(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Sets the inset of the overlay notification from the corner specified by SetOverlayNotificationPosition. + /// + public static void SetOverlayNotificationInset(int nHorizontalInset, int nVerticalInset) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamUtils_SetOverlayNotificationInset(CSteamGameServerAPIContext.GetSteamUtils(), nHorizontalInset, nVerticalInset); + } + + /// + /// returns true if Steam & the Steam Overlay are running in Big Picture mode + /// Games much be launched through the Steam client to enable the Big Picture overlay. During development, + /// a game can be added as a non-steam game to the developers library to test this feature + /// + public static bool IsSteamInBigPictureMode() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_IsSteamInBigPictureMode(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// ask SteamUI to create and render its OpenVR dashboard + /// + public static void StartVRDashboard() { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamUtils_StartVRDashboard(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Returns true if the HMD content will be streamed via Steam Remote Play + /// + public static bool IsVRHeadsetStreamingEnabled() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_IsVRHeadsetStreamingEnabled(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Set whether the HMD content will be streamed via Steam Remote Play + /// If this is set to true, then the scene in the HMD headset will be streamed, and remote input will not be allowed. + /// If this is set to false, then the application window will be streamed instead, and remote input will be allowed. + /// The default is true unless "VRHeadsetStreaming" "0" is in the extended appinfo for a game. + /// (this is useful for games that have asymmetric multiplayer gameplay) + /// + public static void SetVRHeadsetStreamingEnabled(bool bEnabled) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamUtils_SetVRHeadsetStreamingEnabled(CSteamGameServerAPIContext.GetSteamUtils(), bEnabled); + } + + /// + /// Returns whether this steam client is a Steam China specific client, vs the global client. + /// + public static bool IsSteamChinaLauncher() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_IsSteamChinaLauncher(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Initializes text filtering, loading dictionaries for the language the game is running in. + /// unFilterOptions are reserved for future use and should be set to 0 + /// Returns false if filtering is unavailable for the game's language, in which case FilterText() will act as a passthrough. + /// Users can customize the text filter behavior in their Steam Account preferences: + /// https://store.steampowered.com/account/preferences#CommunityContentPreferences + /// + public static bool InitFilterText(uint unFilterOptions = 0) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_InitFilterText(CSteamGameServerAPIContext.GetSteamUtils(), unFilterOptions); + } + + /// + /// Filters the provided input message and places the filtered result into pchOutFilteredText, using legally required filtering and additional filtering based on the context and user settings + /// eContext is the type of content in the input string + /// sourceSteamID is the Steam ID that is the source of the input string (e.g. the player with the name, or who said the chat text) + /// pchInputText is the input string that should be filtered, which can be ASCII or UTF-8 + /// pchOutFilteredText is where the output will be placed, even if no filtering is performed + /// nByteSizeOutFilteredText is the size (in bytes) of pchOutFilteredText, should be at least strlen(pchInputText)+1 + /// Returns the number of characters (not bytes) filtered + /// + public static int FilterText(ETextFilteringContext eContext, CSteamID sourceSteamID, string pchInputMessage, out string pchOutFilteredText, uint nByteSizeOutFilteredText) { + InteropHelp.TestIfAvailableGameServer(); + IntPtr pchOutFilteredText2 = Marshal.AllocHGlobal((int)nByteSizeOutFilteredText); + using (var pchInputMessage2 = new InteropHelp.UTF8StringHandle(pchInputMessage)) { + int ret = NativeMethods.ISteamUtils_FilterText(CSteamGameServerAPIContext.GetSteamUtils(), eContext, sourceSteamID, pchInputMessage2, pchOutFilteredText2, nByteSizeOutFilteredText); + pchOutFilteredText = ret != -1 ? InteropHelp.PtrToStringUTF8(pchOutFilteredText2) : null; + Marshal.FreeHGlobal(pchOutFilteredText2); + return ret; + } + } + + /// + /// Return what we believe your current ipv6 connectivity to "the internet" is on the specified protocol. + /// This does NOT tell you if the Steam client is currently connected to Steam via ipv6. + /// + public static ESteamIPv6ConnectivityState GetIPv6ConnectivityState(ESteamIPv6ConnectivityProtocol eProtocol) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_GetIPv6ConnectivityState(CSteamGameServerAPIContext.GetSteamUtils(), eProtocol); + } + + /// + /// returns true if currently running on the Steam Deck device + /// + public static bool IsSteamRunningOnSteamDeck() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_IsSteamRunningOnSteamDeck(CSteamGameServerAPIContext.GetSteamUtils()); + } + + /// + /// Opens a floating keyboard over the game content and sends OS keyboard keys directly to the game. + /// The text field position is specified in pixels relative the origin of the game window and is used to position the floating keyboard in a way that doesn't cover the text field + /// + public static bool ShowFloatingGamepadTextInput(EFloatingGamepadTextInputMode eKeyboardMode, int nTextFieldXPosition, int nTextFieldYPosition, int nTextFieldWidth, int nTextFieldHeight) { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_ShowFloatingGamepadTextInput(CSteamGameServerAPIContext.GetSteamUtils(), eKeyboardMode, nTextFieldXPosition, nTextFieldYPosition, nTextFieldWidth, nTextFieldHeight); + } + + /// + /// In game launchers that don't have controller support you can call this to have Steam Input translate the controller input into mouse/kb to navigate the launcher + /// + public static void SetGameLauncherMode(bool bLauncherMode) { + InteropHelp.TestIfAvailableGameServer(); + NativeMethods.ISteamUtils_SetGameLauncherMode(CSteamGameServerAPIContext.GetSteamUtils(), bLauncherMode); + } + + /// + /// Dismisses the floating keyboard. + /// + public static bool DismissFloatingGamepadTextInput() { + InteropHelp.TestIfAvailableGameServer(); + return NativeMethods.ISteamUtils_DismissFloatingGamepadTextInput(CSteamGameServerAPIContext.GetSteamUtils()); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverutils.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverutils.cs.meta new file mode 100644 index 0000000..fabea4a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverutils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3bc4fe214c0d4e141a8566489f6eba33 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhtmlsurface.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhtmlsurface.cs new file mode 100644 index 0000000..cc56426 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhtmlsurface.cs @@ -0,0 +1,341 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamHTMLSurface { + /// + /// Must call init and shutdown when starting/ending use of the interface + /// + public static bool Init() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTMLSurface_Init(CSteamAPIContext.GetSteamHTMLSurface()); + } + + public static bool Shutdown() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTMLSurface_Shutdown(CSteamAPIContext.GetSteamHTMLSurface()); + } + + /// + /// Create a browser object for display of a html page, when creation is complete the call handle + /// will return a HTML_BrowserReady_t callback for the HHTMLBrowser of your new browser. + /// The user agent string is a substring to be added to the general user agent string so you can + /// identify your client on web servers. + /// The userCSS string lets you apply a CSS style sheet to every displayed page, leave null if + /// you do not require this functionality. + /// YOU MUST HAVE IMPLEMENTED HANDLERS FOR HTML_BrowserReady_t, HTML_StartRequest_t, + /// HTML_JSAlert_t, HTML_JSConfirm_t, and HTML_FileOpenDialog_t! See the CALLBACKS + /// section of this interface (AllowStartRequest, etc) for more details. If you do + /// not implement these callback handlers, the browser may appear to hang instead of + /// navigating to new pages or triggering javascript popups. + /// + public static SteamAPICall_t CreateBrowser(string pchUserAgent, string pchUserCSS) { + InteropHelp.TestIfAvailableClient(); + using (var pchUserAgent2 = new InteropHelp.UTF8StringHandle(pchUserAgent)) + using (var pchUserCSS2 = new InteropHelp.UTF8StringHandle(pchUserCSS)) { + return (SteamAPICall_t)NativeMethods.ISteamHTMLSurface_CreateBrowser(CSteamAPIContext.GetSteamHTMLSurface(), pchUserAgent2, pchUserCSS2); + } + } + + /// + /// Call this when you are done with a html surface, this lets us free the resources being used by it + /// + public static void RemoveBrowser(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_RemoveBrowser(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// Navigate to this URL, results in a HTML_StartRequest_t as the request commences + /// + public static void LoadURL(HHTMLBrowser unBrowserHandle, string pchURL, string pchPostData) { + InteropHelp.TestIfAvailableClient(); + using (var pchURL2 = new InteropHelp.UTF8StringHandle(pchURL)) + using (var pchPostData2 = new InteropHelp.UTF8StringHandle(pchPostData)) { + NativeMethods.ISteamHTMLSurface_LoadURL(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchURL2, pchPostData2); + } + } + + /// + /// Tells the surface the size in pixels to display the surface + /// + public static void SetSize(HHTMLBrowser unBrowserHandle, uint unWidth, uint unHeight) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_SetSize(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, unWidth, unHeight); + } + + /// + /// Stop the load of the current html page + /// + public static void StopLoad(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_StopLoad(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// Reload (most likely from local cache) the current page + /// + public static void Reload(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_Reload(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// navigate back in the page history + /// + public static void GoBack(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_GoBack(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// navigate forward in the page history + /// + public static void GoForward(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_GoForward(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// add this header to any url requests from this browser + /// + public static void AddHeader(HHTMLBrowser unBrowserHandle, string pchKey, string pchValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) + using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) { + NativeMethods.ISteamHTMLSurface_AddHeader(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchKey2, pchValue2); + } + } + + /// + /// run this javascript script in the currently loaded page + /// + public static void ExecuteJavascript(HHTMLBrowser unBrowserHandle, string pchScript) { + InteropHelp.TestIfAvailableClient(); + using (var pchScript2 = new InteropHelp.UTF8StringHandle(pchScript)) { + NativeMethods.ISteamHTMLSurface_ExecuteJavascript(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchScript2); + } + } + + /// + /// Mouse click and mouse movement commands + /// + public static void MouseUp(HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_MouseUp(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, eMouseButton); + } + + public static void MouseDown(HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_MouseDown(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, eMouseButton); + } + + public static void MouseDoubleClick(HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_MouseDoubleClick(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, eMouseButton); + } + + /// + /// x and y are relative to the HTML bounds + /// + public static void MouseMove(HHTMLBrowser unBrowserHandle, int x, int y) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_MouseMove(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, x, y); + } + + /// + /// nDelta is pixels of scroll + /// + public static void MouseWheel(HHTMLBrowser unBrowserHandle, int nDelta) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_MouseWheel(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nDelta); + } + + /// + /// keyboard interactions, native keycode is the virtual key code value from your OS, system key flags the key to not + /// be sent as a typed character as well as a key down + /// + public static void KeyDown(HHTMLBrowser unBrowserHandle, uint nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers, bool bIsSystemKey = false) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_KeyDown(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nNativeKeyCode, eHTMLKeyModifiers, bIsSystemKey); + } + + public static void KeyUp(HHTMLBrowser unBrowserHandle, uint nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_KeyUp(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nNativeKeyCode, eHTMLKeyModifiers); + } + + /// + /// cUnicodeChar is the unicode character point for this keypress (and potentially multiple chars per press) + /// + public static void KeyChar(HHTMLBrowser unBrowserHandle, uint cUnicodeChar, EHTMLKeyModifiers eHTMLKeyModifiers) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_KeyChar(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, cUnicodeChar, eHTMLKeyModifiers); + } + + /// + /// programmatically scroll this many pixels on the page + /// + public static void SetHorizontalScroll(HHTMLBrowser unBrowserHandle, uint nAbsolutePixelScroll) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_SetHorizontalScroll(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nAbsolutePixelScroll); + } + + public static void SetVerticalScroll(HHTMLBrowser unBrowserHandle, uint nAbsolutePixelScroll) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_SetVerticalScroll(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, nAbsolutePixelScroll); + } + + /// + /// tell the html control if it has key focus currently, controls showing the I-beam cursor in text controls amongst other things + /// + public static void SetKeyFocus(HHTMLBrowser unBrowserHandle, bool bHasKeyFocus) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_SetKeyFocus(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, bHasKeyFocus); + } + + /// + /// open the current pages html code in the local editor of choice, used for debugging + /// + public static void ViewSource(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_ViewSource(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// copy the currently selected text on the html page to the local clipboard + /// + public static void CopyToClipboard(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_CopyToClipboard(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// paste from the local clipboard to the current html page + /// + public static void PasteFromClipboard(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_PasteFromClipboard(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// find this string in the browser, if bCurrentlyInFind is true then instead cycle to the next matching element + /// + public static void Find(HHTMLBrowser unBrowserHandle, string pchSearchStr, bool bCurrentlyInFind, bool bReverse) { + InteropHelp.TestIfAvailableClient(); + using (var pchSearchStr2 = new InteropHelp.UTF8StringHandle(pchSearchStr)) { + NativeMethods.ISteamHTMLSurface_Find(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchSearchStr2, bCurrentlyInFind, bReverse); + } + } + + /// + /// cancel a currently running find + /// + public static void StopFind(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_StopFind(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// return details about the link at position x,y on the current page + /// + public static void GetLinkAtPosition(HHTMLBrowser unBrowserHandle, int x, int y) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_GetLinkAtPosition(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, x, y); + } + + /// + /// set a webcookie for the hostname in question + /// + public static void SetCookie(string pchHostname, string pchKey, string pchValue, string pchPath = "/", uint nExpires = 0, bool bSecure = false, bool bHTTPOnly = false) { + InteropHelp.TestIfAvailableClient(); + using (var pchHostname2 = new InteropHelp.UTF8StringHandle(pchHostname)) + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) + using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) + using (var pchPath2 = new InteropHelp.UTF8StringHandle(pchPath)) { + NativeMethods.ISteamHTMLSurface_SetCookie(CSteamAPIContext.GetSteamHTMLSurface(), pchHostname2, pchKey2, pchValue2, pchPath2, nExpires, bSecure, bHTTPOnly); + } + } + + /// + /// Zoom the current page by flZoom ( from 0.0 to 2.0, so to zoom to 120% use 1.2 ), zooming around point X,Y in the page (use 0,0 if you don't care) + /// + public static void SetPageScaleFactor(HHTMLBrowser unBrowserHandle, float flZoom, int nPointX, int nPointY) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_SetPageScaleFactor(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, flZoom, nPointX, nPointY); + } + + /// + /// Enable/disable low-resource background mode, where javascript and repaint timers are throttled, resources are + /// more aggressively purged from memory, and audio/video elements are paused. When background mode is enabled, + /// all HTML5 video and audio objects will execute ".pause()" and gain the property "._steam_background_paused = 1". + /// When background mode is disabled, any video or audio objects with that property will resume with ".play()". + /// + public static void SetBackgroundMode(HHTMLBrowser unBrowserHandle, bool bBackgroundMode) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_SetBackgroundMode(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, bBackgroundMode); + } + + /// + /// Scale the output display space by this factor, this is useful when displaying content on high dpi devices. + /// Specifies the ratio between physical and logical pixels. + /// + public static void SetDPIScalingFactor(HHTMLBrowser unBrowserHandle, float flDPIScaling) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_SetDPIScalingFactor(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, flDPIScaling); + } + + /// + /// Open HTML/JS developer tools + /// + public static void OpenDeveloperTools(HHTMLBrowser unBrowserHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_OpenDeveloperTools(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle); + } + + /// + /// CALLBACKS + /// These set of functions are used as responses to callback requests + /// You MUST call this in response to a HTML_StartRequest_t callback + /// Set bAllowed to true to allow this navigation, false to cancel it and stay + /// on the current page. You can use this feature to limit the valid pages + /// allowed in your HTML surface. + /// + public static void AllowStartRequest(HHTMLBrowser unBrowserHandle, bool bAllowed) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_AllowStartRequest(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, bAllowed); + } + + /// + /// You MUST call this in response to a HTML_JSAlert_t or HTML_JSConfirm_t callback + /// Set bResult to true for the OK option of a confirm, use false otherwise + /// + public static void JSDialogResponse(HHTMLBrowser unBrowserHandle, bool bResult) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_JSDialogResponse(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, bResult); + } + + /// + /// You MUST call this in response to a HTML_FileOpenDialog_t callback + /// + public static void FileLoadDialogResponse(HHTMLBrowser unBrowserHandle, IntPtr pchSelectedFiles) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamHTMLSurface_FileLoadDialogResponse(CSteamAPIContext.GetSteamHTMLSurface(), unBrowserHandle, pchSelectedFiles); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhtmlsurface.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhtmlsurface.cs.meta new file mode 100644 index 0000000..74a006d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhtmlsurface.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c43dd86c6f6eae843b97b286ffc38913 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhttp.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhttp.cs new file mode 100644 index 0000000..9425dec --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhttp.cs @@ -0,0 +1,277 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamHTTP { + /// + /// Initializes a new HTTP request, returning a handle to use in further operations on it. Requires + /// the method (GET or POST) and the absolute URL for the request. Both http and https are supported, + /// so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/ + /// or such. + /// + public static HTTPRequestHandle CreateHTTPRequest(EHTTPMethod eHTTPRequestMethod, string pchAbsoluteURL) { + InteropHelp.TestIfAvailableClient(); + using (var pchAbsoluteURL2 = new InteropHelp.UTF8StringHandle(pchAbsoluteURL)) { + return (HTTPRequestHandle)NativeMethods.ISteamHTTP_CreateHTTPRequest(CSteamAPIContext.GetSteamHTTP(), eHTTPRequestMethod, pchAbsoluteURL2); + } + } + + /// + /// Set a context value for the request, which will be returned in the HTTPRequestCompleted_t callback after + /// sending the request. This is just so the caller can easily keep track of which callbacks go with which request data. + /// + public static bool SetHTTPRequestContextValue(HTTPRequestHandle hRequest, ulong ulContextValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_SetHTTPRequestContextValue(CSteamAPIContext.GetSteamHTTP(), hRequest, ulContextValue); + } + + /// + /// Set a timeout in seconds for the HTTP request, must be called prior to sending the request. Default + /// timeout is 60 seconds if you don't call this. Returns false if the handle is invalid, or the request + /// has already been sent. + /// + public static bool SetHTTPRequestNetworkActivityTimeout(HTTPRequestHandle hRequest, uint unTimeoutSeconds) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_SetHTTPRequestNetworkActivityTimeout(CSteamAPIContext.GetSteamHTTP(), hRequest, unTimeoutSeconds); + } + + /// + /// Set a request header value for the request, must be called prior to sending the request. Will + /// return false if the handle is invalid or the request is already sent. + /// + public static bool SetHTTPRequestHeaderValue(HTTPRequestHandle hRequest, string pchHeaderName, string pchHeaderValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) + using (var pchHeaderValue2 = new InteropHelp.UTF8StringHandle(pchHeaderValue)) { + return NativeMethods.ISteamHTTP_SetHTTPRequestHeaderValue(CSteamAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, pchHeaderValue2); + } + } + + /// + /// Set a GET or POST parameter value on the request, which is set will depend on the EHTTPMethod specified + /// when creating the request. Must be called prior to sending the request. Will return false if the + /// handle is invalid or the request is already sent. + /// + public static bool SetHTTPRequestGetOrPostParameter(HTTPRequestHandle hRequest, string pchParamName, string pchParamValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchParamName2 = new InteropHelp.UTF8StringHandle(pchParamName)) + using (var pchParamValue2 = new InteropHelp.UTF8StringHandle(pchParamValue)) { + return NativeMethods.ISteamHTTP_SetHTTPRequestGetOrPostParameter(CSteamAPIContext.GetSteamHTTP(), hRequest, pchParamName2, pchParamValue2); + } + } + + /// + /// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on + /// asynchronous response via callback. + /// Note: If the user is in offline mode in Steam, then this will add a only-if-cached cache-control + /// header and only do a local cache lookup rather than sending any actual remote request. + /// + public static bool SendHTTPRequest(HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_SendHTTPRequest(CSteamAPIContext.GetSteamHTTP(), hRequest, out pCallHandle); + } + + /// + /// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on + /// asynchronous response via callback for completion, and listen for HTTPRequestHeadersReceived_t and + /// HTTPRequestDataReceived_t callbacks while streaming. + /// + public static bool SendHTTPRequestAndStreamResponse(HTTPRequestHandle hRequest, out SteamAPICall_t pCallHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_SendHTTPRequestAndStreamResponse(CSteamAPIContext.GetSteamHTTP(), hRequest, out pCallHandle); + } + + /// + /// Defers a request you have sent, the actual HTTP client code may have many requests queued, and this will move + /// the specified request to the tail of the queue. Returns false on invalid handle, or if the request is not yet sent. + /// + public static bool DeferHTTPRequest(HTTPRequestHandle hRequest) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_DeferHTTPRequest(CSteamAPIContext.GetSteamHTTP(), hRequest); + } + + /// + /// Prioritizes a request you have sent, the actual HTTP client code may have many requests queued, and this will move + /// the specified request to the head of the queue. Returns false on invalid handle, or if the request is not yet sent. + /// + public static bool PrioritizeHTTPRequest(HTTPRequestHandle hRequest) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_PrioritizeHTTPRequest(CSteamAPIContext.GetSteamHTTP(), hRequest); + } + + /// + /// Checks if a response header is present in a HTTP response given a handle from HTTPRequestCompleted_t, also + /// returns the size of the header value if present so the caller and allocate a correctly sized buffer for + /// GetHTTPResponseHeaderValue. + /// + public static bool GetHTTPResponseHeaderSize(HTTPRequestHandle hRequest, string pchHeaderName, out uint unResponseHeaderSize) { + InteropHelp.TestIfAvailableClient(); + using (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) { + return NativeMethods.ISteamHTTP_GetHTTPResponseHeaderSize(CSteamAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, out unResponseHeaderSize); + } + } + + /// + /// Gets header values from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the + /// header is not present or if your buffer is too small to contain it's value. You should first call + /// BGetHTTPResponseHeaderSize to check for the presence of the header and to find out the size buffer needed. + /// + public static bool GetHTTPResponseHeaderValue(HTTPRequestHandle hRequest, string pchHeaderName, byte[] pHeaderValueBuffer, uint unBufferSize) { + InteropHelp.TestIfAvailableClient(); + using (var pchHeaderName2 = new InteropHelp.UTF8StringHandle(pchHeaderName)) { + return NativeMethods.ISteamHTTP_GetHTTPResponseHeaderValue(CSteamAPIContext.GetSteamHTTP(), hRequest, pchHeaderName2, pHeaderValueBuffer, unBufferSize); + } + } + + /// + /// Gets the size of the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the + /// handle is invalid. + /// + public static bool GetHTTPResponseBodySize(HTTPRequestHandle hRequest, out uint unBodySize) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_GetHTTPResponseBodySize(CSteamAPIContext.GetSteamHTTP(), hRequest, out unBodySize); + } + + /// + /// Gets the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the + /// handle is invalid or is to a streaming response, or if the provided buffer is not the correct size. Use BGetHTTPResponseBodySize first to find out + /// the correct buffer size to use. + /// + public static bool GetHTTPResponseBodyData(HTTPRequestHandle hRequest, byte[] pBodyDataBuffer, uint unBufferSize) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_GetHTTPResponseBodyData(CSteamAPIContext.GetSteamHTTP(), hRequest, pBodyDataBuffer, unBufferSize); + } + + /// + /// Gets the body data from a streaming HTTP response given a handle from HTTPRequestDataReceived_t. Will return false if the + /// handle is invalid or is to a non-streaming response (meaning it wasn't sent with SendHTTPRequestAndStreamResponse), or if the buffer size and offset + /// do not match the size and offset sent in HTTPRequestDataReceived_t. + /// + public static bool GetHTTPStreamingResponseBodyData(HTTPRequestHandle hRequest, uint cOffset, byte[] pBodyDataBuffer, uint unBufferSize) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_GetHTTPStreamingResponseBodyData(CSteamAPIContext.GetSteamHTTP(), hRequest, cOffset, pBodyDataBuffer, unBufferSize); + } + + /// + /// Releases an HTTP response handle, should always be called to free resources after receiving a HTTPRequestCompleted_t + /// callback and finishing using the response. + /// + public static bool ReleaseHTTPRequest(HTTPRequestHandle hRequest) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_ReleaseHTTPRequest(CSteamAPIContext.GetSteamHTTP(), hRequest); + } + + /// + /// Gets progress on downloading the body for the request. This will be zero unless a response header has already been + /// received which included a content-length field. For responses that contain no content-length it will report + /// zero for the duration of the request as the size is unknown until the connection closes. + /// + public static bool GetHTTPDownloadProgressPct(HTTPRequestHandle hRequest, out float pflPercentOut) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_GetHTTPDownloadProgressPct(CSteamAPIContext.GetSteamHTTP(), hRequest, out pflPercentOut); + } + + /// + /// Sets the body for an HTTP Post request. Will fail and return false on a GET request, and will fail if POST params + /// have already been set for the request. Setting this raw body makes it the only contents for the post, the pchContentType + /// parameter will set the content-type header for the request so the server may know how to interpret the body. + /// + public static bool SetHTTPRequestRawPostBody(HTTPRequestHandle hRequest, string pchContentType, byte[] pubBody, uint unBodyLen) { + InteropHelp.TestIfAvailableClient(); + using (var pchContentType2 = new InteropHelp.UTF8StringHandle(pchContentType)) { + return NativeMethods.ISteamHTTP_SetHTTPRequestRawPostBody(CSteamAPIContext.GetSteamHTTP(), hRequest, pchContentType2, pubBody, unBodyLen); + } + } + + /// + /// Creates a cookie container handle which you must later free with ReleaseCookieContainer(). If bAllowResponsesToModify=true + /// than any response to your requests using this cookie container may add new cookies which may be transmitted with + /// future requests. If bAllowResponsesToModify=false than only cookies you explicitly set will be sent. This API is just for + /// during process lifetime, after steam restarts no cookies are persisted and you have no way to access the cookie container across + /// repeat executions of your process. + /// + public static HTTPCookieContainerHandle CreateCookieContainer(bool bAllowResponsesToModify) { + InteropHelp.TestIfAvailableClient(); + return (HTTPCookieContainerHandle)NativeMethods.ISteamHTTP_CreateCookieContainer(CSteamAPIContext.GetSteamHTTP(), bAllowResponsesToModify); + } + + /// + /// Release a cookie container you are finished using, freeing it's memory + /// + public static bool ReleaseCookieContainer(HTTPCookieContainerHandle hCookieContainer) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_ReleaseCookieContainer(CSteamAPIContext.GetSteamHTTP(), hCookieContainer); + } + + /// + /// Adds a cookie to the specified cookie container that will be used with future requests. + /// + public static bool SetCookie(HTTPCookieContainerHandle hCookieContainer, string pchHost, string pchUrl, string pchCookie) { + InteropHelp.TestIfAvailableClient(); + using (var pchHost2 = new InteropHelp.UTF8StringHandle(pchHost)) + using (var pchUrl2 = new InteropHelp.UTF8StringHandle(pchUrl)) + using (var pchCookie2 = new InteropHelp.UTF8StringHandle(pchCookie)) { + return NativeMethods.ISteamHTTP_SetCookie(CSteamAPIContext.GetSteamHTTP(), hCookieContainer, pchHost2, pchUrl2, pchCookie2); + } + } + + /// + /// Set the cookie container to use for a HTTP request + /// + public static bool SetHTTPRequestCookieContainer(HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_SetHTTPRequestCookieContainer(CSteamAPIContext.GetSteamHTTP(), hRequest, hCookieContainer); + } + + /// + /// Set the extra user agent info for a request, this doesn't clobber the normal user agent, it just adds the extra info on the end + /// + public static bool SetHTTPRequestUserAgentInfo(HTTPRequestHandle hRequest, string pchUserAgentInfo) { + InteropHelp.TestIfAvailableClient(); + using (var pchUserAgentInfo2 = new InteropHelp.UTF8StringHandle(pchUserAgentInfo)) { + return NativeMethods.ISteamHTTP_SetHTTPRequestUserAgentInfo(CSteamAPIContext.GetSteamHTTP(), hRequest, pchUserAgentInfo2); + } + } + + /// + /// Disable or re-enable verification of SSL/TLS certificates. + /// By default, certificates are checked for all HTTPS requests. + /// + public static bool SetHTTPRequestRequiresVerifiedCertificate(HTTPRequestHandle hRequest, bool bRequireVerifiedCertificate) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_SetHTTPRequestRequiresVerifiedCertificate(CSteamAPIContext.GetSteamHTTP(), hRequest, bRequireVerifiedCertificate); + } + + /// + /// Set an absolute timeout on the HTTP request, this is just a total time timeout different than the network activity timeout + /// which can bump everytime we get more data + /// + public static bool SetHTTPRequestAbsoluteTimeoutMS(HTTPRequestHandle hRequest, uint unMilliseconds) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_SetHTTPRequestAbsoluteTimeoutMS(CSteamAPIContext.GetSteamHTTP(), hRequest, unMilliseconds); + } + + /// + /// Check if the reason the request failed was because we timed it out (rather than some harder failure) + /// + public static bool GetHTTPRequestWasTimedOut(HTTPRequestHandle hRequest, out bool pbWasTimedOut) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamHTTP_GetHTTPRequestWasTimedOut(CSteamAPIContext.GetSteamHTTP(), hRequest, out pbWasTimedOut); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhttp.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhttp.cs.meta new file mode 100644 index 0000000..eda8ee8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhttp.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: add20100ffe7965439ac0185598adb2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminput.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminput.cs new file mode 100644 index 0000000..08ca24f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminput.cs @@ -0,0 +1,476 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamInput { + /// + /// Init and Shutdown must be called when starting/ending use of this interface. + /// if bExplicitlyCallRunFrame is called then you will need to manually call RunFrame + /// each frame, otherwise Steam Input will updated when SteamAPI_RunCallbacks() is called + /// + public static bool Init(bool bExplicitlyCallRunFrame) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_Init(CSteamAPIContext.GetSteamInput(), bExplicitlyCallRunFrame); + } + + public static bool Shutdown() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_Shutdown(CSteamAPIContext.GetSteamInput()); + } + + /// + /// Set the absolute path to the Input Action Manifest file containing the in-game actions + /// and file paths to the official configurations. Used in games that bundle Steam Input + /// configurations inside of the game depot instead of using the Steam Workshop + /// + public static bool SetInputActionManifestFilePath(string pchInputActionManifestAbsolutePath) { + InteropHelp.TestIfAvailableClient(); + using (var pchInputActionManifestAbsolutePath2 = new InteropHelp.UTF8StringHandle(pchInputActionManifestAbsolutePath)) { + return NativeMethods.ISteamInput_SetInputActionManifestFilePath(CSteamAPIContext.GetSteamInput(), pchInputActionManifestAbsolutePath2); + } + } + + /// + /// Synchronize API state with the latest Steam Input action data available. This + /// is performed automatically by SteamAPI_RunCallbacks, but for the absolute lowest + /// possible latency, you call this directly before reading controller state. + /// Note: This must be called from somewhere before GetConnectedControllers will + /// return any handles + /// + public static void RunFrame(bool bReservedValue = true) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_RunFrame(CSteamAPIContext.GetSteamInput(), bReservedValue); + } + + /// + /// Waits on an IPC event from Steam sent when there is new data to be fetched from + /// the data drop. Returns true when data was recievied before the timeout expires. + /// Useful for games with a dedicated input thread + /// + public static bool BWaitForData(bool bWaitForever, uint unTimeout) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_BWaitForData(CSteamAPIContext.GetSteamInput(), bWaitForever, unTimeout); + } + + /// + /// Returns true if new data has been received since the last time action data was accessed + /// via GetDigitalActionData or GetAnalogActionData. The game will still need to call + /// SteamInput()->RunFrame() or SteamAPI_RunCallbacks() before this to update the data stream + /// + public static bool BNewDataAvailable() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_BNewDataAvailable(CSteamAPIContext.GetSteamInput()); + } + + /// + /// Enumerate currently connected Steam Input enabled devices - developers can opt in controller by type (ex: Xbox/Playstation/etc) via + /// the Steam Input settings in the Steamworks site or users can opt-in in their controller settings in Steam. + /// handlesOut should point to a STEAM_INPUT_MAX_COUNT sized array of InputHandle_t handles + /// Returns the number of handles written to handlesOut + /// + public static int GetConnectedControllers(InputHandle_t[] handlesOut) { + InteropHelp.TestIfAvailableClient(); + if (handlesOut != null && handlesOut.Length != Constants.STEAM_INPUT_MAX_COUNT) { + throw new System.ArgumentException("handlesOut must be the same size as Constants.STEAM_INPUT_MAX_COUNT!"); + } + return NativeMethods.ISteamInput_GetConnectedControllers(CSteamAPIContext.GetSteamInput(), handlesOut); + } + + /// + /// ----------------------------------------------------------------------------- + /// CALLBACKS + /// ----------------------------------------------------------------------------- + /// Controller configuration loaded - these callbacks will always fire if you have + /// a handler. Note: this is called within either SteamInput()->RunFrame or by SteamAPI_RunCallbacks + /// Enable SteamInputDeviceConnected_t and SteamInputDeviceDisconnected_t callbacks. + /// Each controller that is already connected will generate a device connected + /// callback when you enable them + /// + public static void EnableDeviceCallbacks() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_EnableDeviceCallbacks(CSteamAPIContext.GetSteamInput()); + } + + /// + /// Controller Connected - provides info about a single newly connected controller + /// Note: this is called within either SteamInput()->RunFrame or by SteamAPI_RunCallbacks + /// Controller Disconnected - provides info about a single disconnected controller + /// Note: this is called within either SteamInput()->RunFrame or by SteamAPI_RunCallbacks + /// Controllers using Gamepad emulation (XInput, DirectInput, etc) will be seated in the order that + /// input is sent by the device. This callback will fire on first input for each device and when the + /// a user has manually changed the order via the Steam overlay. This also has the device type info + /// so that you can change out glyph sets without making additional API calls + /// Enable SteamInputActionEvent_t callbacks. Directly calls your callback function + /// for lower latency than standard Steam callbacks. Supports one callback at a time. + /// Note: this is called within either SteamInput()->RunFrame or by SteamAPI_RunCallbacks + /// + public static void EnableActionEventCallbacks(SteamInputActionEventCallbackPointer pCallback) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_EnableActionEventCallbacks(CSteamAPIContext.GetSteamInput(), pCallback); + } + + /// + /// ----------------------------------------------------------------------------- + /// ACTION SETS + /// ----------------------------------------------------------------------------- + /// Lookup the handle for an Action Set. Best to do this once on startup, and store the handles for all future API calls. + /// + public static InputActionSetHandle_t GetActionSetHandle(string pszActionSetName) { + InteropHelp.TestIfAvailableClient(); + using (var pszActionSetName2 = new InteropHelp.UTF8StringHandle(pszActionSetName)) { + return (InputActionSetHandle_t)NativeMethods.ISteamInput_GetActionSetHandle(CSteamAPIContext.GetSteamInput(), pszActionSetName2); + } + } + + /// + /// Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive') + /// This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in + /// your state loops, instead of trying to place it in all of your state transitions. + /// + public static void ActivateActionSet(InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_ActivateActionSet(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetHandle); + } + + public static InputActionSetHandle_t GetCurrentActionSet(InputHandle_t inputHandle) { + InteropHelp.TestIfAvailableClient(); + return (InputActionSetHandle_t)NativeMethods.ISteamInput_GetCurrentActionSet(CSteamAPIContext.GetSteamInput(), inputHandle); + } + + /// + /// ACTION SET LAYERS + /// + public static void ActivateActionSetLayer(InputHandle_t inputHandle, InputActionSetHandle_t actionSetLayerHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_ActivateActionSetLayer(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetLayerHandle); + } + + public static void DeactivateActionSetLayer(InputHandle_t inputHandle, InputActionSetHandle_t actionSetLayerHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_DeactivateActionSetLayer(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetLayerHandle); + } + + public static void DeactivateAllActionSetLayers(InputHandle_t inputHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_DeactivateAllActionSetLayers(CSteamAPIContext.GetSteamInput(), inputHandle); + } + + /// + /// Enumerate currently active layers. + /// handlesOut should point to a STEAM_INPUT_MAX_ACTIVE_LAYERS sized array of InputActionSetHandle_t handles + /// Returns the number of handles written to handlesOut + /// + public static int GetActiveActionSetLayers(InputHandle_t inputHandle, InputActionSetHandle_t[] handlesOut) { + InteropHelp.TestIfAvailableClient(); + if (handlesOut != null && handlesOut.Length != Constants.STEAM_INPUT_MAX_ACTIVE_LAYERS) { + throw new System.ArgumentException("handlesOut must be the same size as Constants.STEAM_INPUT_MAX_ACTIVE_LAYERS!"); + } + return NativeMethods.ISteamInput_GetActiveActionSetLayers(CSteamAPIContext.GetSteamInput(), inputHandle, handlesOut); + } + + /// + /// ----------------------------------------------------------------------------- + /// ACTIONS + /// ----------------------------------------------------------------------------- + /// Lookup the handle for a digital action. Best to do this once on startup, and store the handles for all future API calls. + /// + public static InputDigitalActionHandle_t GetDigitalActionHandle(string pszActionName) { + InteropHelp.TestIfAvailableClient(); + using (var pszActionName2 = new InteropHelp.UTF8StringHandle(pszActionName)) { + return (InputDigitalActionHandle_t)NativeMethods.ISteamInput_GetDigitalActionHandle(CSteamAPIContext.GetSteamInput(), pszActionName2); + } + } + + /// + /// Returns the current state of the supplied digital game action + /// + public static InputDigitalActionData_t GetDigitalActionData(InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetDigitalActionData(CSteamAPIContext.GetSteamInput(), inputHandle, digitalActionHandle); + } + + /// + /// Get the origin(s) for a digital action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action. + /// originsOut should point to a STEAM_INPUT_MAX_ORIGINS sized array of EInputActionOrigin handles. The EInputActionOrigin enum will get extended as support for new controller controllers gets added to + /// the Steam client and will exceed the values from this header, please check bounds if you are using a look up table. + /// + public static int GetDigitalActionOrigins(InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputDigitalActionHandle_t digitalActionHandle, EInputActionOrigin[] originsOut) { + InteropHelp.TestIfAvailableClient(); + if (originsOut != null && originsOut.Length != Constants.STEAM_INPUT_MAX_ORIGINS) { + throw new System.ArgumentException("originsOut must be the same size as Constants.STEAM_INPUT_MAX_ORIGINS!"); + } + return NativeMethods.ISteamInput_GetDigitalActionOrigins(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetHandle, digitalActionHandle, originsOut); + } + + /// + /// Returns a localized string (from Steam's language setting) for the user-facing action name corresponding to the specified handle + /// + public static string GetStringForDigitalActionName(InputDigitalActionHandle_t eActionHandle) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetStringForDigitalActionName(CSteamAPIContext.GetSteamInput(), eActionHandle)); + } + + /// + /// Lookup the handle for an analog action. Best to do this once on startup, and store the handles for all future API calls. + /// + public static InputAnalogActionHandle_t GetAnalogActionHandle(string pszActionName) { + InteropHelp.TestIfAvailableClient(); + using (var pszActionName2 = new InteropHelp.UTF8StringHandle(pszActionName)) { + return (InputAnalogActionHandle_t)NativeMethods.ISteamInput_GetAnalogActionHandle(CSteamAPIContext.GetSteamInput(), pszActionName2); + } + } + + /// + /// Returns the current state of these supplied analog game action + /// + public static InputAnalogActionData_t GetAnalogActionData(InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetAnalogActionData(CSteamAPIContext.GetSteamInput(), inputHandle, analogActionHandle); + } + + /// + /// Get the origin(s) for an analog action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action. + /// originsOut should point to a STEAM_INPUT_MAX_ORIGINS sized array of EInputActionOrigin handles. The EInputActionOrigin enum will get extended as support for new controller controllers gets added to + /// the Steam client and will exceed the values from this header, please check bounds if you are using a look up table. + /// + public static int GetAnalogActionOrigins(InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputAnalogActionHandle_t analogActionHandle, EInputActionOrigin[] originsOut) { + InteropHelp.TestIfAvailableClient(); + if (originsOut != null && originsOut.Length != Constants.STEAM_INPUT_MAX_ORIGINS) { + throw new System.ArgumentException("originsOut must be the same size as Constants.STEAM_INPUT_MAX_ORIGINS!"); + } + return NativeMethods.ISteamInput_GetAnalogActionOrigins(CSteamAPIContext.GetSteamInput(), inputHandle, actionSetHandle, analogActionHandle, originsOut); + } + + /// + /// Get a local path to a PNG file for the provided origin's glyph. + /// + public static string GetGlyphPNGForActionOrigin(EInputActionOrigin eOrigin, ESteamInputGlyphSize eSize, uint unFlags) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetGlyphPNGForActionOrigin(CSteamAPIContext.GetSteamInput(), eOrigin, eSize, unFlags)); + } + + /// + /// Get a local path to a SVG file for the provided origin's glyph. + /// + public static string GetGlyphSVGForActionOrigin(EInputActionOrigin eOrigin, uint unFlags) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetGlyphSVGForActionOrigin(CSteamAPIContext.GetSteamInput(), eOrigin, unFlags)); + } + + /// + /// Get a local path to an older, Big Picture Mode-style PNG file for a particular origin + /// + public static string GetGlyphForActionOrigin_Legacy(EInputActionOrigin eOrigin) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetGlyphForActionOrigin_Legacy(CSteamAPIContext.GetSteamInput(), eOrigin)); + } + + /// + /// Returns a localized string (from Steam's language setting) for the specified origin. + /// + public static string GetStringForActionOrigin(EInputActionOrigin eOrigin) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetStringForActionOrigin(CSteamAPIContext.GetSteamInput(), eOrigin)); + } + + /// + /// Returns a localized string (from Steam's language setting) for the user-facing action name corresponding to the specified handle + /// + public static string GetStringForAnalogActionName(InputAnalogActionHandle_t eActionHandle) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetStringForAnalogActionName(CSteamAPIContext.GetSteamInput(), eActionHandle)); + } + + /// + /// Stop analog momentum for the action if it is a mouse action in trackball mode + /// + public static void StopAnalogActionMomentum(InputHandle_t inputHandle, InputAnalogActionHandle_t eAction) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_StopAnalogActionMomentum(CSteamAPIContext.GetSteamInput(), inputHandle, eAction); + } + + /// + /// Returns raw motion data from the specified device + /// + public static InputMotionData_t GetMotionData(InputHandle_t inputHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetMotionData(CSteamAPIContext.GetSteamInput(), inputHandle); + } + + /// + /// ----------------------------------------------------------------------------- + /// OUTPUTS + /// ----------------------------------------------------------------------------- + /// Trigger a vibration event on supported controllers - Steam will translate these commands into haptic pulses for Steam Controllers + /// + public static void TriggerVibration(InputHandle_t inputHandle, ushort usLeftSpeed, ushort usRightSpeed) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_TriggerVibration(CSteamAPIContext.GetSteamInput(), inputHandle, usLeftSpeed, usRightSpeed); + } + + /// + /// Trigger a vibration event on supported controllers including Xbox trigger impulse rumble - Steam will translate these commands into haptic pulses for Steam Controllers + /// + public static void TriggerVibrationExtended(InputHandle_t inputHandle, ushort usLeftSpeed, ushort usRightSpeed, ushort usLeftTriggerSpeed, ushort usRightTriggerSpeed) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_TriggerVibrationExtended(CSteamAPIContext.GetSteamInput(), inputHandle, usLeftSpeed, usRightSpeed, usLeftTriggerSpeed, usRightTriggerSpeed); + } + + /// + /// Send a haptic pulse, works on Steam Deck and Steam Controller devices + /// + public static void TriggerSimpleHapticEvent(InputHandle_t inputHandle, EControllerHapticLocation eHapticLocation, byte nIntensity, char nGainDB, byte nOtherIntensity, char nOtherGainDB) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_TriggerSimpleHapticEvent(CSteamAPIContext.GetSteamInput(), inputHandle, eHapticLocation, nIntensity, nGainDB, nOtherIntensity, nOtherGainDB); + } + + /// + /// Set the controller LED color on supported controllers. nFlags is a bitmask of values from ESteamInputLEDFlag - 0 will default to setting a color. Steam will handle + /// the behavior on exit of your program so you don't need to try restore the default as you are shutting down + /// + public static void SetLEDColor(InputHandle_t inputHandle, byte nColorR, byte nColorG, byte nColorB, uint nFlags) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_SetLEDColor(CSteamAPIContext.GetSteamInput(), inputHandle, nColorR, nColorG, nColorB, nFlags); + } + + /// + /// Trigger a haptic pulse on a Steam Controller - if you are approximating rumble you may want to use TriggerVibration instead. + /// Good uses for Haptic pulses include chimes, noises, or directional gameplay feedback (taking damage, footstep locations, etc). + /// + public static void Legacy_TriggerHapticPulse(InputHandle_t inputHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_Legacy_TriggerHapticPulse(CSteamAPIContext.GetSteamInput(), inputHandle, eTargetPad, usDurationMicroSec); + } + + /// + /// Trigger a haptic pulse with a duty cycle of usDurationMicroSec / usOffMicroSec, unRepeat times. If you are approximating rumble you may want to use TriggerVibration instead. + /// nFlags is currently unused and reserved for future use. + /// + public static void Legacy_TriggerRepeatedHapticPulse(InputHandle_t inputHandle, ESteamControllerPad eTargetPad, ushort usDurationMicroSec, ushort usOffMicroSec, ushort unRepeat, uint nFlags) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_Legacy_TriggerRepeatedHapticPulse(CSteamAPIContext.GetSteamInput(), inputHandle, eTargetPad, usDurationMicroSec, usOffMicroSec, unRepeat, nFlags); + } + + /// + /// ----------------------------------------------------------------------------- + /// Utility functions available without using the rest of Steam Input API + /// ----------------------------------------------------------------------------- + /// Invokes the Steam overlay and brings up the binding screen if the user is using Big Picture Mode + /// If the user is not in Big Picture Mode it will open up the binding in a new window + /// + public static bool ShowBindingPanel(InputHandle_t inputHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_ShowBindingPanel(CSteamAPIContext.GetSteamInput(), inputHandle); + } + + /// + /// Returns the input type for a particular handle - unlike EInputActionOrigin which update with Steam and may return unrecognized values + /// ESteamInputType will remain static and only return valid values from your SDK version + /// + public static ESteamInputType GetInputTypeForHandle(InputHandle_t inputHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetInputTypeForHandle(CSteamAPIContext.GetSteamInput(), inputHandle); + } + + /// + /// Returns the associated controller handle for the specified emulated gamepad - can be used with the above 2 functions + /// to identify controllers presented to your game over Xinput. Returns 0 if the Xinput index isn't associated with Steam Input + /// + public static InputHandle_t GetControllerForGamepadIndex(int nIndex) { + InteropHelp.TestIfAvailableClient(); + return (InputHandle_t)NativeMethods.ISteamInput_GetControllerForGamepadIndex(CSteamAPIContext.GetSteamInput(), nIndex); + } + + /// + /// Returns the associated gamepad index for the specified controller, if emulating a gamepad or -1 if not associated with an Xinput index + /// + public static int GetGamepadIndexForController(InputHandle_t ulinputHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetGamepadIndexForController(CSteamAPIContext.GetSteamInput(), ulinputHandle); + } + + /// + /// Returns a localized string (from Steam's language setting) for the specified Xbox controller origin. + /// + public static string GetStringForXboxOrigin(EXboxOrigin eOrigin) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetStringForXboxOrigin(CSteamAPIContext.GetSteamInput(), eOrigin)); + } + + /// + /// Get a local path to art for on-screen glyph for a particular Xbox controller origin + /// + public static string GetGlyphForXboxOrigin(EXboxOrigin eOrigin) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamInput_GetGlyphForXboxOrigin(CSteamAPIContext.GetSteamInput(), eOrigin)); + } + + /// + /// Get the equivalent ActionOrigin for a given Xbox controller origin this can be chained with GetGlyphForActionOrigin to provide future proof glyphs for + /// non-Steam Input API action games. Note - this only translates the buttons directly and doesn't take into account any remapping a user has made in their configuration + /// + public static EInputActionOrigin GetActionOriginFromXboxOrigin(InputHandle_t inputHandle, EXboxOrigin eOrigin) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetActionOriginFromXboxOrigin(CSteamAPIContext.GetSteamInput(), inputHandle, eOrigin); + } + + /// + /// Convert an origin to another controller type - for inputs not present on the other controller type this will return k_EInputActionOrigin_None + /// When a new input type is added you will be able to pass in k_ESteamInputType_Unknown and the closest origin that your version of the SDK recognized will be returned + /// ex: if a Playstation 5 controller was released this function would return Playstation 4 origins. + /// + public static EInputActionOrigin TranslateActionOrigin(ESteamInputType eDestinationInputType, EInputActionOrigin eSourceOrigin) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_TranslateActionOrigin(CSteamAPIContext.GetSteamInput(), eDestinationInputType, eSourceOrigin); + } + + /// + /// Get the binding revision for a given device. Returns false if the handle was not valid or if a mapping is not yet loaded for the device + /// + public static bool GetDeviceBindingRevision(InputHandle_t inputHandle, out int pMajor, out int pMinor) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetDeviceBindingRevision(CSteamAPIContext.GetSteamInput(), inputHandle, out pMajor, out pMinor); + } + + /// + /// Get the Steam Remote Play session ID associated with a device, or 0 if there is no session associated with it + /// See isteamremoteplay.h for more information on Steam Remote Play sessions + /// + public static uint GetRemotePlaySessionID(InputHandle_t inputHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetRemotePlaySessionID(CSteamAPIContext.GetSteamInput(), inputHandle); + } + + /// + /// Get a bitmask of the Steam Input Configuration types opted in for the current session. Returns ESteamInputConfigurationEnableType values. + /// Note: user can override the settings from the Steamworks Partner site so the returned values may not exactly match your default configuration + /// + public static ushort GetSessionInputConfigurationSettings() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInput_GetSessionInputConfigurationSettings(CSteamAPIContext.GetSteamInput()); + } + + /// + /// Set the trigger effect for a DualSense controller + /// + public static void SetDualSenseTriggerEffect(InputHandle_t inputHandle, IntPtr pParam) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInput_SetDualSenseTriggerEffect(CSteamAPIContext.GetSteamInput(), inputHandle, pParam); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminput.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminput.cs.meta new file mode 100644 index 0000000..f38b735 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminput.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41c08c9051a973f4ab4585374584267d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminventory.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminventory.cs new file mode 100644 index 0000000..a86d6c8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminventory.cs @@ -0,0 +1,478 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamInventory { + /// + /// INVENTORY ASYNC RESULT MANAGEMENT + /// Asynchronous inventory queries always output a result handle which can be used with + /// GetResultStatus, GetResultItems, etc. A SteamInventoryResultReady_t callback will + /// be triggered when the asynchronous result becomes ready (or fails). + /// Find out the status of an asynchronous inventory result handle. Possible values: + /// k_EResultPending - still in progress + /// k_EResultOK - done, result ready + /// k_EResultExpired - done, result ready, maybe out of date (see DeserializeResult) + /// k_EResultInvalidParam - ERROR: invalid API call parameters + /// k_EResultServiceUnavailable - ERROR: service temporarily down, you may retry later + /// k_EResultLimitExceeded - ERROR: operation would exceed per-user inventory limits + /// k_EResultFail - ERROR: unknown / generic error + /// + public static EResult GetResultStatus(SteamInventoryResult_t resultHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_GetResultStatus(CSteamAPIContext.GetSteamInventory(), resultHandle); + } + + /// + /// Copies the contents of a result set into a flat array. The specific + /// contents of the result set depend on which query which was used. + /// + public static bool GetResultItems(SteamInventoryResult_t resultHandle, SteamItemDetails_t[] pOutItemsArray, ref uint punOutItemsArraySize) { + InteropHelp.TestIfAvailableClient(); + if (pOutItemsArray != null && pOutItemsArray.Length != punOutItemsArraySize) { + throw new System.ArgumentException("pOutItemsArray must be the same size as punOutItemsArraySize!"); + } + return NativeMethods.ISteamInventory_GetResultItems(CSteamAPIContext.GetSteamInventory(), resultHandle, pOutItemsArray, ref punOutItemsArraySize); + } + + /// + /// In combination with GetResultItems, you can use GetResultItemProperty to retrieve + /// dynamic string properties for a given item returned in the result set. + /// Property names are always composed of ASCII letters, numbers, and/or underscores. + /// Pass a NULL pointer for pchPropertyName to get a comma - separated list of available + /// property names. + /// If pchValueBuffer is NULL, *punValueBufferSize will contain the + /// suggested buffer size. Otherwise it will be the number of bytes actually copied + /// to pchValueBuffer. If the results do not fit in the given buffer, partial + /// results may be copied. + /// + public static bool GetResultItemProperty(SteamInventoryResult_t resultHandle, uint unItemIndex, string pchPropertyName, out string pchValueBuffer, ref uint punValueBufferSizeOut) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchValueBuffer2 = Marshal.AllocHGlobal((int)punValueBufferSizeOut); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + bool ret = NativeMethods.ISteamInventory_GetResultItemProperty(CSteamAPIContext.GetSteamInventory(), resultHandle, unItemIndex, pchPropertyName2, pchValueBuffer2, ref punValueBufferSizeOut); + pchValueBuffer = ret ? InteropHelp.PtrToStringUTF8(pchValueBuffer2) : null; + Marshal.FreeHGlobal(pchValueBuffer2); + return ret; + } + } + + /// + /// Returns the server time at which the result was generated. Compare against + /// the value of IClientUtils::GetServerRealTime() to determine age. + /// + public static uint GetResultTimestamp(SteamInventoryResult_t resultHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_GetResultTimestamp(CSteamAPIContext.GetSteamInventory(), resultHandle); + } + + /// + /// Returns true if the result belongs to the target steam ID, false if the + /// result does not. This is important when using DeserializeResult, to verify + /// that a remote player is not pretending to have a different user's inventory. + /// + public static bool CheckResultSteamID(SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_CheckResultSteamID(CSteamAPIContext.GetSteamInventory(), resultHandle, steamIDExpected); + } + + /// + /// Destroys a result handle and frees all associated memory. + /// + public static void DestroyResult(SteamInventoryResult_t resultHandle) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInventory_DestroyResult(CSteamAPIContext.GetSteamInventory(), resultHandle); + } + + /// + /// INVENTORY ASYNC QUERY + /// Captures the entire state of the current user's Steam inventory. + /// You must call DestroyResult on this handle when you are done with it. + /// Returns false and sets *pResultHandle to zero if inventory is unavailable. + /// Note: calls to this function are subject to rate limits and may return + /// cached results if called too frequently. It is suggested that you call + /// this function only when you are about to display the user's full inventory, + /// or if you expect that the inventory may have changed. + /// + public static bool GetAllItems(out SteamInventoryResult_t pResultHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_GetAllItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle); + } + + /// + /// Captures the state of a subset of the current user's Steam inventory, + /// identified by an array of item instance IDs. The results from this call + /// can be serialized and passed to other players to "prove" that the current + /// user owns specific items, without exposing the user's entire inventory. + /// For example, you could call GetItemsByID with the IDs of the user's + /// currently equipped cosmetic items and serialize this to a buffer, and + /// then transmit this buffer to other players upon joining a game. + /// + public static bool GetItemsByID(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t[] pInstanceIDs, uint unCountInstanceIDs) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_GetItemsByID(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pInstanceIDs, unCountInstanceIDs); + } + + /// + /// RESULT SERIALIZATION AND AUTHENTICATION + /// Serialized result sets contain a short signature which can't be forged + /// or replayed across different game sessions. A result set can be serialized + /// on the local client, transmitted to other players via your game networking, + /// and deserialized by the remote players. This is a secure way of preventing + /// hackers from lying about posessing rare/high-value items. + /// Serializes a result set with signature bytes to an output buffer. Pass + /// NULL as an output buffer to get the required size via punOutBufferSize. + /// The size of a serialized result depends on the number items which are being + /// serialized. When securely transmitting items to other players, it is + /// recommended to use "GetItemsByID" first to create a minimal result set. + /// Results have a built-in timestamp which will be considered "expired" after + /// an hour has elapsed. See DeserializeResult for expiration handling. + /// + public static bool SerializeResult(SteamInventoryResult_t resultHandle, byte[] pOutBuffer, out uint punOutBufferSize) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_SerializeResult(CSteamAPIContext.GetSteamInventory(), resultHandle, pOutBuffer, out punOutBufferSize); + } + + /// + /// Deserializes a result set and verifies the signature bytes. Returns false + /// if bRequireFullOnlineVerify is set but Steam is running in Offline mode. + /// Otherwise returns true and then delivers error codes via GetResultStatus. + /// The bRESERVED_MUST_BE_FALSE flag is reserved for future use and should not + /// be set to true by your game at this time. + /// DeserializeResult has a potential soft-failure mode where the handle status + /// is set to k_EResultExpired. GetResultItems() still succeeds in this mode. + /// The "expired" result could indicate that the data may be out of date - not + /// just due to timed expiration (one hour), but also because one of the items + /// in the result set may have been traded or consumed since the result set was + /// generated. You could compare the timestamp from GetResultTimestamp() to + /// ISteamUtils::GetServerRealTime() to determine how old the data is. You could + /// simply ignore the "expired" result code and continue as normal, or you + /// could challenge the player with expired data to send an updated result set. + /// + public static bool DeserializeResult(out SteamInventoryResult_t pOutResultHandle, byte[] pBuffer, uint unBufferSize, bool bRESERVED_MUST_BE_FALSE = false) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_DeserializeResult(CSteamAPIContext.GetSteamInventory(), out pOutResultHandle, pBuffer, unBufferSize, bRESERVED_MUST_BE_FALSE); + } + + /// + /// INVENTORY ASYNC MODIFICATION + /// GenerateItems() creates one or more items and then generates a SteamInventoryCallback_t + /// notification with a matching nCallbackContext parameter. This API is only intended + /// for prototyping - it is only usable by Steam accounts that belong to the publisher group + /// for your game. + /// If punArrayQuantity is not NULL, it should be the same length as pArrayItems and should + /// describe the quantity of each item to generate. + /// + public static bool GenerateItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayItemDefs, uint[] punArrayQuantity, uint unArrayLength) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_GenerateItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pArrayItemDefs, punArrayQuantity, unArrayLength); + } + + /// + /// GrantPromoItems() checks the list of promotional items for which the user may be eligible + /// and grants the items (one time only). On success, the result set will include items which + /// were granted, if any. If no items were granted because the user isn't eligible for any + /// promotions, this is still considered a success. + /// + public static bool GrantPromoItems(out SteamInventoryResult_t pResultHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_GrantPromoItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle); + } + + /// + /// AddPromoItem() / AddPromoItems() are restricted versions of GrantPromoItems(). Instead of + /// scanning for all eligible promotional items, the check is restricted to a single item + /// definition or set of item definitions. This can be useful if your game has custom UI for + /// showing a specific promo item to the user. + /// + public static bool AddPromoItem(out SteamInventoryResult_t pResultHandle, SteamItemDef_t itemDef) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_AddPromoItem(CSteamAPIContext.GetSteamInventory(), out pResultHandle, itemDef); + } + + public static bool AddPromoItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayItemDefs, uint unArrayLength) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_AddPromoItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pArrayItemDefs, unArrayLength); + } + + /// + /// ConsumeItem() removes items from the inventory, permanently. They cannot be recovered. + /// Not for the faint of heart - if your game implements item removal at all, a high-friction + /// UI confirmation process is highly recommended. + /// + public static bool ConsumeItem(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemConsume, uint unQuantity) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_ConsumeItem(CSteamAPIContext.GetSteamInventory(), out pResultHandle, itemConsume, unQuantity); + } + + /// + /// ExchangeItems() is an atomic combination of item generation and consumption. + /// It can be used to implement crafting recipes or transmutations, or items which unpack + /// themselves into other items (e.g., a chest). + /// Exchange recipes are defined in the ItemDef, and explicitly list the required item + /// types and resulting generated type. + /// Exchange recipes are evaluated atomically by the Inventory Service; if the supplied + /// components do not match the recipe, or do not contain sufficient quantity, the + /// exchange will fail. + /// + public static bool ExchangeItems(out SteamInventoryResult_t pResultHandle, SteamItemDef_t[] pArrayGenerate, uint[] punArrayGenerateQuantity, uint unArrayGenerateLength, SteamItemInstanceID_t[] pArrayDestroy, uint[] punArrayDestroyQuantity, uint unArrayDestroyLength) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_ExchangeItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pArrayGenerate, punArrayGenerateQuantity, unArrayGenerateLength, pArrayDestroy, punArrayDestroyQuantity, unArrayDestroyLength); + } + + /// + /// TransferItemQuantity() is intended for use with items which are "stackable" (can have + /// quantity greater than one). It can be used to split a stack into two, or to transfer + /// quantity from one stack into another stack of identical items. To split one stack into + /// two, pass k_SteamItemInstanceIDInvalid for itemIdDest and a new item will be generated. + /// + public static bool TransferItemQuantity(out SteamInventoryResult_t pResultHandle, SteamItemInstanceID_t itemIdSource, uint unQuantity, SteamItemInstanceID_t itemIdDest) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_TransferItemQuantity(CSteamAPIContext.GetSteamInventory(), out pResultHandle, itemIdSource, unQuantity, itemIdDest); + } + + /// + /// TIMED DROPS AND PLAYTIME CREDIT + /// Deprecated. Calling this method is not required for proper playtime accounting. + /// + public static void SendItemDropHeartbeat() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamInventory_SendItemDropHeartbeat(CSteamAPIContext.GetSteamInventory()); + } + + /// + /// Playtime credit must be consumed and turned into item drops by your game. Only item + /// definitions which are marked as "playtime item generators" can be spawned. The call + /// will return an empty result set if there is not enough playtime credit for a drop. + /// Your game should call TriggerItemDrop at an appropriate time for the user to receive + /// new items, such as between rounds or while the player is dead. Note that players who + /// hack their clients could modify the value of "dropListDefinition", so do not use it + /// to directly control rarity. + /// See your Steamworks configuration to set playtime drop rates for individual itemdefs. + /// The client library will suppress too-frequent calls to this method. + /// + public static bool TriggerItemDrop(out SteamInventoryResult_t pResultHandle, SteamItemDef_t dropListDefinition) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_TriggerItemDrop(CSteamAPIContext.GetSteamInventory(), out pResultHandle, dropListDefinition); + } + + /// + /// Deprecated. This method is not supported. + /// + public static bool TradeItems(out SteamInventoryResult_t pResultHandle, CSteamID steamIDTradePartner, SteamItemInstanceID_t[] pArrayGive, uint[] pArrayGiveQuantity, uint nArrayGiveLength, SteamItemInstanceID_t[] pArrayGet, uint[] pArrayGetQuantity, uint nArrayGetLength) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_TradeItems(CSteamAPIContext.GetSteamInventory(), out pResultHandle, steamIDTradePartner, pArrayGive, pArrayGiveQuantity, nArrayGiveLength, pArrayGet, pArrayGetQuantity, nArrayGetLength); + } + + /// + /// ITEM DEFINITIONS + /// Item definitions are a mapping of "definition IDs" (integers between 1 and 1000000) + /// to a set of string properties. Some of these properties are required to display items + /// on the Steam community web site. Other properties can be defined by applications. + /// Use of these functions is optional; there is no reason to call LoadItemDefinitions + /// if your game hardcodes the numeric definition IDs (eg, purple face mask = 20, blue + /// weapon mod = 55) and does not allow for adding new item types without a client patch. + /// LoadItemDefinitions triggers the automatic load and refresh of item definitions. + /// Every time new item definitions are available (eg, from the dynamic addition of new + /// item types while players are still in-game), a SteamInventoryDefinitionUpdate_t + /// callback will be fired. + /// + public static bool LoadItemDefinitions() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_LoadItemDefinitions(CSteamAPIContext.GetSteamInventory()); + } + + /// + /// GetItemDefinitionIDs returns the set of all defined item definition IDs (which are + /// defined via Steamworks configuration, and not necessarily contiguous integers). + /// If pItemDefIDs is null, the call will return true and *punItemDefIDsArraySize will + /// contain the total size necessary for a subsequent call. Otherwise, the call will + /// return false if and only if there is not enough space in the output array. + /// + public static bool GetItemDefinitionIDs(SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize) { + InteropHelp.TestIfAvailableClient(); + if (pItemDefIDs != null && pItemDefIDs.Length != punItemDefIDsArraySize) { + throw new System.ArgumentException("pItemDefIDs must be the same size as punItemDefIDsArraySize!"); + } + return NativeMethods.ISteamInventory_GetItemDefinitionIDs(CSteamAPIContext.GetSteamInventory(), pItemDefIDs, ref punItemDefIDsArraySize); + } + + /// + /// GetItemDefinitionProperty returns a string property from a given item definition. + /// Note that some properties (for example, "name") may be localized and will depend + /// on the current Steam language settings (see ISteamApps::GetCurrentGameLanguage). + /// Property names are always composed of ASCII letters, numbers, and/or underscores. + /// Pass a NULL pointer for pchPropertyName to get a comma - separated list of available + /// property names. If pchValueBuffer is NULL, *punValueBufferSize will contain the + /// suggested buffer size. Otherwise it will be the number of bytes actually copied + /// to pchValueBuffer. If the results do not fit in the given buffer, partial + /// results may be copied. + /// + public static bool GetItemDefinitionProperty(SteamItemDef_t iDefinition, string pchPropertyName, out string pchValueBuffer, ref uint punValueBufferSizeOut) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchValueBuffer2 = Marshal.AllocHGlobal((int)punValueBufferSizeOut); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + bool ret = NativeMethods.ISteamInventory_GetItemDefinitionProperty(CSteamAPIContext.GetSteamInventory(), iDefinition, pchPropertyName2, pchValueBuffer2, ref punValueBufferSizeOut); + pchValueBuffer = ret ? InteropHelp.PtrToStringUTF8(pchValueBuffer2) : null; + Marshal.FreeHGlobal(pchValueBuffer2); + return ret; + } + } + + /// + /// Request the list of "eligible" promo items that can be manually granted to the given + /// user. These are promo items of type "manual" that won't be granted automatically. + /// An example usage of this is an item that becomes available every week. + /// + public static SteamAPICall_t RequestEligiblePromoItemDefinitionsIDs(CSteamID steamID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamInventory_RequestEligiblePromoItemDefinitionsIDs(CSteamAPIContext.GetSteamInventory(), steamID); + } + + /// + /// After handling a SteamInventoryEligiblePromoItemDefIDs_t call result, use this + /// function to pull out the list of item definition ids that the user can be + /// manually granted via the AddPromoItems() call. + /// + public static bool GetEligiblePromoItemDefinitionIDs(CSteamID steamID, SteamItemDef_t[] pItemDefIDs, ref uint punItemDefIDsArraySize) { + InteropHelp.TestIfAvailableClient(); + if (pItemDefIDs != null && pItemDefIDs.Length != punItemDefIDsArraySize) { + throw new System.ArgumentException("pItemDefIDs must be the same size as punItemDefIDsArraySize!"); + } + return NativeMethods.ISteamInventory_GetEligiblePromoItemDefinitionIDs(CSteamAPIContext.GetSteamInventory(), steamID, pItemDefIDs, ref punItemDefIDsArraySize); + } + + /// + /// Starts the purchase process for the given item definitions. The callback SteamInventoryStartPurchaseResult_t + /// will be posted if Steam was able to initialize the transaction. + /// Once the purchase has been authorized and completed by the user, the callback SteamInventoryResultReady_t + /// will be posted. + /// + public static SteamAPICall_t StartPurchase(SteamItemDef_t[] pArrayItemDefs, uint[] punArrayQuantity, uint unArrayLength) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamInventory_StartPurchase(CSteamAPIContext.GetSteamInventory(), pArrayItemDefs, punArrayQuantity, unArrayLength); + } + + /// + /// Request current prices for all applicable item definitions + /// + public static SteamAPICall_t RequestPrices() { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamInventory_RequestPrices(CSteamAPIContext.GetSteamInventory()); + } + + /// + /// Returns the number of items with prices. Need to call RequestPrices() first. + /// + public static uint GetNumItemsWithPrices() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_GetNumItemsWithPrices(CSteamAPIContext.GetSteamInventory()); + } + + /// + /// Returns item definition ids and their prices in the user's local currency. + /// Need to call RequestPrices() first. + /// + public static bool GetItemsWithPrices(SteamItemDef_t[] pArrayItemDefs, ulong[] pCurrentPrices, ulong[] pBasePrices, uint unArrayLength) { + InteropHelp.TestIfAvailableClient(); + if (pArrayItemDefs != null && pArrayItemDefs.Length != unArrayLength) { + throw new System.ArgumentException("pArrayItemDefs must be the same size as unArrayLength!"); + } + if (pCurrentPrices != null && pCurrentPrices.Length != unArrayLength) { + throw new System.ArgumentException("pCurrentPrices must be the same size as unArrayLength!"); + } + if (pBasePrices != null && pBasePrices.Length != unArrayLength) { + throw new System.ArgumentException("pBasePrices must be the same size as unArrayLength!"); + } + return NativeMethods.ISteamInventory_GetItemsWithPrices(CSteamAPIContext.GetSteamInventory(), pArrayItemDefs, pCurrentPrices, pBasePrices, unArrayLength); + } + + /// + /// Retrieves the price for the item definition id + /// Returns false if there is no price stored for the item definition. + /// + public static bool GetItemPrice(SteamItemDef_t iDefinition, out ulong pCurrentPrice, out ulong pBasePrice) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_GetItemPrice(CSteamAPIContext.GetSteamInventory(), iDefinition, out pCurrentPrice, out pBasePrice); + } + + /// + /// Create a request to update properties on items + /// + public static SteamInventoryUpdateHandle_t StartUpdateProperties() { + InteropHelp.TestIfAvailableClient(); + return (SteamInventoryUpdateHandle_t)NativeMethods.ISteamInventory_StartUpdateProperties(CSteamAPIContext.GetSteamInventory()); + } + + /// + /// Remove the property on the item + /// + public static bool RemoveProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName) { + InteropHelp.TestIfAvailableClient(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + return NativeMethods.ISteamInventory_RemoveProperty(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2); + } + } + + /// + /// Accessor methods to set properties on items + /// + public static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, string pchPropertyValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) + using (var pchPropertyValue2 = new InteropHelp.UTF8StringHandle(pchPropertyValue)) { + return NativeMethods.ISteamInventory_SetPropertyString(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, pchPropertyValue2); + } + } + + public static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, bool bValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + return NativeMethods.ISteamInventory_SetPropertyBool(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, bValue); + } + } + + public static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, long nValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + return NativeMethods.ISteamInventory_SetPropertyInt64(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, nValue); + } + } + + public static bool SetProperty(SteamInventoryUpdateHandle_t handle, SteamItemInstanceID_t nItemID, string pchPropertyName, float flValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchPropertyName2 = new InteropHelp.UTF8StringHandle(pchPropertyName)) { + return NativeMethods.ISteamInventory_SetPropertyFloat(CSteamAPIContext.GetSteamInventory(), handle, nItemID, pchPropertyName2, flValue); + } + } + + /// + /// Submit the update request by handle + /// + public static bool SubmitUpdateProperties(SteamInventoryUpdateHandle_t handle, out SteamInventoryResult_t pResultHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamInventory_SubmitUpdateProperties(CSteamAPIContext.GetSteamInventory(), handle, out pResultHandle); + } + + public static bool InspectItem(out SteamInventoryResult_t pResultHandle, string pchItemToken) { + InteropHelp.TestIfAvailableClient(); + using (var pchItemToken2 = new InteropHelp.UTF8StringHandle(pchItemToken)) { + return NativeMethods.ISteamInventory_InspectItem(CSteamAPIContext.GetSteamInventory(), out pResultHandle, pchItemToken2); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminventory.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminventory.cs.meta new file mode 100644 index 0000000..b48cef6 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminventory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b3cb110b82106574b8dca4e5a56bbb3e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammatchmaking.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammatchmaking.cs new file mode 100644 index 0000000..5945345 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammatchmaking.cs @@ -0,0 +1,892 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamMatchmaking { + /// + /// game server favorites storage + /// saves basic details about a multiplayer game server locally + /// returns the number of favorites servers the user has stored + /// + public static int GetFavoriteGameCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_GetFavoriteGameCount(CSteamAPIContext.GetSteamMatchmaking()); + } + + /// + /// returns the details of the game server + /// iGame is of range [0,GetFavoriteGameCount()) + /// *pnIP, *pnConnPort are filled in the with IP:port of the game server + /// *punFlags specify whether the game server was stored as an explicit favorite or in the history of connections + /// *pRTime32LastPlayedOnServer is filled in the with the Unix time the favorite was added + /// + public static bool GetFavoriteGame(int iGame, out AppId_t pnAppID, out uint pnIP, out ushort pnConnPort, out ushort pnQueryPort, out uint punFlags, out uint pRTime32LastPlayedOnServer) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_GetFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), iGame, out pnAppID, out pnIP, out pnConnPort, out pnQueryPort, out punFlags, out pRTime32LastPlayedOnServer); + } + + /// + /// adds the game server to the local list; updates the time played of the server if it already exists in the list + /// + public static int AddFavoriteGame(AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags, uint rTime32LastPlayedOnServer) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_AddFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), nAppID, nIP, nConnPort, nQueryPort, unFlags, rTime32LastPlayedOnServer); + } + + /// + /// removes the game server from the local storage; returns true if one was removed + /// + public static bool RemoveFavoriteGame(AppId_t nAppID, uint nIP, ushort nConnPort, ushort nQueryPort, uint unFlags) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_RemoveFavoriteGame(CSteamAPIContext.GetSteamMatchmaking(), nAppID, nIP, nConnPort, nQueryPort, unFlags); + } + + /// + /// ///// + /// Game lobby functions + /// Get a list of relevant lobbies + /// this is an asynchronous request + /// results will be returned by LobbyMatchList_t callback & call result, with the number of lobbies found + /// this will never return lobbies that are full + /// to add more filter, the filter calls below need to be call before each and every RequestLobbyList() call + /// use the CCallResult<> object in steam_api.h to match the SteamAPICall_t call result to a function in an object, e.g. + /// class CMyLobbyListManager + /// { + /// CCallResult<CMyLobbyListManager, LobbyMatchList_t> m_CallResultLobbyMatchList; + /// void FindLobbies() + /// { + /// // SteamMatchmaking()->AddRequestLobbyListFilter*() functions would be called here, before RequestLobbyList() + /// SteamAPICall_t hSteamAPICall = SteamMatchmaking()->RequestLobbyList(); + /// m_CallResultLobbyMatchList.Set( hSteamAPICall, this, &CMyLobbyListManager::OnLobbyMatchList ); + /// } + /// void OnLobbyMatchList( LobbyMatchList_t *pLobbyMatchList, bool bIOFailure ) + /// { + /// // lobby list has be retrieved from Steam back-end, use results + /// } + /// } + /// + public static SteamAPICall_t RequestLobbyList() { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamMatchmaking_RequestLobbyList(CSteamAPIContext.GetSteamMatchmaking()); + } + + /// + /// filters for lobbies + /// this needs to be called before RequestLobbyList() to take effect + /// these are cleared on each call to RequestLobbyList() + /// + public static void AddRequestLobbyListStringFilter(string pchKeyToMatch, string pchValueToMatch, ELobbyComparison eComparisonType) { + InteropHelp.TestIfAvailableClient(); + using (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch)) + using (var pchValueToMatch2 = new InteropHelp.UTF8StringHandle(pchValueToMatch)) { + NativeMethods.ISteamMatchmaking_AddRequestLobbyListStringFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, pchValueToMatch2, eComparisonType); + } + } + + /// + /// numerical comparison + /// + public static void AddRequestLobbyListNumericalFilter(string pchKeyToMatch, int nValueToMatch, ELobbyComparison eComparisonType) { + InteropHelp.TestIfAvailableClient(); + using (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch)) { + NativeMethods.ISteamMatchmaking_AddRequestLobbyListNumericalFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, nValueToMatch, eComparisonType); + } + } + + /// + /// returns results closest to the specified value. Multiple near filters can be added, with early filters taking precedence + /// + public static void AddRequestLobbyListNearValueFilter(string pchKeyToMatch, int nValueToBeCloseTo) { + InteropHelp.TestIfAvailableClient(); + using (var pchKeyToMatch2 = new InteropHelp.UTF8StringHandle(pchKeyToMatch)) { + NativeMethods.ISteamMatchmaking_AddRequestLobbyListNearValueFilter(CSteamAPIContext.GetSteamMatchmaking(), pchKeyToMatch2, nValueToBeCloseTo); + } + } + + /// + /// returns only lobbies with the specified number of slots available + /// + public static void AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmaking_AddRequestLobbyListFilterSlotsAvailable(CSteamAPIContext.GetSteamMatchmaking(), nSlotsAvailable); + } + + /// + /// sets the distance for which we should search for lobbies (based on users IP address to location map on the Steam backed) + /// + public static void AddRequestLobbyListDistanceFilter(ELobbyDistanceFilter eLobbyDistanceFilter) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmaking_AddRequestLobbyListDistanceFilter(CSteamAPIContext.GetSteamMatchmaking(), eLobbyDistanceFilter); + } + + /// + /// sets how many results to return, the lower the count the faster it is to download the lobby results & details to the client + /// + public static void AddRequestLobbyListResultCountFilter(int cMaxResults) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmaking_AddRequestLobbyListResultCountFilter(CSteamAPIContext.GetSteamMatchmaking(), cMaxResults); + } + + public static void AddRequestLobbyListCompatibleMembersFilter(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmaking_AddRequestLobbyListCompatibleMembersFilter(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby); + } + + /// + /// returns the CSteamID of a lobby, as retrieved by a RequestLobbyList call + /// should only be called after a LobbyMatchList_t callback is received + /// iLobby is of the range [0, LobbyMatchList_t::m_nLobbiesMatching) + /// the returned CSteamID::IsValid() will be false if iLobby is out of range + /// + public static CSteamID GetLobbyByIndex(int iLobby) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyByIndex(CSteamAPIContext.GetSteamMatchmaking(), iLobby); + } + + /// + /// Create a lobby on the Steam servers. + /// If private, then the lobby will not be returned by any RequestLobbyList() call; the CSteamID + /// of the lobby will need to be communicated via game channels or via InviteUserToLobby() + /// this is an asynchronous request + /// results will be returned by LobbyCreated_t callback and call result; lobby is joined & ready to use at this point + /// a LobbyEnter_t callback will also be received (since the local user is joining their own lobby) + /// + public static SteamAPICall_t CreateLobby(ELobbyType eLobbyType, int cMaxMembers) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamMatchmaking_CreateLobby(CSteamAPIContext.GetSteamMatchmaking(), eLobbyType, cMaxMembers); + } + + /// + /// Joins an existing lobby + /// this is an asynchronous request + /// results will be returned by LobbyEnter_t callback & call result, check m_EChatRoomEnterResponse to see if was successful + /// lobby metadata is available to use immediately on this call completing + /// + public static SteamAPICall_t JoinLobby(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamMatchmaking_JoinLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby); + } + + /// + /// Leave a lobby; this will take effect immediately on the client side + /// other users in the lobby will be notified by a LobbyChatUpdate_t callback + /// + public static void LeaveLobby(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmaking_LeaveLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby); + } + + /// + /// Invite another user to the lobby + /// the target user will receive a LobbyInvite_t callback + /// will return true if the invite is successfully sent, whether or not the target responds + /// returns false if the local user is not connected to the Steam servers + /// if the other user clicks the join link, a GameLobbyJoinRequested_t will be posted if the user is in-game, + /// or if the game isn't running yet the game will be launched with the parameter +connect_lobby <64-bit lobby id> + /// + public static bool InviteUserToLobby(CSteamID steamIDLobby, CSteamID steamIDInvitee) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_InviteUserToLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDInvitee); + } + + /// + /// Lobby iteration, for viewing details of users in a lobby + /// only accessible if the lobby user is a member of the specified lobby + /// persona information for other lobby members (name, avatar, etc.) will be asynchronously received + /// and accessible via ISteamFriends interface + /// returns the number of users in the specified lobby + /// + public static int GetNumLobbyMembers(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_GetNumLobbyMembers(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby); + } + + /// + /// returns the CSteamID of a user in the lobby + /// iMember is of range [0,GetNumLobbyMembers()) + /// note that the current user must be in a lobby to retrieve CSteamIDs of other users in that lobby + /// + public static CSteamID GetLobbyMemberByIndex(CSteamID steamIDLobby, int iMember) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyMemberByIndex(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iMember); + } + + /// + /// Get data associated with this lobby + /// takes a simple key, and returns the string associated with it + /// "" will be returned if no value is set, or if steamIDLobby is invalid + /// + public static string GetLobbyData(CSteamID steamIDLobby, string pchKey) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamMatchmaking_GetLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2)); + } + } + + /// + /// Sets a key/value pair in the lobby metadata + /// each user in the lobby will be broadcast this new value, and any new users joining will receive any existing data + /// this can be used to set lobby names, map, etc. + /// to reset a key, just set it to "" + /// other users in the lobby will receive notification of the lobby data change via a LobbyDataUpdate_t callback + /// + public static bool SetLobbyData(CSteamID steamIDLobby, string pchKey, string pchValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) + using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) { + return NativeMethods.ISteamMatchmaking_SetLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2, pchValue2); + } + } + + /// + /// returns the number of metadata keys set on the specified lobby + /// + public static int GetLobbyDataCount(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_GetLobbyDataCount(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby); + } + + /// + /// returns a lobby metadata key/values pair by index, of range [0, GetLobbyDataCount()) + /// + public static bool GetLobbyDataByIndex(CSteamID steamIDLobby, int iLobbyData, out string pchKey, int cchKeyBufferSize, out string pchValue, int cchValueBufferSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchKey2 = Marshal.AllocHGlobal(cchKeyBufferSize); + IntPtr pchValue2 = Marshal.AllocHGlobal(cchValueBufferSize); + bool ret = NativeMethods.ISteamMatchmaking_GetLobbyDataByIndex(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iLobbyData, pchKey2, cchKeyBufferSize, pchValue2, cchValueBufferSize); + pchKey = ret ? InteropHelp.PtrToStringUTF8(pchKey2) : null; + Marshal.FreeHGlobal(pchKey2); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + + /// + /// removes a metadata key from the lobby + /// + public static bool DeleteLobbyData(CSteamID steamIDLobby, string pchKey) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + return NativeMethods.ISteamMatchmaking_DeleteLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2); + } + } + + /// + /// Gets per-user metadata for someone in this lobby + /// + public static string GetLobbyMemberData(CSteamID steamIDLobby, CSteamID steamIDUser, string pchKey) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamMatchmaking_GetLobbyMemberData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDUser, pchKey2)); + } + } + + /// + /// Sets per-user metadata (for the local user implicitly) + /// + public static void SetLobbyMemberData(CSteamID steamIDLobby, string pchKey, string pchValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) + using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) { + NativeMethods.ISteamMatchmaking_SetLobbyMemberData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pchKey2, pchValue2); + } + } + + /// + /// Broadcasts a chat message to the all the users in the lobby + /// users in the lobby (including the local user) will receive a LobbyChatMsg_t callback + /// returns true if the message is successfully sent + /// pvMsgBody can be binary or text data, up to 4k + /// if pvMsgBody is text, cubMsgBody should be strlen( text ) + 1, to include the null terminator + /// + public static bool SendLobbyChatMsg(CSteamID steamIDLobby, byte[] pvMsgBody, int cubMsgBody) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_SendLobbyChatMsg(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, pvMsgBody, cubMsgBody); + } + + /// + /// Get a chat message as specified in a LobbyChatMsg_t callback + /// iChatID is the LobbyChatMsg_t::m_iChatID value in the callback + /// *pSteamIDUser is filled in with the CSteamID of the member + /// *pvData is filled in with the message itself + /// return value is the number of bytes written into the buffer + /// + public static int GetLobbyChatEntry(CSteamID steamIDLobby, int iChatID, out CSteamID pSteamIDUser, byte[] pvData, int cubData, out EChatEntryType peChatEntryType) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_GetLobbyChatEntry(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, iChatID, out pSteamIDUser, pvData, cubData, out peChatEntryType); + } + + /// + /// Refreshes metadata for a lobby you're not necessarily in right now + /// you never do this for lobbies you're a member of, only if your + /// this will send down all the metadata associated with a lobby + /// this is an asynchronous call + /// returns false if the local user is not connected to the Steam servers + /// results will be returned by a LobbyDataUpdate_t callback + /// if the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to false + /// + public static bool RequestLobbyData(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_RequestLobbyData(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby); + } + + /// + /// sets the game server associated with the lobby + /// usually at this point, the users will join the specified game server + /// either the IP/Port or the steamID of the game server has to be valid, depending on how you want the clients to be able to connect + /// + public static void SetLobbyGameServer(CSteamID steamIDLobby, uint unGameServerIP, ushort unGameServerPort, CSteamID steamIDGameServer) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmaking_SetLobbyGameServer(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, unGameServerIP, unGameServerPort, steamIDGameServer); + } + + /// + /// returns the details of a game server set in a lobby - returns false if there is no game server set, or that lobby doesn't exist + /// + public static bool GetLobbyGameServer(CSteamID steamIDLobby, out uint punGameServerIP, out ushort punGameServerPort, out CSteamID psteamIDGameServer) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_GetLobbyGameServer(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, out punGameServerIP, out punGameServerPort, out psteamIDGameServer); + } + + /// + /// set the limit on the # of users who can join the lobby + /// + public static bool SetLobbyMemberLimit(CSteamID steamIDLobby, int cMaxMembers) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_SetLobbyMemberLimit(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, cMaxMembers); + } + + /// + /// returns the current limit on the # of users who can join the lobby; returns 0 if no limit is defined + /// + public static int GetLobbyMemberLimit(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_GetLobbyMemberLimit(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby); + } + + /// + /// updates which type of lobby it is + /// only lobbies that are k_ELobbyTypePublic or k_ELobbyTypeInvisible, and are set to joinable, will be returned by RequestLobbyList() calls + /// + public static bool SetLobbyType(CSteamID steamIDLobby, ELobbyType eLobbyType) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_SetLobbyType(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, eLobbyType); + } + + /// + /// sets whether or not a lobby is joinable - defaults to true for a new lobby + /// if set to false, no user can join, even if they are a friend or have been invited + /// + public static bool SetLobbyJoinable(CSteamID steamIDLobby, bool bLobbyJoinable) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_SetLobbyJoinable(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, bLobbyJoinable); + } + + /// + /// returns the current lobby owner + /// you must be a member of the lobby to access this + /// there always one lobby owner - if the current owner leaves, another user will become the owner + /// it is possible (bur rare) to join a lobby just as the owner is leaving, thus entering a lobby with self as the owner + /// + public static CSteamID GetLobbyOwner(CSteamID steamIDLobby) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamMatchmaking_GetLobbyOwner(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby); + } + + /// + /// changes who the lobby owner is + /// you must be the lobby owner for this to succeed, and steamIDNewOwner must be in the lobby + /// after completion, the local user will no longer be the owner + /// + public static bool SetLobbyOwner(CSteamID steamIDLobby, CSteamID steamIDNewOwner) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_SetLobbyOwner(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDNewOwner); + } + + /// + /// link two lobbies for the purposes of checking player compatibility + /// you must be the lobby owner of both lobbies + /// + public static bool SetLinkedLobby(CSteamID steamIDLobby, CSteamID steamIDLobbyDependent) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmaking_SetLinkedLobby(CSteamAPIContext.GetSteamMatchmaking(), steamIDLobby, steamIDLobbyDependent); + } +#if _PS3 + /// + /// changes who the lobby owner is + /// you must be the lobby owner for this to succeed, and steamIDNewOwner must be in the lobby + /// after completion, the local user will no longer be the owner + /// + public static void CheckForPSNGameBootInvite(uint iGameBootAttributes) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmaking_CheckForPSNGameBootInvite(CSteamAPIContext.GetSteamMatchmaking(), iGameBootAttributes); + } +#endif + } + public static class SteamMatchmakingServers { + /// + /// Request a new list of servers of a particular type. These calls each correspond to one of the EMatchMakingType values. + /// Each call allocates a new asynchronous request object. + /// Request object must be released by calling ReleaseRequest( hServerListRequest ) + /// + public static HServerListRequest RequestInternetServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestInternetServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse); + } + + public static HServerListRequest RequestLANServerList(AppId_t iApp, ISteamMatchmakingServerListResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestLANServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, (IntPtr)pRequestServersResponse); + } + + public static HServerListRequest RequestFriendsServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestFriendsServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse); + } + + public static HServerListRequest RequestFavoritesServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestFavoritesServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse); + } + + public static HServerListRequest RequestHistoryServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestHistoryServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse); + } + + public static HServerListRequest RequestSpectatorServerList(AppId_t iApp, MatchMakingKeyValuePair_t[] ppchFilters, uint nFilters, ISteamMatchmakingServerListResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerListRequest)NativeMethods.ISteamMatchmakingServers_RequestSpectatorServerList(CSteamAPIContext.GetSteamMatchmakingServers(), iApp, new MMKVPMarshaller(ppchFilters), nFilters, (IntPtr)pRequestServersResponse); + } + + /// + /// Releases the asynchronous request object and cancels any pending query on it if there's a pending query in progress. + /// RefreshComplete callback is not posted when request is released. + /// + public static void ReleaseRequest(HServerListRequest hServerListRequest) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmakingServers_ReleaseRequest(CSteamAPIContext.GetSteamMatchmakingServers(), hServerListRequest); + } + + /// + /// the filter operation codes that go in the key part of MatchMakingKeyValuePair_t should be one of these: + /// "map" + /// - Server passes the filter if the server is playing the specified map. + /// "gamedataand" + /// - Server passes the filter if the server's game data (ISteamGameServer::SetGameData) contains all of the + /// specified strings. The value field is a comma-delimited list of strings to match. + /// "gamedataor" + /// - Server passes the filter if the server's game data (ISteamGameServer::SetGameData) contains at least one of the + /// specified strings. The value field is a comma-delimited list of strings to match. + /// "gamedatanor" + /// - Server passes the filter if the server's game data (ISteamGameServer::SetGameData) does not contain any + /// of the specified strings. The value field is a comma-delimited list of strings to check. + /// "gametagsand" + /// - Server passes the filter if the server's game tags (ISteamGameServer::SetGameTags) contains all + /// of the specified strings. The value field is a comma-delimited list of strings to check. + /// "gametagsnor" + /// - Server passes the filter if the server's game tags (ISteamGameServer::SetGameTags) does not contain any + /// of the specified strings. The value field is a comma-delimited list of strings to check. + /// "and" (x1 && x2 && ... && xn) + /// "or" (x1 || x2 || ... || xn) + /// "nand" !(x1 && x2 && ... && xn) + /// "nor" !(x1 || x2 || ... || xn) + /// - Performs Boolean operation on the following filters. The operand to this filter specifies + /// the "size" of the Boolean inputs to the operation, in Key/value pairs. (The keyvalue + /// pairs must immediately follow, i.e. this is a prefix logical operator notation.) + /// In the simplest case where Boolean expressions are not nested, this is simply + /// the number of operands. + /// For example, to match servers on a particular map or with a particular tag, would would + /// use these filters. + /// ( server.map == "cp_dustbowl" || server.gametags.contains("payload") ) + /// "or", "2" + /// "map", "cp_dustbowl" + /// "gametagsand", "payload" + /// If logical inputs are nested, then the operand specifies the size of the entire + /// "length" of its operands, not the number of immediate children. + /// ( server.map == "cp_dustbowl" || ( server.gametags.contains("payload") && !server.gametags.contains("payloadrace") ) ) + /// "or", "4" + /// "map", "cp_dustbowl" + /// "and", "2" + /// "gametagsand", "payload" + /// "gametagsnor", "payloadrace" + /// Unary NOT can be achieved using either "nand" or "nor" with a single operand. + /// "addr" + /// - Server passes the filter if the server's query address matches the specified IP or IP:port. + /// "gameaddr" + /// - Server passes the filter if the server's game address matches the specified IP or IP:port. + /// The following filter operations ignore the "value" part of MatchMakingKeyValuePair_t + /// "dedicated" + /// - Server passes the filter if it passed true to SetDedicatedServer. + /// "secure" + /// - Server passes the filter if the server is VAC-enabled. + /// "notfull" + /// - Server passes the filter if the player count is less than the reported max player count. + /// "hasplayers" + /// - Server passes the filter if the player count is greater than zero. + /// "noplayers" + /// - Server passes the filter if it doesn't have any players. + /// "linux" + /// - Server passes the filter if it's a linux server + /// Get details on a given server in the list, you can get the valid range of index + /// values by calling GetServerCount(). You will also receive index values in + /// ISteamMatchmakingServerListResponse::ServerResponded() callbacks + /// + public static gameserveritem_t GetServerDetails(HServerListRequest hRequest, int iServer) { + InteropHelp.TestIfAvailableClient(); + return (gameserveritem_t)Marshal.PtrToStructure(NativeMethods.ISteamMatchmakingServers_GetServerDetails(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest, iServer), typeof(gameserveritem_t)); + } + + /// + /// Cancel an request which is operation on the given list type. You should call this to cancel + /// any in-progress requests before destructing a callback object that may have been passed + /// to one of the above list request calls. Not doing so may result in a crash when a callback + /// occurs on the destructed object. + /// Canceling a query does not release the allocated request handle. + /// The request handle must be released using ReleaseRequest( hRequest ) + /// + public static void CancelQuery(HServerListRequest hRequest) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmakingServers_CancelQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest); + } + + /// + /// Ping every server in your list again but don't update the list of servers + /// Query callback installed when the server list was requested will be used + /// again to post notifications and RefreshComplete, so the callback must remain + /// valid until another RefreshComplete is called on it or the request + /// is released with ReleaseRequest( hRequest ) + /// + public static void RefreshQuery(HServerListRequest hRequest) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmakingServers_RefreshQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest); + } + + /// + /// Returns true if the list is currently refreshing its server list + /// + public static bool IsRefreshing(HServerListRequest hRequest) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmakingServers_IsRefreshing(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest); + } + + /// + /// How many servers in the given list, GetServerDetails above takes 0... GetServerCount() - 1 + /// + public static int GetServerCount(HServerListRequest hRequest) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMatchmakingServers_GetServerCount(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest); + } + + /// + /// Refresh a single server inside of a query (rather than all the servers ) + /// + public static void RefreshServer(HServerListRequest hRequest, int iServer) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmakingServers_RefreshServer(CSteamAPIContext.GetSteamMatchmakingServers(), hRequest, iServer); + } + + /// + /// ----------------------------------------------------------------------------- + /// Queries to individual servers directly via IP/Port + /// ----------------------------------------------------------------------------- + /// Request updated ping time and other details from a single server + /// + public static HServerQuery PingServer(uint unIP, ushort usPort, ISteamMatchmakingPingResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerQuery)NativeMethods.ISteamMatchmakingServers_PingServer(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse); + } + + /// + /// Request the list of players currently playing on a server + /// + public static HServerQuery PlayerDetails(uint unIP, ushort usPort, ISteamMatchmakingPlayersResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerQuery)NativeMethods.ISteamMatchmakingServers_PlayerDetails(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse); + } + + /// + /// Request the list of rules that the server is running (See ISteamGameServer::SetKeyValue() to set the rules server side) + /// + public static HServerQuery ServerRules(uint unIP, ushort usPort, ISteamMatchmakingRulesResponse pRequestServersResponse) { + InteropHelp.TestIfAvailableClient(); + return (HServerQuery)NativeMethods.ISteamMatchmakingServers_ServerRules(CSteamAPIContext.GetSteamMatchmakingServers(), unIP, usPort, (IntPtr)pRequestServersResponse); + } + + /// + /// Cancel an outstanding Ping/Players/Rules query from above. You should call this to cancel + /// any in-progress requests before destructing a callback object that may have been passed + /// to one of the above calls to avoid crashing when callbacks occur. + /// + public static void CancelServerQuery(HServerQuery hServerQuery) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMatchmakingServers_CancelServerQuery(CSteamAPIContext.GetSteamMatchmakingServers(), hServerQuery); + } + } + public static class SteamGameSearch { + /// + /// ============================================================================================= + /// Game Player APIs + /// a keyname and a list of comma separated values: one of which is must be found in order for the match to qualify + /// fails if a search is currently in progress + /// + public static EGameSearchErrorCode_t AddGameSearchParams(string pchKeyToFind, string pchValuesToFind) { + InteropHelp.TestIfAvailableClient(); + using (var pchKeyToFind2 = new InteropHelp.UTF8StringHandle(pchKeyToFind)) + using (var pchValuesToFind2 = new InteropHelp.UTF8StringHandle(pchValuesToFind)) { + return NativeMethods.ISteamGameSearch_AddGameSearchParams(CSteamAPIContext.GetSteamGameSearch(), pchKeyToFind2, pchValuesToFind2); + } + } + + /// + /// all players in lobby enter the queue and await a SearchForGameNotificationCallback_t callback. fails if another search is currently in progress + /// if not the owner of the lobby or search already in progress this call fails + /// periodic callbacks will be sent as queue time estimates change + /// + public static EGameSearchErrorCode_t SearchForGameWithLobby(CSteamID steamIDLobby, int nPlayerMin, int nPlayerMax) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_SearchForGameWithLobby(CSteamAPIContext.GetSteamGameSearch(), steamIDLobby, nPlayerMin, nPlayerMax); + } + + /// + /// user enter the queue and await a SearchForGameNotificationCallback_t callback. fails if another search is currently in progress + /// periodic callbacks will be sent as queue time estimates change + /// + public static EGameSearchErrorCode_t SearchForGameSolo(int nPlayerMin, int nPlayerMax) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_SearchForGameSolo(CSteamAPIContext.GetSteamGameSearch(), nPlayerMin, nPlayerMax); + } + + /// + /// after receiving SearchForGameResultCallback_t, accept or decline the game + /// multiple SearchForGameResultCallback_t will follow as players accept game until the host starts or cancels the game + /// + public static EGameSearchErrorCode_t AcceptGame() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_AcceptGame(CSteamAPIContext.GetSteamGameSearch()); + } + + public static EGameSearchErrorCode_t DeclineGame() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_DeclineGame(CSteamAPIContext.GetSteamGameSearch()); + } + + /// + /// after receiving GameStartedByHostCallback_t get connection details to server + /// + public static EGameSearchErrorCode_t RetrieveConnectionDetails(CSteamID steamIDHost, out string pchConnectionDetails, int cubConnectionDetails) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchConnectionDetails2 = Marshal.AllocHGlobal(cubConnectionDetails); + EGameSearchErrorCode_t ret = NativeMethods.ISteamGameSearch_RetrieveConnectionDetails(CSteamAPIContext.GetSteamGameSearch(), steamIDHost, pchConnectionDetails2, cubConnectionDetails); + pchConnectionDetails = ret != 0 ? InteropHelp.PtrToStringUTF8(pchConnectionDetails2) : null; + Marshal.FreeHGlobal(pchConnectionDetails2); + return ret; + } + + /// + /// leaves queue if still waiting + /// + public static EGameSearchErrorCode_t EndGameSearch() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_EndGameSearch(CSteamAPIContext.GetSteamGameSearch()); + } + + /// + /// ============================================================================================= + /// Game Host APIs + /// a keyname and a list of comma separated values: all the values you allow + /// + public static EGameSearchErrorCode_t SetGameHostParams(string pchKey, string pchValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) + using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) { + return NativeMethods.ISteamGameSearch_SetGameHostParams(CSteamAPIContext.GetSteamGameSearch(), pchKey2, pchValue2); + } + } + + /// + /// set connection details for players once game is found so they can connect to this server + /// + public static EGameSearchErrorCode_t SetConnectionDetails(string pchConnectionDetails, int cubConnectionDetails) { + InteropHelp.TestIfAvailableClient(); + using (var pchConnectionDetails2 = new InteropHelp.UTF8StringHandle(pchConnectionDetails)) { + return NativeMethods.ISteamGameSearch_SetConnectionDetails(CSteamAPIContext.GetSteamGameSearch(), pchConnectionDetails2, cubConnectionDetails); + } + } + + /// + /// mark server as available for more players with nPlayerMin,nPlayerMax desired + /// accept no lobbies with playercount greater than nMaxTeamSize + /// the set of lobbies returned must be partitionable into teams of no more than nMaxTeamSize + /// RequestPlayersForGameNotificationCallback_t callback will be sent when the search has started + /// multple RequestPlayersForGameResultCallback_t callbacks will follow when players are found + /// + public static EGameSearchErrorCode_t RequestPlayersForGame(int nPlayerMin, int nPlayerMax, int nMaxTeamSize) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_RequestPlayersForGame(CSteamAPIContext.GetSteamGameSearch(), nPlayerMin, nPlayerMax, nMaxTeamSize); + } + + /// + /// accept the player list and release connection details to players + /// players will only be given connection details and host steamid when this is called + /// ( allows host to accept after all players confirm, some confirm, or none confirm. decision is entirely up to the host ) + /// + public static EGameSearchErrorCode_t HostConfirmGameStart(ulong ullUniqueGameID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_HostConfirmGameStart(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID); + } + + /// + /// cancel request and leave the pool of game hosts looking for players + /// if a set of players has already been sent to host, all players will receive SearchForGameHostFailedToConfirm_t + /// + public static EGameSearchErrorCode_t CancelRequestPlayersForGame() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_CancelRequestPlayersForGame(CSteamAPIContext.GetSteamGameSearch()); + } + + /// + /// submit a result for one player. does not end the game. ullUniqueGameID continues to describe this game + /// + public static EGameSearchErrorCode_t SubmitPlayerResult(ulong ullUniqueGameID, CSteamID steamIDPlayer, EPlayerResult_t EPlayerResult) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_SubmitPlayerResult(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID, steamIDPlayer, EPlayerResult); + } + + /// + /// ends the game. no further SubmitPlayerResults for ullUniqueGameID will be accepted + /// any future requests will provide a new ullUniqueGameID + /// + public static EGameSearchErrorCode_t EndGame(ulong ullUniqueGameID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamGameSearch_EndGame(CSteamAPIContext.GetSteamGameSearch(), ullUniqueGameID); + } + } + public static class SteamParties { + /// + /// ============================================================================================= + /// Party Client APIs + /// Enumerate any active beacons for parties you may wish to join + /// + public static uint GetNumActiveBeacons() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParties_GetNumActiveBeacons(CSteamAPIContext.GetSteamParties()); + } + + public static PartyBeaconID_t GetBeaconByIndex(uint unIndex) { + InteropHelp.TestIfAvailableClient(); + return (PartyBeaconID_t)NativeMethods.ISteamParties_GetBeaconByIndex(CSteamAPIContext.GetSteamParties(), unIndex); + } + + public static bool GetBeaconDetails(PartyBeaconID_t ulBeaconID, out CSteamID pSteamIDBeaconOwner, out SteamPartyBeaconLocation_t pLocation, out string pchMetadata, int cchMetadata) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchMetadata2 = Marshal.AllocHGlobal(cchMetadata); + bool ret = NativeMethods.ISteamParties_GetBeaconDetails(CSteamAPIContext.GetSteamParties(), ulBeaconID, out pSteamIDBeaconOwner, out pLocation, pchMetadata2, cchMetadata); + pchMetadata = ret ? InteropHelp.PtrToStringUTF8(pchMetadata2) : null; + Marshal.FreeHGlobal(pchMetadata2); + return ret; + } + + /// + /// Join an open party. Steam will reserve one beacon slot for your SteamID, + /// and return the necessary JoinGame string for you to use to connect + /// + public static SteamAPICall_t JoinParty(PartyBeaconID_t ulBeaconID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamParties_JoinParty(CSteamAPIContext.GetSteamParties(), ulBeaconID); + } + + /// + /// ============================================================================================= + /// Party Host APIs + /// Get a list of possible beacon locations + /// + public static bool GetNumAvailableBeaconLocations(out uint puNumLocations) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParties_GetNumAvailableBeaconLocations(CSteamAPIContext.GetSteamParties(), out puNumLocations); + } + + public static bool GetAvailableBeaconLocations(SteamPartyBeaconLocation_t[] pLocationList, uint uMaxNumLocations) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParties_GetAvailableBeaconLocations(CSteamAPIContext.GetSteamParties(), pLocationList, uMaxNumLocations); + } + + /// + /// Create a new party beacon and activate it in the selected location. + /// unOpenSlots is the maximum number of users that Steam will send to you. + /// When people begin responding to your beacon, Steam will send you + /// PartyReservationCallback_t callbacks to let you know who is on the way. + /// + public static SteamAPICall_t CreateBeacon(uint unOpenSlots, ref SteamPartyBeaconLocation_t pBeaconLocation, string pchConnectString, string pchMetadata) { + InteropHelp.TestIfAvailableClient(); + using (var pchConnectString2 = new InteropHelp.UTF8StringHandle(pchConnectString)) + using (var pchMetadata2 = new InteropHelp.UTF8StringHandle(pchMetadata)) { + return (SteamAPICall_t)NativeMethods.ISteamParties_CreateBeacon(CSteamAPIContext.GetSteamParties(), unOpenSlots, ref pBeaconLocation, pchConnectString2, pchMetadata2); + } + } + + /// + /// Call this function when a user that had a reservation (see callback below) + /// has successfully joined your party. + /// Steam will manage the remaining open slots automatically. + /// + public static void OnReservationCompleted(PartyBeaconID_t ulBeacon, CSteamID steamIDUser) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamParties_OnReservationCompleted(CSteamAPIContext.GetSteamParties(), ulBeacon, steamIDUser); + } + + /// + /// To cancel a reservation (due to timeout or user input), call this. + /// Steam will open a new reservation slot. + /// Note: The user may already be in-flight to your game, so it's possible they will still connect and try to join your party. + /// + public static void CancelReservation(PartyBeaconID_t ulBeacon, CSteamID steamIDUser) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamParties_CancelReservation(CSteamAPIContext.GetSteamParties(), ulBeacon, steamIDUser); + } + + /// + /// Change the number of open beacon reservation slots. + /// Call this if, for example, someone without a reservation joins your party (eg a friend, or via your own matchmaking system). + /// + public static SteamAPICall_t ChangeNumOpenSlots(PartyBeaconID_t ulBeacon, uint unOpenSlots) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamParties_ChangeNumOpenSlots(CSteamAPIContext.GetSteamParties(), ulBeacon, unOpenSlots); + } + + /// + /// Turn off the beacon. + /// + public static bool DestroyBeacon(PartyBeaconID_t ulBeacon) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParties_DestroyBeacon(CSteamAPIContext.GetSteamParties(), ulBeacon); + } + + /// + /// Utils + /// + public static bool GetBeaconLocationData(SteamPartyBeaconLocation_t BeaconLocation, ESteamPartyBeaconLocationData eData, out string pchDataStringOut, int cchDataStringOut) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchDataStringOut2 = Marshal.AllocHGlobal(cchDataStringOut); + bool ret = NativeMethods.ISteamParties_GetBeaconLocationData(CSteamAPIContext.GetSteamParties(), BeaconLocation, eData, pchDataStringOut2, cchDataStringOut); + pchDataStringOut = ret ? InteropHelp.PtrToStringUTF8(pchDataStringOut2) : null; + Marshal.FreeHGlobal(pchDataStringOut2); + return ret; + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammatchmaking.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammatchmaking.cs.meta new file mode 100644 index 0000000..4ccb6fa --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammatchmaking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6511b3ce700864d46ab81d101aac5560 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusic.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusic.cs new file mode 100644 index 0000000..7568da4 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusic.cs @@ -0,0 +1,69 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamMusic { + public static bool BIsEnabled() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusic_BIsEnabled(CSteamAPIContext.GetSteamMusic()); + } + + public static bool BIsPlaying() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusic_BIsPlaying(CSteamAPIContext.GetSteamMusic()); + } + + public static AudioPlayback_Status GetPlaybackStatus() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusic_GetPlaybackStatus(CSteamAPIContext.GetSteamMusic()); + } + + public static void Play() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMusic_Play(CSteamAPIContext.GetSteamMusic()); + } + + public static void Pause() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMusic_Pause(CSteamAPIContext.GetSteamMusic()); + } + + public static void PlayPrevious() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMusic_PlayPrevious(CSteamAPIContext.GetSteamMusic()); + } + + public static void PlayNext() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMusic_PlayNext(CSteamAPIContext.GetSteamMusic()); + } + + /// + /// volume is between 0.0 and 1.0 + /// + public static void SetVolume(float flVolume) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamMusic_SetVolume(CSteamAPIContext.GetSteamMusic(), flVolume); + } + + public static float GetVolume() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusic_GetVolume(CSteamAPIContext.GetSteamMusic()); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusic.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusic.cs.meta new file mode 100644 index 0000000..e2729dd --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusic.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 72776072787328946ad6c1c1b0f54e0d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusicremote.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusicremote.cs new file mode 100644 index 0000000..a56ac7c --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusicremote.cs @@ -0,0 +1,212 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamMusicRemote { + /// + /// Service Definition + /// + public static bool RegisterSteamMusicRemote(string pchName) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamMusicRemote_RegisterSteamMusicRemote(CSteamAPIContext.GetSteamMusicRemote(), pchName2); + } + } + + public static bool DeregisterSteamMusicRemote() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_DeregisterSteamMusicRemote(CSteamAPIContext.GetSteamMusicRemote()); + } + + public static bool BIsCurrentMusicRemote() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_BIsCurrentMusicRemote(CSteamAPIContext.GetSteamMusicRemote()); + } + + public static bool BActivationSuccess(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_BActivationSuccess(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + public static bool SetDisplayName(string pchDisplayName) { + InteropHelp.TestIfAvailableClient(); + using (var pchDisplayName2 = new InteropHelp.UTF8StringHandle(pchDisplayName)) { + return NativeMethods.ISteamMusicRemote_SetDisplayName(CSteamAPIContext.GetSteamMusicRemote(), pchDisplayName2); + } + } + + public static bool SetPNGIcon_64x64(byte[] pvBuffer, uint cbBufferLength) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_SetPNGIcon_64x64(CSteamAPIContext.GetSteamMusicRemote(), pvBuffer, cbBufferLength); + } + + /// + /// Abilities for the user interface + /// + public static bool EnablePlayPrevious(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_EnablePlayPrevious(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + public static bool EnablePlayNext(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_EnablePlayNext(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + public static bool EnableShuffled(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_EnableShuffled(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + public static bool EnableLooped(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_EnableLooped(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + public static bool EnableQueue(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_EnableQueue(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + public static bool EnablePlaylists(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_EnablePlaylists(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + /// + /// Status + /// + public static bool UpdatePlaybackStatus(AudioPlayback_Status nStatus) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_UpdatePlaybackStatus(CSteamAPIContext.GetSteamMusicRemote(), nStatus); + } + + public static bool UpdateShuffled(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_UpdateShuffled(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + public static bool UpdateLooped(bool bValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_UpdateLooped(CSteamAPIContext.GetSteamMusicRemote(), bValue); + } + + /// + /// volume is between 0.0 and 1.0 + /// + public static bool UpdateVolume(float flValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_UpdateVolume(CSteamAPIContext.GetSteamMusicRemote(), flValue); + } + + /// + /// Current Entry + /// + public static bool CurrentEntryWillChange() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_CurrentEntryWillChange(CSteamAPIContext.GetSteamMusicRemote()); + } + + public static bool CurrentEntryIsAvailable(bool bAvailable) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_CurrentEntryIsAvailable(CSteamAPIContext.GetSteamMusicRemote(), bAvailable); + } + + public static bool UpdateCurrentEntryText(string pchText) { + InteropHelp.TestIfAvailableClient(); + using (var pchText2 = new InteropHelp.UTF8StringHandle(pchText)) { + return NativeMethods.ISteamMusicRemote_UpdateCurrentEntryText(CSteamAPIContext.GetSteamMusicRemote(), pchText2); + } + } + + public static bool UpdateCurrentEntryElapsedSeconds(int nValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_UpdateCurrentEntryElapsedSeconds(CSteamAPIContext.GetSteamMusicRemote(), nValue); + } + + public static bool UpdateCurrentEntryCoverArt(byte[] pvBuffer, uint cbBufferLength) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_UpdateCurrentEntryCoverArt(CSteamAPIContext.GetSteamMusicRemote(), pvBuffer, cbBufferLength); + } + + public static bool CurrentEntryDidChange() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_CurrentEntryDidChange(CSteamAPIContext.GetSteamMusicRemote()); + } + + /// + /// Queue + /// + public static bool QueueWillChange() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_QueueWillChange(CSteamAPIContext.GetSteamMusicRemote()); + } + + public static bool ResetQueueEntries() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_ResetQueueEntries(CSteamAPIContext.GetSteamMusicRemote()); + } + + public static bool SetQueueEntry(int nID, int nPosition, string pchEntryText) { + InteropHelp.TestIfAvailableClient(); + using (var pchEntryText2 = new InteropHelp.UTF8StringHandle(pchEntryText)) { + return NativeMethods.ISteamMusicRemote_SetQueueEntry(CSteamAPIContext.GetSteamMusicRemote(), nID, nPosition, pchEntryText2); + } + } + + public static bool SetCurrentQueueEntry(int nID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_SetCurrentQueueEntry(CSteamAPIContext.GetSteamMusicRemote(), nID); + } + + public static bool QueueDidChange() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_QueueDidChange(CSteamAPIContext.GetSteamMusicRemote()); + } + + /// + /// Playlist + /// + public static bool PlaylistWillChange() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_PlaylistWillChange(CSteamAPIContext.GetSteamMusicRemote()); + } + + public static bool ResetPlaylistEntries() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_ResetPlaylistEntries(CSteamAPIContext.GetSteamMusicRemote()); + } + + public static bool SetPlaylistEntry(int nID, int nPosition, string pchEntryText) { + InteropHelp.TestIfAvailableClient(); + using (var pchEntryText2 = new InteropHelp.UTF8StringHandle(pchEntryText)) { + return NativeMethods.ISteamMusicRemote_SetPlaylistEntry(CSteamAPIContext.GetSteamMusicRemote(), nID, nPosition, pchEntryText2); + } + } + + public static bool SetCurrentPlaylistEntry(int nID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_SetCurrentPlaylistEntry(CSteamAPIContext.GetSteamMusicRemote(), nID); + } + + public static bool PlaylistDidChange() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamMusicRemote_PlaylistDidChange(CSteamAPIContext.GetSteamMusicRemote()); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusicremote.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusicremote.cs.meta new file mode 100644 index 0000000..3ab0241 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusicremote.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 288337a492146b7469b28813c4cb20ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworking.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworking.cs new file mode 100644 index 0000000..afed66e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworking.cs @@ -0,0 +1,270 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamNetworking { + /// + /// ////////////////////////////////////////////////////////////////////////////////////////// + /// UDP-style (connectionless) networking interface. These functions send messages using + /// an API organized around the destination. Reliable and unreliable messages are supported. + /// For a more TCP-style interface (meaning you have a connection handle), see the functions below. + /// Both interface styles can send both reliable and unreliable messages. + /// Automatically establishes NAT-traversing or Relay server connections + /// These APIs are deprecated, and may be removed in a future version of the Steamworks + /// SDK. See ISteamNetworkingMessages. + /// Sends a P2P packet to the specified user + /// UDP-like, unreliable and a max packet size of 1200 bytes + /// the first packet send may be delayed as the NAT-traversal code runs + /// if we can't get through to the user, an error will be posted via the callback P2PSessionConnectFail_t + /// see EP2PSend enum above for the descriptions of the different ways of sending packets + /// nChannel is a routing number you can use to help route message to different systems - you'll have to call ReadP2PPacket() + /// with the same channel number in order to retrieve the data on the other end + /// using different channels to talk to the same user will still use the same underlying p2p connection, saving on resources + /// + public static bool SendP2PPacket(CSteamID steamIDRemote, byte[] pubData, uint cubData, EP2PSend eP2PSendType, int nChannel = 0) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_SendP2PPacket(CSteamAPIContext.GetSteamNetworking(), steamIDRemote, pubData, cubData, eP2PSendType, nChannel); + } + + /// + /// returns true if any data is available for read, and the amount of data that will need to be read + /// + public static bool IsP2PPacketAvailable(out uint pcubMsgSize, int nChannel = 0) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_IsP2PPacketAvailable(CSteamAPIContext.GetSteamNetworking(), out pcubMsgSize, nChannel); + } + + /// + /// reads in a packet that has been sent from another user via SendP2PPacket() + /// returns the size of the message and the steamID of the user who sent it in the last two parameters + /// if the buffer passed in is too small, the message will be truncated + /// this call is not blocking, and will return false if no data is available + /// + public static bool ReadP2PPacket(byte[] pubDest, uint cubDest, out uint pcubMsgSize, out CSteamID psteamIDRemote, int nChannel = 0) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_ReadP2PPacket(CSteamAPIContext.GetSteamNetworking(), pubDest, cubDest, out pcubMsgSize, out psteamIDRemote, nChannel); + } + + /// + /// AcceptP2PSessionWithUser() should only be called in response to a P2PSessionRequest_t callback + /// P2PSessionRequest_t will be posted if another user tries to send you a packet that you haven't talked to yet + /// if you don't want to talk to the user, just ignore the request + /// if the user continues to send you packets, another P2PSessionRequest_t will be posted periodically + /// this may be called multiple times for a single user + /// (if you've called SendP2PPacket() on the other user, this implicitly accepts the session request) + /// + public static bool AcceptP2PSessionWithUser(CSteamID steamIDRemote) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_AcceptP2PSessionWithUser(CSteamAPIContext.GetSteamNetworking(), steamIDRemote); + } + + /// + /// call CloseP2PSessionWithUser() when you're done talking to a user, will free up resources under-the-hood + /// if the remote user tries to send data to you again, another P2PSessionRequest_t callback will be posted + /// + public static bool CloseP2PSessionWithUser(CSteamID steamIDRemote) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_CloseP2PSessionWithUser(CSteamAPIContext.GetSteamNetworking(), steamIDRemote); + } + + /// + /// call CloseP2PChannelWithUser() when you're done talking to a user on a specific channel. Once all channels + /// open channels to a user have been closed, the open session to the user will be closed and new data from this + /// user will trigger a P2PSessionRequest_t callback + /// + public static bool CloseP2PChannelWithUser(CSteamID steamIDRemote, int nChannel) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_CloseP2PChannelWithUser(CSteamAPIContext.GetSteamNetworking(), steamIDRemote, nChannel); + } + + /// + /// fills out P2PSessionState_t structure with details about the underlying connection to the user + /// should only needed for debugging purposes + /// returns false if no connection exists to the specified user + /// + public static bool GetP2PSessionState(CSteamID steamIDRemote, out P2PSessionState_t pConnectionState) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_GetP2PSessionState(CSteamAPIContext.GetSteamNetworking(), steamIDRemote, out pConnectionState); + } + + /// + /// Allow P2P connections to fall back to being relayed through the Steam servers if a direct connection + /// or NAT-traversal cannot be established. Only applies to connections created after setting this value, + /// or to existing connections that need to automatically reconnect after this value is set. + /// P2P packet relay is allowed by default + /// NOTE: This function is deprecated and may be removed in a future version of the SDK. For + /// security purposes, we may decide to relay the traffic to certain peers, even if you pass false + /// to this function, to prevent revealing the client's IP address top another peer. + /// + public static bool AllowP2PPacketRelay(bool bAllow) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_AllowP2PPacketRelay(CSteamAPIContext.GetSteamNetworking(), bAllow); + } + + /// + /// ////////////////////////////////////////////////////////////////////////////////////////// + /// LISTEN / CONNECT connection-oriented interface functions + /// These functions are more like a client-server TCP API. One side is the "server" + /// and "listens" for incoming connections, which then must be "accepted." The "client" + /// initiates a connection by "connecting." Sending and receiving is done through a + /// connection handle. + /// For a more UDP-style interface, where you do not track connection handles but + /// simply send messages to a SteamID, use the UDP-style functions above. + /// Both methods can send both reliable and unreliable methods. + /// These APIs are deprecated, and may be removed in a future version of the Steamworks + /// SDK. See ISteamNetworkingSockets. + /// ////////////////////////////////////////////////////////////////////////////////////////// + /// creates a socket and listens others to connect + /// will trigger a SocketStatusCallback_t callback on another client connecting + /// nVirtualP2PPort is the unique ID that the client will connect to, in case you have multiple ports + /// this can usually just be 0 unless you want multiple sets of connections + /// unIP is the local IP address to bind to + /// pass in 0 if you just want the default local IP + /// unPort is the port to use + /// pass in 0 if you don't want users to be able to connect via IP/Port, but expect to be always peer-to-peer connections only + /// + public static SNetListenSocket_t CreateListenSocket(int nVirtualP2PPort, SteamIPAddress_t nIP, ushort nPort, bool bAllowUseOfPacketRelay) { + InteropHelp.TestIfAvailableClient(); + return (SNetListenSocket_t)NativeMethods.ISteamNetworking_CreateListenSocket(CSteamAPIContext.GetSteamNetworking(), nVirtualP2PPort, nIP, nPort, bAllowUseOfPacketRelay); + } + + /// + /// creates a socket and begin connection to a remote destination + /// can connect via a known steamID (client or game server), or directly to an IP + /// on success will trigger a SocketStatusCallback_t callback + /// on failure or timeout will trigger a SocketStatusCallback_t callback with a failure code in m_eSNetSocketState + /// + public static SNetSocket_t CreateP2PConnectionSocket(CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay) { + InteropHelp.TestIfAvailableClient(); + return (SNetSocket_t)NativeMethods.ISteamNetworking_CreateP2PConnectionSocket(CSteamAPIContext.GetSteamNetworking(), steamIDTarget, nVirtualPort, nTimeoutSec, bAllowUseOfPacketRelay); + } + + public static SNetSocket_t CreateConnectionSocket(SteamIPAddress_t nIP, ushort nPort, int nTimeoutSec) { + InteropHelp.TestIfAvailableClient(); + return (SNetSocket_t)NativeMethods.ISteamNetworking_CreateConnectionSocket(CSteamAPIContext.GetSteamNetworking(), nIP, nPort, nTimeoutSec); + } + + /// + /// disconnects the connection to the socket, if any, and invalidates the handle + /// any unread data on the socket will be thrown away + /// if bNotifyRemoteEnd is set, socket will not be completely destroyed until the remote end acknowledges the disconnect + /// + public static bool DestroySocket(SNetSocket_t hSocket, bool bNotifyRemoteEnd) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_DestroySocket(CSteamAPIContext.GetSteamNetworking(), hSocket, bNotifyRemoteEnd); + } + + /// + /// destroying a listen socket will automatically kill all the regular sockets generated from it + /// + public static bool DestroyListenSocket(SNetListenSocket_t hSocket, bool bNotifyRemoteEnd) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_DestroyListenSocket(CSteamAPIContext.GetSteamNetworking(), hSocket, bNotifyRemoteEnd); + } + + /// + /// sending data + /// must be a handle to a connected socket + /// data is all sent via UDP, and thus send sizes are limited to 1200 bytes; after this, many routers will start dropping packets + /// use the reliable flag with caution; although the resend rate is pretty aggressive, + /// it can still cause stalls in receiving data (like TCP) + /// + public static bool SendDataOnSocket(SNetSocket_t hSocket, byte[] pubData, uint cubData, bool bReliable) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_SendDataOnSocket(CSteamAPIContext.GetSteamNetworking(), hSocket, pubData, cubData, bReliable); + } + + /// + /// receiving data + /// returns false if there is no data remaining + /// fills out *pcubMsgSize with the size of the next message, in bytes + /// + public static bool IsDataAvailableOnSocket(SNetSocket_t hSocket, out uint pcubMsgSize) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_IsDataAvailableOnSocket(CSteamAPIContext.GetSteamNetworking(), hSocket, out pcubMsgSize); + } + + /// + /// fills in pubDest with the contents of the message + /// messages are always complete, of the same size as was sent (i.e. packetized, not streaming) + /// if *pcubMsgSize < cubDest, only partial data is written + /// returns false if no data is available + /// + public static bool RetrieveDataFromSocket(SNetSocket_t hSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_RetrieveDataFromSocket(CSteamAPIContext.GetSteamNetworking(), hSocket, pubDest, cubDest, out pcubMsgSize); + } + + /// + /// checks for data from any socket that has been connected off this listen socket + /// returns false if there is no data remaining + /// fills out *pcubMsgSize with the size of the next message, in bytes + /// fills out *phSocket with the socket that data is available on + /// + public static bool IsDataAvailable(SNetListenSocket_t hListenSocket, out uint pcubMsgSize, out SNetSocket_t phSocket) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_IsDataAvailable(CSteamAPIContext.GetSteamNetworking(), hListenSocket, out pcubMsgSize, out phSocket); + } + + /// + /// retrieves data from any socket that has been connected off this listen socket + /// fills in pubDest with the contents of the message + /// messages are always complete, of the same size as was sent (i.e. packetized, not streaming) + /// if *pcubMsgSize < cubDest, only partial data is written + /// returns false if no data is available + /// fills out *phSocket with the socket that data is available on + /// + public static bool RetrieveData(SNetListenSocket_t hListenSocket, byte[] pubDest, uint cubDest, out uint pcubMsgSize, out SNetSocket_t phSocket) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_RetrieveData(CSteamAPIContext.GetSteamNetworking(), hListenSocket, pubDest, cubDest, out pcubMsgSize, out phSocket); + } + + /// + /// returns information about the specified socket, filling out the contents of the pointers + /// + public static bool GetSocketInfo(SNetSocket_t hSocket, out CSteamID pSteamIDRemote, out int peSocketStatus, out SteamIPAddress_t punIPRemote, out ushort punPortRemote) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_GetSocketInfo(CSteamAPIContext.GetSteamNetworking(), hSocket, out pSteamIDRemote, out peSocketStatus, out punIPRemote, out punPortRemote); + } + + /// + /// returns which local port the listen socket is bound to + /// *pnIP and *pnPort will be 0 if the socket is set to listen for P2P connections only + /// + public static bool GetListenSocketInfo(SNetListenSocket_t hListenSocket, out SteamIPAddress_t pnIP, out ushort pnPort) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_GetListenSocketInfo(CSteamAPIContext.GetSteamNetworking(), hListenSocket, out pnIP, out pnPort); + } + + /// + /// returns true to describe how the socket ended up connecting + /// + public static ESNetSocketConnectionType GetSocketConnectionType(SNetSocket_t hSocket) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_GetSocketConnectionType(CSteamAPIContext.GetSteamNetworking(), hSocket); + } + + /// + /// max packet size, in bytes + /// + public static int GetMaxPacketSize(SNetSocket_t hSocket) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworking_GetMaxPacketSize(CSteamAPIContext.GetSteamNetworking(), hSocket); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworking.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworking.cs.meta new file mode 100644 index 0000000..85d2bde --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15b6f39e728f43c4b85c79fd3d6e6ecb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingmessages.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingmessages.cs new file mode 100644 index 0000000..db8e2c1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingmessages.cs @@ -0,0 +1,139 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamNetworkingMessages { + /// + /// / Sends a message to the specified host. If we don't already have a session with that user, + /// / a session is implicitly created. There might be some handshaking that needs to happen + /// / before we can actually begin sending message data. If this handshaking fails and we can't + /// / get through, an error will be posted via the callback SteamNetworkingMessagesSessionFailed_t. + /// / There is no notification when the operation succeeds. (You should have the peer send a reply + /// / for this purpose.) + /// / + /// / Sending a message to a host will also implicitly accept any incoming connection from that host. + /// / + /// / nSendFlags is a bitmask of k_nSteamNetworkingSend_xxx options + /// / + /// / nRemoteChannel is a routing number you can use to help route message to different systems. + /// / You'll have to call ReceiveMessagesOnChannel() with the same channel number in order to retrieve + /// / the data on the other end. + /// / + /// / Using different channels to talk to the same user will still use the same underlying + /// / connection, saving on resources. If you don't need this feature, use 0. + /// / Otherwise, small integers are the most efficient. + /// / + /// / It is guaranteed that reliable messages to the same host on the same channel + /// / will be be received by the remote host (if they are received at all) exactly once, + /// / and in the same order that they were sent. + /// / + /// / NO other order guarantees exist! In particular, unreliable messages may be dropped, + /// / received out of order with respect to each other and with respect to reliable data, + /// / or may be received multiple times. Messages on different channels are *not* guaranteed + /// / to be received in the order they were sent. + /// / + /// / A note for those familiar with TCP/IP ports, or converting an existing codebase that + /// / opened multiple sockets: You might notice that there is only one channel, and with + /// / TCP/IP each endpoint has a port number. You can think of the channel number as the + /// / *destination* port. If you need each message to also include a "source port" (so the + /// / recipient can route the reply), then just put that in your message. That is essentially + /// / how UDP works! + /// / + /// / Returns: + /// / - k_EREsultOK on success. + /// / - k_EResultNoConnection, if the session has failed or was closed by the peer and + /// / k_nSteamNetworkingSend_AutoRestartBrokenSession was not specified. (You can + /// / use GetSessionConnectionInfo to get the details.) In order to acknowledge the + /// / broken session and start a new one, you must call CloseSessionWithUser, or you may + /// / repeat the call with k_nSteamNetworkingSend_AutoRestartBrokenSession. See + /// / k_nSteamNetworkingSend_AutoRestartBrokenSession for more details. + /// / - See ISteamNetworkingSockets::SendMessageToConnection for more possible return values + /// + public static EResult SendMessageToUser(ref SteamNetworkingIdentity identityRemote, IntPtr pubData, uint cubData, int nSendFlags, int nRemoteChannel) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingMessages_SendMessageToUser(CSteamAPIContext.GetSteamNetworkingMessages(), ref identityRemote, pubData, cubData, nSendFlags, nRemoteChannel); + } + + /// + /// / Reads the next message that has been sent from another user via SendMessageToUser() on the given channel. + /// / Returns number of messages returned into your list. (0 if no message are available on that channel.) + /// / + /// / When you're done with the message object(s), make sure and call SteamNetworkingMessage_t::Release()! + /// + public static int ReceiveMessagesOnChannel(int nLocalChannel, IntPtr[] ppOutMessages, int nMaxMessages) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingMessages_ReceiveMessagesOnChannel(CSteamAPIContext.GetSteamNetworkingMessages(), nLocalChannel, ppOutMessages, nMaxMessages); + } + + /// + /// / Call this in response to a SteamNetworkingMessagesSessionRequest_t callback. + /// / SteamNetworkingMessagesSessionRequest_t are posted when a user tries to send you a message, + /// / and you haven't tried to talk to them first. If you don't want to talk to them, just ignore + /// / the request. If the user continues to send you messages, SteamNetworkingMessagesSessionRequest_t + /// / callbacks will continue to be posted periodically. + /// / + /// / Returns false if there is no session with the user pending or otherwise. If there is an + /// / existing active session, this function will return true, even if it is not pending. + /// / + /// / Calling SendMessageToUser() will implicitly accepts any pending session request to that user. + /// + public static bool AcceptSessionWithUser(ref SteamNetworkingIdentity identityRemote) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingMessages_AcceptSessionWithUser(CSteamAPIContext.GetSteamNetworkingMessages(), ref identityRemote); + } + + /// + /// / Call this when you're done talking to a user to immediately free up resources under-the-hood. + /// / If the remote user tries to send data to you again, another SteamNetworkingMessagesSessionRequest_t + /// / callback will be posted. + /// / + /// / Note that sessions that go unused for a few minutes are automatically timed out. + /// + public static bool CloseSessionWithUser(ref SteamNetworkingIdentity identityRemote) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingMessages_CloseSessionWithUser(CSteamAPIContext.GetSteamNetworkingMessages(), ref identityRemote); + } + + /// + /// / Call this when you're done talking to a user on a specific channel. Once all + /// / open channels to a user have been closed, the open session to the user will be + /// / closed, and any new data from this user will trigger a + /// / SteamSteamNetworkingMessagesSessionRequest_t callback + /// + public static bool CloseChannelWithUser(ref SteamNetworkingIdentity identityRemote, int nLocalChannel) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingMessages_CloseChannelWithUser(CSteamAPIContext.GetSteamNetworkingMessages(), ref identityRemote, nLocalChannel); + } + + /// + /// / Returns information about the latest state of a connection, if any, with the given peer. + /// / Primarily intended for debugging purposes, but can also be used to get more detailed + /// / failure information. (See SendMessageToUser and k_nSteamNetworkingSend_AutoRestartBrokenSession.) + /// / + /// / Returns the value of SteamNetConnectionInfo_t::m_eState, or k_ESteamNetworkingConnectionState_None + /// / if no connection exists with specified peer. You may pass nullptr for either parameter if + /// / you do not need the corresponding details. Note that sessions time out after a while, + /// / so if a connection fails, or SendMessageToUser returns k_EResultNoConnection, you cannot wait + /// / indefinitely to obtain the reason for failure. + /// + public static ESteamNetworkingConnectionState GetSessionConnectionInfo(ref SteamNetworkingIdentity identityRemote, out SteamNetConnectionInfo_t pConnectionInfo, out SteamNetConnectionRealTimeStatus_t pQuickStatus) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingMessages_GetSessionConnectionInfo(CSteamAPIContext.GetSteamNetworkingMessages(), ref identityRemote, out pConnectionInfo, out pQuickStatus); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingmessages.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingmessages.cs.meta new file mode 100644 index 0000000..369aecc --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingmessages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: abf31235e5c3e35459961b3c09239003 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingsockets.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingsockets.cs new file mode 100644 index 0000000..66bd295 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingsockets.cs @@ -0,0 +1,1111 @@ +#define STEAMNETWORKINGSOCKETS_ENABLE_SDR +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamNetworkingSockets { + /// + /// / Creates a "server" socket that listens for clients to connect to by + /// / calling ConnectByIPAddress, over ordinary UDP (IPv4 or IPv6) + /// / + /// / You must select a specific local port to listen on and set it + /// / the port field of the local address. + /// / + /// / Usually you will set the IP portion of the address to zero (SteamNetworkingIPAddr::Clear()). + /// / This means that you will not bind to any particular local interface (i.e. the same + /// / as INADDR_ANY in plain socket code). Furthermore, if possible the socket will be bound + /// / in "dual stack" mode, which means that it can accept both IPv4 and IPv6 client connections. + /// / If you really do wish to bind a particular interface, then set the local address to the + /// / appropriate IPv4 or IPv6 IP. + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// / + /// / When a client attempts to connect, a SteamNetConnectionStatusChangedCallback_t + /// / will be posted. The connection will be in the connecting state. + /// + public static HSteamListenSocket CreateListenSocketIP(ref SteamNetworkingIPAddr localAddress, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableClient(); + return (HSteamListenSocket)NativeMethods.ISteamNetworkingSockets_CreateListenSocketIP(CSteamAPIContext.GetSteamNetworkingSockets(), ref localAddress, nOptions, pOptions); + } + + /// + /// / Creates a connection and begins talking to a "server" over UDP at the + /// / given IPv4 or IPv6 address. The remote host must be listening with a + /// / matching call to CreateListenSocketIP on the specified port. + /// / + /// / A SteamNetConnectionStatusChangedCallback_t callback will be triggered when we start + /// / connecting, and then another one on either timeout or successful connection. + /// / + /// / If the server does not have any identity configured, then their network address + /// / will be the only identity in use. Or, the network host may provide a platform-specific + /// / identity with or without a valid certificate to authenticate that identity. (These + /// / details will be contained in the SteamNetConnectionStatusChangedCallback_t.) It's + /// / up to your application to decide whether to allow the connection. + /// / + /// / By default, all connections will get basic encryption sufficient to prevent + /// / casual eavesdropping. But note that without certificates (or a shared secret + /// / distributed through some other out-of-band mechanism), you don't have any + /// / way of knowing who is actually on the other end, and thus are vulnerable to + /// / man-in-the-middle attacks. + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamNetConnection ConnectByIPAddress(ref SteamNetworkingIPAddr address, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableClient(); + return (HSteamNetConnection)NativeMethods.ISteamNetworkingSockets_ConnectByIPAddress(CSteamAPIContext.GetSteamNetworkingSockets(), ref address, nOptions, pOptions); + } + + /// + /// / Like CreateListenSocketIP, but clients will connect using ConnectP2P. + /// / + /// / nLocalVirtualPort specifies how clients can connect to this socket using + /// / ConnectP2P. It's very common for applications to only have one listening socket; + /// / in that case, use zero. If you need to open multiple listen sockets and have clients + /// / be able to connect to one or the other, then nLocalVirtualPort should be a small + /// / integer (<1000) unique to each listen socket you create. + /// / + /// / If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess() + /// / when your app initializes. + /// / + /// / If you are listening on a dedicated servers in known data center, + /// / then you can listen using this function instead of CreateHostedDedicatedServerListenSocket, + /// / to allow clients to connect without a ticket. Any user that owns + /// / the app and is signed into Steam will be able to attempt to connect to + /// / your server. Also, a connection attempt may require the client to + /// / be connected to Steam, which is one more moving part that may fail. When + /// / tickets are used, then once a ticket is obtained, a client can connect to + /// / your server even if they got disconnected from Steam or Steam is offline. + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamListenSocket CreateListenSocketP2P(int nLocalVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableClient(); + return (HSteamListenSocket)NativeMethods.ISteamNetworkingSockets_CreateListenSocketP2P(CSteamAPIContext.GetSteamNetworkingSockets(), nLocalVirtualPort, nOptions, pOptions); + } + + /// + /// / Begin connecting to a peer that is identified using a platform-specific identifier. + /// / This uses the default rendezvous service, which depends on the platform and library + /// / configuration. (E.g. on Steam, it goes through the steam backend.) + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// / + /// / To use your own signaling service, see: + /// / - ConnectP2PCustomSignaling + /// / - k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling + /// + public static HSteamNetConnection ConnectP2P(ref SteamNetworkingIdentity identityRemote, int nRemoteVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableClient(); + return (HSteamNetConnection)NativeMethods.ISteamNetworkingSockets_ConnectP2P(CSteamAPIContext.GetSteamNetworkingSockets(), ref identityRemote, nRemoteVirtualPort, nOptions, pOptions); + } + + /// + /// / Accept an incoming connection that has been received on a listen socket. + /// / + /// / When a connection attempt is received (perhaps after a few basic handshake + /// / packets have been exchanged to prevent trivial spoofing), a connection interface + /// / object is created in the k_ESteamNetworkingConnectionState_Connecting state + /// / and a SteamNetConnectionStatusChangedCallback_t is posted. At this point, your + /// / application MUST either accept or close the connection. (It may not ignore it.) + /// / Accepting the connection will transition it either into the connected state, + /// / or the finding route state, depending on the connection type. + /// / + /// / You should take action within a second or two, because accepting the connection is + /// / what actually sends the reply notifying the client that they are connected. If you + /// / delay taking action, from the client's perspective it is the same as the network + /// / being unresponsive, and the client may timeout the connection attempt. In other + /// / words, the client cannot distinguish between a delay caused by network problems + /// / and a delay caused by the application. + /// / + /// / This means that if your application goes for more than a few seconds without + /// / processing callbacks (for example, while loading a map), then there is a chance + /// / that a client may attempt to connect in that interval and fail due to timeout. + /// / + /// / If the application does not respond to the connection attempt in a timely manner, + /// / and we stop receiving communication from the client, the connection attempt will + /// / be timed out locally, transitioning the connection to the + /// / k_ESteamNetworkingConnectionState_ProblemDetectedLocally state. The client may also + /// / close the connection before it is accepted, and a transition to the + /// / k_ESteamNetworkingConnectionState_ClosedByPeer is also possible depending the exact + /// / sequence of events. + /// / + /// / Returns k_EResultInvalidParam if the handle is invalid. + /// / Returns k_EResultInvalidState if the connection is not in the appropriate state. + /// / (Remember that the connection state could change in between the time that the + /// / notification being posted to the queue and when it is received by the application.) + /// / + /// / A note about connection configuration options. If you need to set any configuration + /// / options that are common to all connections accepted through a particular listen + /// / socket, consider setting the options on the listen socket, since such options are + /// / inherited automatically. If you really do need to set options that are connection + /// / specific, it is safe to set them on the connection before accepting the connection. + /// + public static EResult AcceptConnection(HSteamNetConnection hConn) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_AcceptConnection(CSteamAPIContext.GetSteamNetworkingSockets(), hConn); + } + + /// + /// / Disconnects from the remote host and invalidates the connection handle. + /// / Any unread data on the connection is discarded. + /// / + /// / nReason is an application defined code that will be received on the other + /// / end and recorded (when possible) in backend analytics. The value should + /// / come from a restricted range. (See ESteamNetConnectionEnd.) If you don't need + /// / to communicate any information to the remote host, and do not want analytics to + /// / be able to distinguish "normal" connection terminations from "exceptional" ones, + /// / You may pass zero, in which case the generic value of + /// / k_ESteamNetConnectionEnd_App_Generic will be used. + /// / + /// / pszDebug is an optional human-readable diagnostic string that will be received + /// / by the remote host and recorded (when possible) in backend analytics. + /// / + /// / If you wish to put the socket into a "linger" state, where an attempt is made to + /// / flush any remaining sent data, use bEnableLinger=true. Otherwise reliable data + /// / is not flushed. + /// / + /// / If the connection has already ended and you are just freeing up the + /// / connection interface, the reason code, debug string, and linger flag are + /// / ignored. + /// + public static bool CloseConnection(HSteamNetConnection hPeer, int nReason, string pszDebug, bool bEnableLinger) { + InteropHelp.TestIfAvailableClient(); + using (var pszDebug2 = new InteropHelp.UTF8StringHandle(pszDebug)) { + return NativeMethods.ISteamNetworkingSockets_CloseConnection(CSteamAPIContext.GetSteamNetworkingSockets(), hPeer, nReason, pszDebug2, bEnableLinger); + } + } + + /// + /// / Destroy a listen socket. All the connections that were accepting on the listen + /// / socket are closed ungracefully. + /// + public static bool CloseListenSocket(HSteamListenSocket hSocket) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_CloseListenSocket(CSteamAPIContext.GetSteamNetworkingSockets(), hSocket); + } + + /// + /// / Set connection user data. the data is returned in the following places + /// / - You can query it using GetConnectionUserData. + /// / - The SteamNetworkingmessage_t structure. + /// / - The SteamNetConnectionInfo_t structure. + /// / (Which is a member of SteamNetConnectionStatusChangedCallback_t -- but see WARNINGS below!!!!) + /// / + /// / Do you need to set this atomically when the connection is created? + /// / See k_ESteamNetworkingConfig_ConnectionUserData. + /// / + /// / WARNING: Be *very careful* when using the value provided in callbacks structs. + /// / Callbacks are queued, and the value that you will receive in your + /// / callback is the userdata that was effective at the time the callback + /// / was queued. There are subtle race conditions that can hapen if you + /// / don't understand this! + /// / + /// / If any incoming messages for this connection are queued, the userdata + /// / field is updated, so that when when you receive messages (e.g. with + /// / ReceiveMessagesOnConnection), they will always have the very latest + /// / userdata. So the tricky race conditions that can happen with callbacks + /// / do not apply to retrieving messages. + /// / + /// / Returns false if the handle is invalid. + /// + public static bool SetConnectionUserData(HSteamNetConnection hPeer, long nUserData) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_SetConnectionUserData(CSteamAPIContext.GetSteamNetworkingSockets(), hPeer, nUserData); + } + + /// + /// / Fetch connection user data. Returns -1 if handle is invalid + /// / or if you haven't set any userdata on the connection. + /// + public static long GetConnectionUserData(HSteamNetConnection hPeer) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetConnectionUserData(CSteamAPIContext.GetSteamNetworkingSockets(), hPeer); + } + + /// + /// / Set a name for the connection, used mostly for debugging + /// + public static void SetConnectionName(HSteamNetConnection hPeer, string pszName) { + InteropHelp.TestIfAvailableClient(); + using (var pszName2 = new InteropHelp.UTF8StringHandle(pszName)) { + NativeMethods.ISteamNetworkingSockets_SetConnectionName(CSteamAPIContext.GetSteamNetworkingSockets(), hPeer, pszName2); + } + } + + /// + /// / Fetch connection name. Returns false if handle is invalid + /// + public static bool GetConnectionName(HSteamNetConnection hPeer, out string pszName, int nMaxLen) { + InteropHelp.TestIfAvailableClient(); + IntPtr pszName2 = Marshal.AllocHGlobal(nMaxLen); + bool ret = NativeMethods.ISteamNetworkingSockets_GetConnectionName(CSteamAPIContext.GetSteamNetworkingSockets(), hPeer, pszName2, nMaxLen); + pszName = ret ? InteropHelp.PtrToStringUTF8(pszName2) : null; + Marshal.FreeHGlobal(pszName2); + return ret; + } + + /// + /// / Send a message to the remote host on the specified connection. + /// / + /// / nSendFlags determines the delivery guarantees that will be provided, + /// / when data should be buffered, etc. E.g. k_nSteamNetworkingSend_Unreliable + /// / + /// / Note that the semantics we use for messages are not precisely + /// / the same as the semantics of a standard "stream" socket. + /// / (SOCK_STREAM) For an ordinary stream socket, the boundaries + /// / between chunks are not considered relevant, and the sizes of + /// / the chunks of data written will not necessarily match up to + /// / the sizes of the chunks that are returned by the reads on + /// / the other end. The remote host might read a partial chunk, + /// / or chunks might be coalesced. For the message semantics + /// / used here, however, the sizes WILL match. Each send call + /// / will match a successful read call on the remote host + /// / one-for-one. If you are porting existing stream-oriented + /// / code to the semantics of reliable messages, your code should + /// / work the same, since reliable message semantics are more + /// / strict than stream semantics. The only caveat is related to + /// / performance: there is per-message overhead to retain the + /// / message sizes, and so if your code sends many small chunks + /// / of data, performance will suffer. Any code based on stream + /// / sockets that does not write excessively small chunks will + /// / work without any changes. + /// / + /// / The pOutMessageNumber is an optional pointer to receive the + /// / message number assigned to the message, if sending was successful. + /// / + /// / Returns: + /// / - k_EResultInvalidParam: invalid connection handle, or the individual message is too big. + /// / (See k_cbMaxSteamNetworkingSocketsMessageSizeSend) + /// / - k_EResultInvalidState: connection is in an invalid state + /// / - k_EResultNoConnection: connection has ended + /// / - k_EResultIgnored: You used k_nSteamNetworkingSend_NoDelay, and the message was dropped because + /// / we were not ready to send it. + /// / - k_EResultLimitExceeded: there was already too much data queued to be sent. + /// / (See k_ESteamNetworkingConfig_SendBufferSize) + /// + public static EResult SendMessageToConnection(HSteamNetConnection hConn, IntPtr pData, uint cbData, int nSendFlags, out long pOutMessageNumber) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_SendMessageToConnection(CSteamAPIContext.GetSteamNetworkingSockets(), hConn, pData, cbData, nSendFlags, out pOutMessageNumber); + } + + /// + /// / Send one or more messages without copying the message payload. + /// / This is the most efficient way to send messages. To use this + /// / function, you must first allocate a message object using + /// / ISteamNetworkingUtils::AllocateMessage. (Do not declare one + /// / on the stack or allocate your own.) + /// / + /// / You should fill in the message payload. You can either let + /// / it allocate the buffer for you and then fill in the payload, + /// / or if you already have a buffer allocated, you can just point + /// / m_pData at your buffer and set the callback to the appropriate function + /// / to free it. Note that if you use your own buffer, it MUST remain valid + /// / until the callback is executed. And also note that your callback can be + /// / invoked at any time from any thread (perhaps even before SendMessages + /// / returns!), so it MUST be fast and threadsafe. + /// / + /// / You MUST also fill in: + /// / - m_conn - the handle of the connection to send the message to + /// / - m_nFlags - bitmask of k_nSteamNetworkingSend_xxx flags. + /// / + /// / All other fields are currently reserved and should not be modified. + /// / + /// / The library will take ownership of the message structures. They may + /// / be modified or become invalid at any time, so you must not read them + /// / after passing them to this function. + /// / + /// / pOutMessageNumberOrResult is an optional array that will receive, + /// / for each message, the message number that was assigned to the message + /// / if sending was successful. If sending failed, then a negative EResult + /// / value is placed into the array. For example, the array will hold + /// / -k_EResultInvalidState if the connection was in an invalid state. + /// / See ISteamNetworkingSockets::SendMessageToConnection for possible + /// / failure codes. + /// + public static void SendMessages(int nMessages, SteamNetworkingMessage_t[] pMessages, long[] pOutMessageNumberOrResult) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamNetworkingSockets_SendMessages(CSteamAPIContext.GetSteamNetworkingSockets(), nMessages, pMessages, pOutMessageNumberOrResult); + } + + /// + /// / Flush any messages waiting on the Nagle timer and send them + /// / at the next transmission opportunity (often that means right now). + /// / + /// / If Nagle is enabled (it's on by default) then when calling + /// / SendMessageToConnection the message will be buffered, up to the Nagle time + /// / before being sent, to merge small messages into the same packet. + /// / (See k_ESteamNetworkingConfig_NagleTime) + /// / + /// / Returns: + /// / k_EResultInvalidParam: invalid connection handle + /// / k_EResultInvalidState: connection is in an invalid state + /// / k_EResultNoConnection: connection has ended + /// / k_EResultIgnored: We weren't (yet) connected, so this operation has no effect. + /// + public static EResult FlushMessagesOnConnection(HSteamNetConnection hConn) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_FlushMessagesOnConnection(CSteamAPIContext.GetSteamNetworkingSockets(), hConn); + } + + /// + /// / Fetch the next available message(s) from the connection, if any. + /// / Returns the number of messages returned into your array, up to nMaxMessages. + /// / If the connection handle is invalid, -1 is returned. + /// / + /// / The order of the messages returned in the array is relevant. + /// / Reliable messages will be received in the order they were sent (and with the + /// / same sizes --- see SendMessageToConnection for on this subtle difference from a stream socket). + /// / + /// / Unreliable messages may be dropped, or delivered out of order with respect to + /// / each other or with respect to reliable messages. The same unreliable message + /// / may be received multiple times. + /// / + /// / If any messages are returned, you MUST call SteamNetworkingMessage_t::Release() on each + /// / of them free up resources after you are done. It is safe to keep the object alive for + /// / a little while (put it into some queue, etc), and you may call Release() from any thread. + /// + public static int ReceiveMessagesOnConnection(HSteamNetConnection hConn, IntPtr[] ppOutMessages, int nMaxMessages) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_ReceiveMessagesOnConnection(CSteamAPIContext.GetSteamNetworkingSockets(), hConn, ppOutMessages, nMaxMessages); + } + + /// + /// / Returns basic information about the high-level state of the connection. + /// + public static bool GetConnectionInfo(HSteamNetConnection hConn, out SteamNetConnectionInfo_t pInfo) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetConnectionInfo(CSteamAPIContext.GetSteamNetworkingSockets(), hConn, out pInfo); + } + + /// + /// / Returns a small set of information about the real-time state of the connection + /// / and the queue status of each lane. + /// / + /// / - pStatus may be NULL if the information is not desired. (E.g. you are only interested + /// / in the lane information.) + /// / - On entry, nLanes specifies the length of the pLanes array. This may be 0 + /// / if you do not wish to receive any lane data. It's OK for this to be smaller than + /// / the total number of configured lanes. + /// / - pLanes points to an array that will receive lane-specific info. It can be NULL + /// / if this is not needed. + /// / + /// / Return value: + /// / - k_EResultNoConnection - connection handle is invalid or connection has been closed. + /// / - k_EResultInvalidParam - nLanes is bad + /// + public static EResult GetConnectionRealTimeStatus(HSteamNetConnection hConn, ref SteamNetConnectionRealTimeStatus_t pStatus, int nLanes, ref SteamNetConnectionRealTimeLaneStatus_t pLanes) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetConnectionRealTimeStatus(CSteamAPIContext.GetSteamNetworkingSockets(), hConn, ref pStatus, nLanes, ref pLanes); + } + + /// + /// / Returns detailed connection stats in text format. Useful + /// / for dumping to a log, etc. + /// / + /// / Returns: + /// / -1 failure (bad connection handle) + /// / 0 OK, your buffer was filled in and '\0'-terminated + /// / >0 Your buffer was either nullptr, or it was too small and the text got truncated. + /// / Try again with a buffer of at least N bytes. + /// + public static int GetDetailedConnectionStatus(HSteamNetConnection hConn, out string pszBuf, int cbBuf) { + InteropHelp.TestIfAvailableClient(); + IntPtr pszBuf2 = Marshal.AllocHGlobal(cbBuf); + int ret = NativeMethods.ISteamNetworkingSockets_GetDetailedConnectionStatus(CSteamAPIContext.GetSteamNetworkingSockets(), hConn, pszBuf2, cbBuf); + pszBuf = ret != -1 ? InteropHelp.PtrToStringUTF8(pszBuf2) : null; + Marshal.FreeHGlobal(pszBuf2); + return ret; + } + + /// + /// / Returns local IP and port that a listen socket created using CreateListenSocketIP is bound to. + /// / + /// / An IPv6 address of ::0 means "any IPv4 or IPv6" + /// / An IPv6 address of ::ffff:0000:0000 means "any IPv4" + /// + public static bool GetListenSocketAddress(HSteamListenSocket hSocket, out SteamNetworkingIPAddr address) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetListenSocketAddress(CSteamAPIContext.GetSteamNetworkingSockets(), hSocket, out address); + } + + /// + /// / Create a pair of connections that are talking to each other, e.g. a loopback connection. + /// / This is very useful for testing, or so that your client/server code can work the same + /// / even when you are running a local "server". + /// / + /// / The two connections will immediately be placed into the connected state, and no callbacks + /// / will be posted immediately. After this, if you close either connection, the other connection + /// / will receive a callback, exactly as if they were communicating over the network. You must + /// / close *both* sides in order to fully clean up the resources! + /// / + /// / By default, internal buffers are used, completely bypassing the network, the chopping up of + /// / messages into packets, encryption, copying the payload, etc. This means that loopback + /// / packets, by default, will not simulate lag or loss. Passing true for bUseNetworkLoopback will + /// / cause the socket pair to send packets through the local network loopback device (127.0.0.1) + /// / on ephemeral ports. Fake lag and loss are supported in this case, and CPU time is expended + /// / to encrypt and decrypt. + /// / + /// / If you wish to assign a specific identity to either connection, you may pass a particular + /// / identity. Otherwise, if you pass nullptr, the respective connection will assume a generic + /// / "localhost" identity. If you use real network loopback, this might be translated to the + /// / actual bound loopback port. Otherwise, the port will be zero. + /// + public static bool CreateSocketPair(out HSteamNetConnection pOutConnection1, out HSteamNetConnection pOutConnection2, bool bUseNetworkLoopback, ref SteamNetworkingIdentity pIdentity1, ref SteamNetworkingIdentity pIdentity2) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_CreateSocketPair(CSteamAPIContext.GetSteamNetworkingSockets(), out pOutConnection1, out pOutConnection2, bUseNetworkLoopback, ref pIdentity1, ref pIdentity2); + } + + /// + /// / Configure multiple outbound messages streams ("lanes") on a connection, and + /// / control head-of-line blocking between them. Messages within a given lane + /// / are always sent in the order they are queued, but messages from different + /// / lanes may be sent out of order. Each lane has its own message number + /// / sequence. The first message sent on each lane will be assigned the number 1. + /// / + /// / Each lane has a "priority". Lower priority lanes will only be processed + /// / when all higher-priority lanes are empty. The magnitudes of the priority + /// / values are not relevant, only their sort order. Higher numeric values + /// / take priority over lower numeric values. + /// / + /// / Each lane also is assigned a weight, which controls the approximate proportion + /// / of the bandwidth that will be consumed by the lane, relative to other lanes + /// / of the same priority. (This is assuming the lane stays busy. An idle lane + /// / does not build up "credits" to be be spent once a message is queued.) + /// / This value is only meaningful as a proportion, relative to other lanes with + /// / the same priority. For lanes with different priorities, the strict priority + /// / order will prevail, and their weights relative to each other are not relevant. + /// / Thus, if a lane has a unique priority value, the weight value for that lane is + /// / not relevant. + /// / + /// / Example: 3 lanes, with priorities [ 0, 10, 10 ] and weights [ (NA), 20, 5 ]. + /// / Messages sent on the first will always be sent first, before messages in the + /// / other two lanes. Its weight value is irrelevant, since there are no other + /// / lanes with priority=0. The other two lanes will share bandwidth, with the second + /// / and third lanes sharing bandwidth using a ratio of approximately 4:1. + /// / (The weights [ NA, 4, 1 ] would be equivalent.) + /// / + /// / Notes: + /// / - At the time of this writing, some code has performance cost that is linear + /// / in the number of lanes, so keep the number of lanes to an absolute minimum. + /// / 3 or so is fine; >8 is a lot. The max number of lanes on Steam is 255, + /// / which is a very large number and not recommended! If you are compiling this + /// / library from source, see STEAMNETWORKINGSOCKETS_MAX_LANES.) + /// / - Lane priority values may be any int. Their absolute value is not relevant, + /// / only the order matters. + /// / - Weights must be positive, and due to implementation details, they are restricted + /// / to 16-bit values. The absolute magnitudes don't matter, just the proportions. + /// / - Messages sent on a lane index other than 0 have a small overhead on the wire, + /// / so for maximum wire efficiency, lane 0 should be the "most common" lane, regardless + /// / of priorities or weights. + /// / - A connection has a single lane by default. Calling this function with + /// / nNumLanes=1 is legal, but pointless, since the priority and weight values are + /// / irrelevant in that case. + /// / - You may reconfigure connection lanes at any time, however reducing the number of + /// / lanes is not allowed. + /// / - Reconfiguring lanes might restart any bandwidth sharing balancing. Usually you + /// / will call this function once, near the start of the connection, perhaps after + /// / exchanging a few messages. + /// / - To assign all lanes the same priority, you may use pLanePriorities=NULL. + /// / - If you wish all lanes with the same priority to share bandwidth equally (or + /// / if no two lanes have the same priority value, and thus priority values are + /// / irrelevant), you may use pLaneWeights=NULL + /// / - Priorities and weights determine the order that messages are SENT on the wire. + /// / There are NO GUARANTEES on the order that messages are RECEIVED! Due to packet + /// / loss, out-of-order delivery, and subtle details of packet serialization, messages + /// / might still be received slightly out-of-order! The *only* strong guarantee is that + /// / *reliable* messages on the *same lane* will be delivered in the order they are sent. + /// / - Each host configures the lanes for the packets they send; the lanes for the flow + /// / in one direction are completely unrelated to the lanes in the opposite direction. + /// / + /// / Return value: + /// / - k_EResultNoConnection - bad hConn + /// / - k_EResultInvalidParam - Invalid number of lanes, bad weights, or you tried to reduce the number of lanes + /// / - k_EResultInvalidState - Connection is already dead, etc + /// / + /// / See also: + /// / SteamNetworkingMessage_t::m_idxLane + /// + public static EResult ConfigureConnectionLanes(HSteamNetConnection hConn, int nNumLanes, out int pLanePriorities, out ushort pLaneWeights) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_ConfigureConnectionLanes(CSteamAPIContext.GetSteamNetworkingSockets(), hConn, nNumLanes, out pLanePriorities, out pLaneWeights); + } + + /// + /// Identity and authentication + /// / Get the identity assigned to this interface. + /// / E.g. on Steam, this is the user's SteamID, or for the gameserver interface, the SteamID assigned + /// / to the gameserver. Returns false and sets the result to an invalid identity if we don't know + /// / our identity yet. (E.g. GameServer has not logged in. On Steam, the user will know their SteamID + /// / even if they are not signed into Steam.) + /// + public static bool GetIdentity(out SteamNetworkingIdentity pIdentity) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetIdentity(CSteamAPIContext.GetSteamNetworkingSockets(), out pIdentity); + } + + /// + /// / Indicate our desire to be ready participate in authenticated communications. + /// / If we are currently not ready, then steps will be taken to obtain the necessary + /// / certificates. (This includes a certificate for us, as well as any CA certificates + /// / needed to authenticate peers.) + /// / + /// / You can call this at program init time if you know that you are going to + /// / be making authenticated connections, so that we will be ready immediately when + /// / those connections are attempted. (Note that essentially all connections require + /// / authentication, with the exception of ordinary UDP connections with authentication + /// / disabled using k_ESteamNetworkingConfig_IP_AllowWithoutAuth.) If you don't call + /// / this function, we will wait until a feature is utilized that that necessitates + /// / these resources. + /// / + /// / You can also call this function to force a retry, if failure has occurred. + /// / Once we make an attempt and fail, we will not automatically retry. + /// / In this respect, the behavior of the system after trying and failing is the same + /// / as before the first attempt: attempting authenticated communication or calling + /// / this function will call the system to attempt to acquire the necessary resources. + /// / + /// / You can use GetAuthenticationStatus or listen for SteamNetAuthenticationStatus_t + /// / to monitor the status. + /// / + /// / Returns the current value that would be returned from GetAuthenticationStatus. + /// + public static ESteamNetworkingAvailability InitAuthentication() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_InitAuthentication(CSteamAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// / Query our readiness to participate in authenticated communications. A + /// / SteamNetAuthenticationStatus_t callback is posted any time this status changes, + /// / but you can use this function to query it at any time. + /// / + /// / The value of SteamNetAuthenticationStatus_t::m_eAvail is returned. If you only + /// / want this high level status, you can pass NULL for pDetails. If you want further + /// / details, pass non-NULL to receive them. + /// + public static ESteamNetworkingAvailability GetAuthenticationStatus(out SteamNetAuthenticationStatus_t pDetails) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetAuthenticationStatus(CSteamAPIContext.GetSteamNetworkingSockets(), out pDetails); + } + + /// + /// Poll groups. A poll group is a set of connections that can be polled efficiently. + /// (In our API, to "poll" a connection means to retrieve all pending messages. We + /// actually don't have an API to "poll" the connection *state*, like BSD sockets.) + /// / Create a new poll group. + /// / + /// / You should destroy the poll group when you are done using DestroyPollGroup + /// + public static HSteamNetPollGroup CreatePollGroup() { + InteropHelp.TestIfAvailableClient(); + return (HSteamNetPollGroup)NativeMethods.ISteamNetworkingSockets_CreatePollGroup(CSteamAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// / Destroy a poll group created with CreatePollGroup(). + /// / + /// / If there are any connections in the poll group, they are removed from the group, + /// / and left in a state where they are not part of any poll group. + /// / Returns false if passed an invalid poll group handle. + /// + public static bool DestroyPollGroup(HSteamNetPollGroup hPollGroup) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_DestroyPollGroup(CSteamAPIContext.GetSteamNetworkingSockets(), hPollGroup); + } + + /// + /// / Assign a connection to a poll group. Note that a connection may only belong to a + /// / single poll group. Adding a connection to a poll group implicitly removes it from + /// / any other poll group it is in. + /// / + /// / You can pass k_HSteamNetPollGroup_Invalid to remove a connection from its current + /// / poll group without adding it to a new poll group. + /// / + /// / If there are received messages currently pending on the connection, an attempt + /// / is made to add them to the queue of messages for the poll group in approximately + /// / the order that would have applied if the connection was already part of the poll + /// / group at the time that the messages were received. + /// / + /// / Returns false if the connection handle is invalid, or if the poll group handle + /// / is invalid (and not k_HSteamNetPollGroup_Invalid). + /// + public static bool SetConnectionPollGroup(HSteamNetConnection hConn, HSteamNetPollGroup hPollGroup) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_SetConnectionPollGroup(CSteamAPIContext.GetSteamNetworkingSockets(), hConn, hPollGroup); + } + + /// + /// / Same as ReceiveMessagesOnConnection, but will return the next messages available + /// / on any connection in the poll group. Examine SteamNetworkingMessage_t::m_conn + /// / to know which connection. (SteamNetworkingMessage_t::m_nConnUserData might also + /// / be useful.) + /// / + /// / Delivery order of messages among different connections will usually match the + /// / order that the last packet was received which completed the message. But this + /// / is not a strong guarantee, especially for packets received right as a connection + /// / is being assigned to poll group. + /// / + /// / Delivery order of messages on the same connection is well defined and the + /// / same guarantees are present as mentioned in ReceiveMessagesOnConnection. + /// / (But the messages are not grouped by connection, so they will not necessarily + /// / appear consecutively in the list; they may be interleaved with messages for + /// / other connections.) + /// + public static int ReceiveMessagesOnPollGroup(HSteamNetPollGroup hPollGroup, IntPtr[] ppOutMessages, int nMaxMessages) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_ReceiveMessagesOnPollGroup(CSteamAPIContext.GetSteamNetworkingSockets(), hPollGroup, ppOutMessages, nMaxMessages); + } + + /// + /// Clients connecting to dedicated servers hosted in a data center, + /// using tickets issued by your game coordinator. If you are not + /// issuing your own tickets to restrict who can attempt to connect + /// to your server, then you won't use these functions. + /// / Call this when you receive a ticket from your backend / matchmaking system. Puts the + /// / ticket into a persistent cache, and optionally returns the parsed ticket. + /// / + /// / See stamdatagram_ticketgen.h for more details. + /// + public static bool ReceivedRelayAuthTicket(IntPtr pvTicket, int cbTicket, out SteamDatagramRelayAuthTicket pOutParsedTicket) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_ReceivedRelayAuthTicket(CSteamAPIContext.GetSteamNetworkingSockets(), pvTicket, cbTicket, out pOutParsedTicket); + } + + /// + /// / Search cache for a ticket to talk to the server on the specified virtual port. + /// / If found, returns the number of seconds until the ticket expires, and optionally + /// / the complete cracked ticket. Returns 0 if we don't have a ticket. + /// / + /// / Typically this is useful just to confirm that you have a ticket, before you + /// / call ConnectToHostedDedicatedServer to connect to the server. + /// + public static int FindRelayAuthTicketForServer(ref SteamNetworkingIdentity identityGameServer, int nRemoteVirtualPort, out SteamDatagramRelayAuthTicket pOutParsedTicket) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_FindRelayAuthTicketForServer(CSteamAPIContext.GetSteamNetworkingSockets(), ref identityGameServer, nRemoteVirtualPort, out pOutParsedTicket); + } + + /// + /// / Client call to connect to a server hosted in a Valve data center, on the specified virtual + /// / port. You must have placed a ticket for this server into the cache, or else this connect + /// / attempt will fail! If you are not issuing your own tickets, then to connect to a dedicated + /// / server via SDR in auto-ticket mode, use ConnectP2P. (The server must be configured to allow + /// / this type of connection by listening using CreateListenSocketP2P.) + /// / + /// / You may wonder why tickets are stored in a cache, instead of simply being passed as an argument + /// / here. The reason is to make reconnection to a gameserver robust, even if the client computer loses + /// / connection to Steam or the central backend, or the app is restarted or crashes, etc. + /// / + /// / If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess() + /// / when your app initializes + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamNetConnection ConnectToHostedDedicatedServer(ref SteamNetworkingIdentity identityTarget, int nRemoteVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableClient(); + return (HSteamNetConnection)NativeMethods.ISteamNetworkingSockets_ConnectToHostedDedicatedServer(CSteamAPIContext.GetSteamNetworkingSockets(), ref identityTarget, nRemoteVirtualPort, nOptions, pOptions); + } + + /// + /// Servers hosted in data centers known to the Valve relay network + /// / Returns the value of the SDR_LISTEN_PORT environment variable. This + /// / is the UDP server your server will be listening on. This will + /// / configured automatically for you in production environments. + /// / + /// / In development, you'll need to set it yourself. See + /// / https://partner.steamgames.com/doc/api/ISteamNetworkingSockets + /// / for more information on how to configure dev environments. + /// + public static ushort GetHostedDedicatedServerPort() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetHostedDedicatedServerPort(CSteamAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// / Returns 0 if SDR_LISTEN_PORT is not set. Otherwise, returns the data center the server + /// / is running in. This will be k_SteamDatagramPOPID_dev in non-production environment. + /// + public static SteamNetworkingPOPID GetHostedDedicatedServerPOPID() { + InteropHelp.TestIfAvailableClient(); + return (SteamNetworkingPOPID)NativeMethods.ISteamNetworkingSockets_GetHostedDedicatedServerPOPID(CSteamAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// / Return info about the hosted server. This contains the PoPID of the server, + /// / and opaque routing information that can be used by the relays to send traffic + /// / to your server. + /// / + /// / You will need to send this information to your backend, and put it in tickets, + /// / so that the relays will know how to forward traffic from + /// / clients to your server. See SteamDatagramRelayAuthTicket for more info. + /// / + /// / Also, note that the routing information is contained in SteamDatagramGameCoordinatorServerLogin, + /// / so if possible, it's preferred to use GetGameCoordinatorServerLogin to send this info + /// / to your game coordinator service, and also login securely at the same time. + /// / + /// / On a successful exit, k_EResultOK is returned + /// / + /// / Unsuccessful exit: + /// / - Something other than k_EResultOK is returned. + /// / - k_EResultInvalidState: We are not configured to listen for SDR (SDR_LISTEN_SOCKET + /// / is not set.) + /// / - k_EResultPending: we do not (yet) have the authentication information needed. + /// / (See GetAuthenticationStatus.) If you use environment variables to pre-fetch + /// / the network config, this data should always be available immediately. + /// / - A non-localized diagnostic debug message will be placed in m_data that describes + /// / the cause of the failure. + /// / + /// / NOTE: The returned blob is not encrypted. Send it to your backend, but don't + /// / directly share it with clients. + /// + public static EResult GetHostedDedicatedServerAddress(out SteamDatagramHostedAddress pRouting) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetHostedDedicatedServerAddress(CSteamAPIContext.GetSteamNetworkingSockets(), out pRouting); + } + + /// + /// / Create a listen socket on the specified virtual port. The physical UDP port to use + /// / will be determined by the SDR_LISTEN_PORT environment variable. If a UDP port is not + /// / configured, this call will fail. + /// / + /// / This call MUST be made through the SteamGameServerNetworkingSockets() interface. + /// / + /// / This function should be used when you are using the ticket generator library + /// / to issue your own tickets. Clients connecting to the server on this virtual + /// / port will need a ticket, and they must connect using ConnectToHostedDedicatedServer. + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamListenSocket CreateHostedDedicatedServerListenSocket(int nLocalVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableClient(); + return (HSteamListenSocket)NativeMethods.ISteamNetworkingSockets_CreateHostedDedicatedServerListenSocket(CSteamAPIContext.GetSteamNetworkingSockets(), nLocalVirtualPort, nOptions, pOptions); + } + + /// + /// / Generate an authentication blob that can be used to securely login with + /// / your backend, using SteamDatagram_ParseHostedServerLogin. (See + /// / steamdatagram_gamecoordinator.h) + /// / + /// / Before calling the function: + /// / - Populate the app data in pLoginInfo (m_cbAppData and m_appData). You can leave + /// / all other fields uninitialized. + /// / - *pcbSignedBlob contains the size of the buffer at pBlob. (It should be + /// / at least k_cbMaxSteamDatagramGameCoordinatorServerLoginSerialized.) + /// / + /// / On a successful exit: + /// / - k_EResultOK is returned + /// / - All of the remaining fields of pLoginInfo will be filled out. + /// / - *pcbSignedBlob contains the size of the serialized blob that has been + /// / placed into pBlob. + /// / + /// / Unsuccessful exit: + /// / - Something other than k_EResultOK is returned. + /// / - k_EResultNotLoggedOn: you are not logged in (yet) + /// / - See GetHostedDedicatedServerAddress for more potential failure return values. + /// / - A non-localized diagnostic debug message will be placed in pBlob that describes + /// / the cause of the failure. + /// / + /// / This works by signing the contents of the SteamDatagramGameCoordinatorServerLogin + /// / with the cert that is issued to this server. In dev environments, it's OK if you do + /// / not have a cert. (You will need to enable insecure dev login in SteamDatagram_ParseHostedServerLogin.) + /// / Otherwise, you will need a signed cert. + /// / + /// / NOTE: The routing blob returned here is not encrypted. Send it to your backend + /// / and don't share it directly with clients. + /// + public static EResult GetGameCoordinatorServerLogin(IntPtr pLoginInfo, out int pcbSignedBlob, IntPtr pBlob) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetGameCoordinatorServerLogin(CSteamAPIContext.GetSteamNetworkingSockets(), pLoginInfo, out pcbSignedBlob, pBlob); + } + + /// + /// Relayed connections using custom signaling protocol + /// This is used if you have your own method of sending out-of-band + /// signaling / rendezvous messages through a mutually trusted channel. + /// / Create a P2P "client" connection that does signaling over a custom + /// / rendezvous/signaling channel. + /// / + /// / pSignaling points to a new object that you create just for this connection. + /// / It must stay valid until Release() is called. Once you pass the + /// / object to this function, it assumes ownership. Release() will be called + /// / from within the function call if the call fails. Furthermore, until Release() + /// / is called, you should be prepared for methods to be invoked on your + /// / object from any thread! You need to make sure your object is threadsafe! + /// / Furthermore, you should make sure that dispatching the methods is done + /// / as quickly as possible. + /// / + /// / This function will immediately construct a connection in the "connecting" + /// / state. Soon after (perhaps before this function returns, perhaps in another thread), + /// / the connection will begin sending signaling messages by calling + /// / ISteamNetworkingConnectionSignaling::SendSignal. + /// / + /// / When the remote peer accepts the connection (See + /// / ISteamNetworkingSignalingRecvContext::OnConnectRequest), + /// / it will begin sending signaling messages. When these messages are received, + /// / you can pass them to the connection using ReceivedP2PCustomSignal. + /// / + /// / If you know the identity of the peer that you expect to be on the other end, + /// / you can pass their identity to improve debug output or just detect bugs. + /// / If you don't know their identity yet, you can pass NULL, and their + /// / identity will be established in the connection handshake. + /// / + /// / If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess() + /// / when your app initializes + /// / + /// / If you need to set any initial config options, pass them here. See + /// / SteamNetworkingConfigValue_t for more about why this is preferable to + /// / setting the options "immediately" after creation. + /// + public static HSteamNetConnection ConnectP2PCustomSignaling(out ISteamNetworkingConnectionSignaling pSignaling, ref SteamNetworkingIdentity pPeerIdentity, int nRemoteVirtualPort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableClient(); + return (HSteamNetConnection)NativeMethods.ISteamNetworkingSockets_ConnectP2PCustomSignaling(CSteamAPIContext.GetSteamNetworkingSockets(), out pSignaling, ref pPeerIdentity, nRemoteVirtualPort, nOptions, pOptions); + } + + /// + /// / Called when custom signaling has received a message. When your + /// / signaling channel receives a message, it should save off whatever + /// / routing information was in the envelope into the context object, + /// / and then pass the payload to this function. + /// / + /// / A few different things can happen next, depending on the message: + /// / + /// / - If the signal is associated with existing connection, it is dealt + /// / with immediately. If any replies need to be sent, they will be + /// / dispatched using the ISteamNetworkingConnectionSignaling + /// / associated with the connection. + /// / - If the message represents a connection request (and the request + /// / is not redundant for an existing connection), a new connection + /// / will be created, and ReceivedConnectRequest will be called on your + /// / context object to determine how to proceed. + /// / - Otherwise, the message is for a connection that does not + /// / exist (anymore). In this case, we *may* call SendRejectionReply + /// / on your context object. + /// / + /// / In any case, we will not save off pContext or access it after this + /// / function returns. + /// / + /// / Returns true if the message was parsed and dispatched without anything + /// / unusual or suspicious happening. Returns false if there was some problem + /// / with the message that prevented ordinary handling. (Debug output will + /// / usually have more information.) + /// / + /// / If you expect to be using relayed connections, then you probably want + /// / to call ISteamNetworkingUtils::InitRelayNetworkAccess() when your app initializes + /// + public static bool ReceivedP2PCustomSignal(IntPtr pMsg, int cbMsg, out ISteamNetworkingSignalingRecvContext pContext) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_ReceivedP2PCustomSignal(CSteamAPIContext.GetSteamNetworkingSockets(), pMsg, cbMsg, out pContext); + } + + /// + /// Certificate provision by the application. On Steam, we normally handle all this automatically + /// and you will not need to use these advanced functions. + /// / Get blob that describes a certificate request. You can send this to your game coordinator. + /// / Upon entry, *pcbBlob should contain the size of the buffer. On successful exit, it will + /// / return the number of bytes that were populated. You can pass pBlob=NULL to query for the required + /// / size. (512 bytes is a conservative estimate.) + /// / + /// / Pass this blob to your game coordinator and call SteamDatagram_CreateCert. + /// + public static bool GetCertificateRequest(out int pcbBlob, IntPtr pBlob, out SteamNetworkingErrMsg errMsg) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetCertificateRequest(CSteamAPIContext.GetSteamNetworkingSockets(), out pcbBlob, pBlob, out errMsg); + } + + /// + /// / Set the certificate. The certificate blob should be the output of + /// / SteamDatagram_CreateCert. + /// + public static bool SetCertificate(IntPtr pCertificate, int cbCertificate, out SteamNetworkingErrMsg errMsg) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_SetCertificate(CSteamAPIContext.GetSteamNetworkingSockets(), pCertificate, cbCertificate, out errMsg); + } + + /// + /// / Reset the identity associated with this instance. + /// / Any open connections are closed. Any previous certificates, etc are discarded. + /// / You can pass a specific identity that you want to use, or you can pass NULL, + /// / in which case the identity will be invalid until you set it using SetCertificate + /// / + /// / NOTE: This function is not actually supported on Steam! It is included + /// / for use on other platforms where the active user can sign out and + /// / a new user can sign in. + /// + public static void ResetIdentity(ref SteamNetworkingIdentity pIdentity) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamNetworkingSockets_ResetIdentity(CSteamAPIContext.GetSteamNetworkingSockets(), ref pIdentity); + } + + /// + /// Misc + /// / Invoke all callback functions queued for this interface. + /// / See k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, etc + /// / + /// / You don't need to call this if you are using Steam's callback dispatch + /// / mechanism (SteamAPI_RunCallbacks and SteamGameserver_RunCallbacks). + /// + public static void RunCallbacks() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamNetworkingSockets_RunCallbacks(CSteamAPIContext.GetSteamNetworkingSockets()); + } + + /// + /// "FakeIP" system. + /// A FakeIP is essentially a temporary, arbitrary identifier that + /// happens to be a valid IPv4 address. The purpose of this system is to make it + /// easy to integrate with existing code that identifies hosts using IPv4 addresses. + /// The FakeIP address will never actually be used to send or receive any packets + /// on the Internet, it is strictly an identifier. + /// FakeIP addresses are designed to (hopefully) pass through existing code as + /// transparently as possible, while conflicting with "real" addresses that might + /// be in use on networks (both the Internet and LANs) in the same code as little + /// as possible. At the time this comment is being written, they come from the + /// 169.254.0.0/16 range, and the port number will always be >1024. HOWEVER, + /// this is subject to change! Do not make assumptions about these addresses, + /// or your code might break in the future. In particular, you should use + /// functions such as ISteamNetworkingUtils::IsFakeIP to determine if an IP + /// address is a "fake" one used by this system. + /// / Begin asynchronous process of allocating a fake IPv4 address that other + /// / peers can use to contact us via P2P. IP addresses returned by this + /// / function are globally unique for a given appid. + /// / + /// / nNumPorts is the numbers of ports you wish to reserve. This is useful + /// / for the same reason that listening on multiple UDP ports is useful for + /// / different types of traffic. Because these allocations come from a global + /// / namespace, there is a relatively strict limit on the maximum number of + /// / ports you may request. (At the time of this writing, the limit is 4.) + /// / The Port assignments are *not* guaranteed to have any particular order + /// / or relationship! Do *not* assume they are contiguous, even though that + /// / may often occur in practice. + /// / + /// / Returns false if a request was already in progress, true if a new request + /// / was started. A SteamNetworkingFakeIPResult_t will be posted when the request + /// / completes. + /// / + /// / For gameservers, you *must* call this after initializing the SDK but before + /// / beginning login. Steam needs to know in advance that FakeIP will be used. + /// / Everywhere your public IP would normally appear (such as the server browser) will be + /// / replaced by the FakeIP, and the fake port at index 0. The request is actually queued + /// / until the logon completes, so you must not wait until the allocation completes + /// / before logging in. Except for trivial failures that can be detected locally + /// / (e.g. invalid parameter), a SteamNetworkingFakeIPResult_t callback (whether success or + /// / failure) will not be posted until after we have logged in. Furthermore, it is assumed + /// / that FakeIP allocation is essential for your application to function, and so failure + /// / will not be reported until *several* retries have been attempted. This process may + /// / last several minutes. It is *highly* recommended to treat failure as fatal. + /// / + /// / To communicate using a connection-oriented (TCP-style) API: + /// / - Server creates a listen socket using CreateListenSocketP2PFakeIP + /// / - Client connects using ConnectByIPAddress, passing in the FakeIP address. + /// / - The connection will behave mostly like a P2P connection. The identities + /// / that appear in SteamNetConnectionInfo_t will be the FakeIP identity until + /// / we know the real identity. Then it will be the real identity. If the + /// / SteamNetConnectionInfo_t::m_addrRemote is valid, it will be a real IPv4 + /// / address of a NAT-punched connection. Otherwise, it will not be valid. + /// / + /// / To communicate using an ad-hoc sendto/recv from (UDP-style) API, + /// / use CreateFakeUDPPort. + /// + public static bool BeginAsyncRequestFakeIP(int nNumPorts) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_BeginAsyncRequestFakeIP(CSteamAPIContext.GetSteamNetworkingSockets(), nNumPorts); + } + + /// + /// / Return info about the FakeIP and port(s) that we have been assigned, + /// / if any. idxFirstPort is currently reserved and must be zero. + /// / Make sure and check SteamNetworkingFakeIPResult_t::m_eResult + /// + public static void GetFakeIP(int idxFirstPort, out SteamNetworkingFakeIPResult_t pInfo) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamNetworkingSockets_GetFakeIP(CSteamAPIContext.GetSteamNetworkingSockets(), idxFirstPort, out pInfo); + } + + /// + /// / Create a listen socket that will listen for P2P connections sent + /// / to our FakeIP. A peer can initiate connections to this listen + /// / socket by calling ConnectByIPAddress. + /// / + /// / idxFakePort refers to the *index* of the fake port requested, + /// / not the actual port number. For example, pass 0 to refer to the + /// / first port in the reservation. You must call this only after calling + /// / BeginAsyncRequestFakeIP. However, you do not need to wait for the + /// / request to complete before creating the listen socket. + /// + public static HSteamListenSocket CreateListenSocketP2PFakeIP(int idxFakePort, int nOptions, SteamNetworkingConfigValue_t[] pOptions) { + InteropHelp.TestIfAvailableClient(); + return (HSteamListenSocket)NativeMethods.ISteamNetworkingSockets_CreateListenSocketP2PFakeIP(CSteamAPIContext.GetSteamNetworkingSockets(), idxFakePort, nOptions, pOptions); + } + + /// + /// / If the connection was initiated using the "FakeIP" system, then we + /// / we can get an IP address for the remote host. If the remote host had + /// / a global FakeIP at the time the connection was established, this + /// / function will return that global IP. Otherwise, a FakeIP that is + /// / unique locally will be allocated from the local FakeIP address space, + /// / and that will be returned. + /// / + /// / The allocation of local FakeIPs attempts to assign addresses in + /// / a consistent manner. If multiple connections are made to the + /// / same remote host, they *probably* will return the same FakeIP. + /// / However, since the namespace is limited, this cannot be guaranteed. + /// / + /// / On failure, returns: + /// / - k_EResultInvalidParam: invalid connection handle + /// / - k_EResultIPNotFound: This connection wasn't made using FakeIP system + /// + public static EResult GetRemoteFakeIPForConnection(HSteamNetConnection hConn, out SteamNetworkingIPAddr pOutAddr) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_GetRemoteFakeIPForConnection(CSteamAPIContext.GetSteamNetworkingSockets(), hConn, out pOutAddr); + } + + /// + /// / Get an interface that can be used like a UDP port to send/receive + /// / datagrams to a FakeIP address. This is intended to make it easy + /// / to port existing UDP-based code to take advantage of SDR. + /// / + /// / idxFakeServerPort refers to the *index* of the port allocated using + /// / BeginAsyncRequestFakeIP and is used to create "server" ports. You may + /// / call this before the allocation has completed. However, any attempts + /// / to send packets will fail until the allocation has succeeded. When + /// / the peer receives packets sent from this interface, the from address + /// / of the packet will be the globally-unique FakeIP. If you call this + /// / function multiple times and pass the same (nonnegative) fake port index, + /// / the same object will be returned, and this object is not reference counted. + /// / + /// / To create a "client" port (e.g. the equivalent of an ephemeral UDP port) + /// / pass -1. In this case, a distinct object will be returned for each call. + /// / When the peer receives packets sent from this interface, the peer will + /// / assign a FakeIP from its own locally-controlled namespace. + /// + public static IntPtr CreateFakeUDPPort(int idxFakeServerPort) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingSockets_CreateFakeUDPPort(CSteamAPIContext.GetSteamNetworkingSockets(), idxFakeServerPort); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingsockets.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingsockets.cs.meta new file mode 100644 index 0000000..801b89a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingsockets.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b14ddce873fdbfc4aab2f5e4dafc27aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingutils.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingutils.cs new file mode 100644 index 0000000..cb069d7 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingutils.cs @@ -0,0 +1,444 @@ +#define STEAMNETWORKINGSOCKETS_ENABLE_SDR +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamNetworkingUtils { + /// + /// Efficient message sending + /// / Allocate and initialize a message object. Usually the reason + /// / you call this is to pass it to ISteamNetworkingSockets::SendMessages. + /// / The returned object will have all of the relevant fields cleared to zero. + /// / + /// / Optionally you can also request that this system allocate space to + /// / hold the payload itself. If cbAllocateBuffer is nonzero, the system + /// / will allocate memory to hold a payload of at least cbAllocateBuffer bytes. + /// / m_pData will point to the allocated buffer, m_cbSize will be set to the + /// / size, and m_pfnFreeData will be set to the proper function to free up + /// / the buffer. + /// / + /// / If cbAllocateBuffer=0, then no buffer is allocated. m_pData will be NULL, + /// / m_cbSize will be zero, and m_pfnFreeData will be NULL. You will need to + /// / set each of these. + /// + public static IntPtr AllocateMessage(int cbAllocateBuffer) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_AllocateMessage(CSteamAPIContext.GetSteamNetworkingUtils(), cbAllocateBuffer); + } + + /// + /// Access to Steam Datagram Relay (SDR) network + /// Initialization and status check + /// / If you know that you are going to be using the relay network (for example, + /// / because you anticipate making P2P connections), call this to initialize the + /// / relay network. If you do not call this, the initialization will + /// / be delayed until the first time you use a feature that requires access + /// / to the relay network, which will delay that first access. + /// / + /// / You can also call this to force a retry if the previous attempt has failed. + /// / Performing any action that requires access to the relay network will also + /// / trigger a retry, and so calling this function is never strictly necessary, + /// / but it can be useful to call it a program launch time, if access to the + /// / relay network is anticipated. + /// / + /// / Use GetRelayNetworkStatus or listen for SteamRelayNetworkStatus_t + /// / callbacks to know when initialization has completed. + /// / Typically initialization completes in a few seconds. + /// / + /// / Note: dedicated servers hosted in known data centers do *not* need + /// / to call this, since they do not make routing decisions. However, if + /// / the dedicated server will be using P2P functionality, it will act as + /// / a "client" and this should be called. + /// + public static void InitRelayNetworkAccess() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamNetworkingUtils_InitRelayNetworkAccess(CSteamAPIContext.GetSteamNetworkingUtils()); + } + + /// + /// / Fetch current status of the relay network. + /// / + /// / SteamRelayNetworkStatus_t is also a callback. It will be triggered on + /// / both the user and gameserver interfaces any time the status changes, or + /// / ping measurement starts or stops. + /// / + /// / SteamRelayNetworkStatus_t::m_eAvail is returned. If you want + /// / more details, you can pass a non-NULL value. + /// + public static ESteamNetworkingAvailability GetRelayNetworkStatus(out SteamRelayNetworkStatus_t pDetails) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetRelayNetworkStatus(CSteamAPIContext.GetSteamNetworkingUtils(), out pDetails); + } + + /// + /// "Ping location" functions + /// We use the ping times to the valve relays deployed worldwide to + /// generate a "marker" that describes the location of an Internet host. + /// Given two such markers, we can estimate the network latency between + /// two hosts, without sending any packets. The estimate is based on the + /// optimal route that is found through the Valve network. If you are + /// using the Valve network to carry the traffic, then this is precisely + /// the ping you want. If you are not, then the ping time will probably + /// still be a reasonable estimate. + /// This is extremely useful to select peers for matchmaking! + /// The markers can also be converted to a string, so they can be transmitted. + /// We have a separate library you can use on your app's matchmaking/coordinating + /// server to manipulate these objects. (See steamdatagram_gamecoordinator.h) + /// / Return location info for the current host. Returns the approximate + /// / age of the data, in seconds, or -1 if no data is available. + /// / + /// / It takes a few seconds to initialize access to the relay network. If + /// / you call this very soon after calling InitRelayNetworkAccess, + /// / the data may not be available yet. + /// / + /// / This always return the most up-to-date information we have available + /// / right now, even if we are in the middle of re-calculating ping times. + /// + public static float GetLocalPingLocation(out SteamNetworkPingLocation_t result) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetLocalPingLocation(CSteamAPIContext.GetSteamNetworkingUtils(), out result); + } + + /// + /// / Estimate the round-trip latency between two arbitrary locations, in + /// / milliseconds. This is a conservative estimate, based on routing through + /// / the relay network. For most basic relayed connections, this ping time + /// / will be pretty accurate, since it will be based on the route likely to + /// / be actually used. + /// / + /// / If a direct IP route is used (perhaps via NAT traversal), then the route + /// / will be different, and the ping time might be better. Or it might actually + /// / be a bit worse! Standard IP routing is frequently suboptimal! + /// / + /// / But even in this case, the estimate obtained using this method is a + /// / reasonable upper bound on the ping time. (Also it has the advantage + /// / of returning immediately and not sending any packets.) + /// / + /// / In a few cases we might not able to estimate the route. In this case + /// / a negative value is returned. k_nSteamNetworkingPing_Failed means + /// / the reason was because of some networking difficulty. (Failure to + /// / ping, etc) k_nSteamNetworkingPing_Unknown is returned if we cannot + /// / currently answer the question for some other reason. + /// / + /// / Do you need to be able to do this from a backend/matchmaking server? + /// / You are looking for the "game coordinator" library. + /// + public static int EstimatePingTimeBetweenTwoLocations(ref SteamNetworkPingLocation_t location1, ref SteamNetworkPingLocation_t location2) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_EstimatePingTimeBetweenTwoLocations(CSteamAPIContext.GetSteamNetworkingUtils(), ref location1, ref location2); + } + + /// + /// / Same as EstimatePingTime, but assumes that one location is the local host. + /// / This is a bit faster, especially if you need to calculate a bunch of + /// / these in a loop to find the fastest one. + /// / + /// / In rare cases this might return a slightly different estimate than combining + /// / GetLocalPingLocation with EstimatePingTimeBetweenTwoLocations. That's because + /// / this function uses a slightly more complete set of information about what + /// / route would be taken. + /// + public static int EstimatePingTimeFromLocalHost(ref SteamNetworkPingLocation_t remoteLocation) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_EstimatePingTimeFromLocalHost(CSteamAPIContext.GetSteamNetworkingUtils(), ref remoteLocation); + } + + /// + /// / Convert a ping location into a text format suitable for sending over the wire. + /// / The format is a compact and human readable. However, it is subject to change + /// / so please do not parse it yourself. Your buffer must be at least + /// / k_cchMaxSteamNetworkingPingLocationString bytes. + /// + public static void ConvertPingLocationToString(ref SteamNetworkPingLocation_t location, out string pszBuf, int cchBufSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pszBuf2 = Marshal.AllocHGlobal(cchBufSize); + NativeMethods.ISteamNetworkingUtils_ConvertPingLocationToString(CSteamAPIContext.GetSteamNetworkingUtils(), ref location, pszBuf2, cchBufSize); + pszBuf = InteropHelp.PtrToStringUTF8(pszBuf2); + Marshal.FreeHGlobal(pszBuf2); + } + + /// + /// / Parse back SteamNetworkPingLocation_t string. Returns false if we couldn't understand + /// / the string. + /// + public static bool ParsePingLocationString(string pszString, out SteamNetworkPingLocation_t result) { + InteropHelp.TestIfAvailableClient(); + using (var pszString2 = new InteropHelp.UTF8StringHandle(pszString)) { + return NativeMethods.ISteamNetworkingUtils_ParsePingLocationString(CSteamAPIContext.GetSteamNetworkingUtils(), pszString2, out result); + } + } + + /// + /// / Check if the ping data of sufficient recency is available, and if + /// / it's too old, start refreshing it. + /// / + /// / Please only call this function when you *really* do need to force an + /// / immediate refresh of the data. (For example, in response to a specific + /// / user input to refresh this information.) Don't call it "just in case", + /// / before every connection, etc. That will cause extra traffic to be sent + /// / for no benefit. The library will automatically refresh the information + /// / as needed. + /// / + /// / Returns true if sufficiently recent data is already available. + /// / + /// / Returns false if sufficiently recent data is not available. In this + /// / case, ping measurement is initiated, if it is not already active. + /// / (You cannot restart a measurement already in progress.) + /// / + /// / You can use GetRelayNetworkStatus or listen for SteamRelayNetworkStatus_t + /// / to know when ping measurement completes. + /// + public static bool CheckPingDataUpToDate(float flMaxAgeSeconds) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_CheckPingDataUpToDate(CSteamAPIContext.GetSteamNetworkingUtils(), flMaxAgeSeconds); + } + + /// + /// List of Valve data centers, and ping times to them. This might + /// be useful to you if you are use our hosting, or just need to measure + /// latency to a cloud data center where we are running relays. + /// / Fetch ping time of best available relayed route from this host to + /// / the specified data center. + /// + public static int GetPingToDataCenter(SteamNetworkingPOPID popID, out SteamNetworkingPOPID pViaRelayPoP) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetPingToDataCenter(CSteamAPIContext.GetSteamNetworkingUtils(), popID, out pViaRelayPoP); + } + + /// + /// / Get *direct* ping time to the relays at the data center. + /// + public static int GetDirectPingToPOP(SteamNetworkingPOPID popID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetDirectPingToPOP(CSteamAPIContext.GetSteamNetworkingUtils(), popID); + } + + /// + /// / Get number of network points of presence in the config + /// + public static int GetPOPCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetPOPCount(CSteamAPIContext.GetSteamNetworkingUtils()); + } + + /// + /// / Get list of all POP IDs. Returns the number of entries that were filled into + /// / your list. + /// + public static int GetPOPList(out SteamNetworkingPOPID list, int nListSz) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetPOPList(CSteamAPIContext.GetSteamNetworkingUtils(), out list, nListSz); + } + + /// + /// Misc + /// / Fetch current timestamp. This timer has the following properties: + /// / + /// / - Monotonicity is guaranteed. + /// / - The initial value will be at least 24*3600*30*1e6, i.e. about + /// / 30 days worth of microseconds. In this way, the timestamp value of + /// / 0 will always be at least "30 days ago". Also, negative numbers + /// / will never be returned. + /// / - Wraparound / overflow is not a practical concern. + /// / + /// / If you are running under the debugger and stop the process, the clock + /// / might not advance the full wall clock time that has elapsed between + /// / calls. If the process is not blocked from normal operation, the + /// / timestamp values will track wall clock time, even if you don't call + /// / the function frequently. + /// / + /// / The value is only meaningful for this run of the process. Don't compare + /// / it to values obtained on another computer, or other runs of the same process. + /// + public static SteamNetworkingMicroseconds GetLocalTimestamp() { + InteropHelp.TestIfAvailableClient(); + return (SteamNetworkingMicroseconds)NativeMethods.ISteamNetworkingUtils_GetLocalTimestamp(CSteamAPIContext.GetSteamNetworkingUtils()); + } + + /// + /// / Set a function to receive network-related information that is useful for debugging. + /// / This can be very useful during development, but it can also be useful for troubleshooting + /// / problems with tech savvy end users. If you have a console or other log that customers + /// / can examine, these log messages can often be helpful to troubleshoot network issues. + /// / (Especially any warning/error messages.) + /// / + /// / The detail level indicates what message to invoke your callback on. Lower numeric + /// / value means more important, and the value you pass is the lowest priority (highest + /// / numeric value) you wish to receive callbacks for. + /// / + /// / The value here controls the detail level for most messages. You can control the + /// / detail level for various subsystems (perhaps only for certain connections) by + /// / adjusting the configuration values k_ESteamNetworkingConfig_LogLevel_Xxxxx. + /// / + /// / Except when debugging, you should only use k_ESteamNetworkingSocketsDebugOutputType_Msg + /// / or k_ESteamNetworkingSocketsDebugOutputType_Warning. For best performance, do NOT + /// / request a high detail level and then filter out messages in your callback. This incurs + /// / all of the expense of formatting the messages, which are then discarded. Setting a high + /// / priority value (low numeric value) here allows the library to avoid doing this work. + /// / + /// / IMPORTANT: This may be called from a service thread, while we own a mutex, etc. + /// / Your output function must be threadsafe and fast! Do not make any other + /// / Steamworks calls from within the handler. + /// + public static void SetDebugOutputFunction(ESteamNetworkingSocketsDebugOutputType eDetailLevel, FSteamNetworkingSocketsDebugOutput pfnFunc) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamNetworkingUtils_SetDebugOutputFunction(CSteamAPIContext.GetSteamNetworkingUtils(), eDetailLevel, pfnFunc); + } + + /// + /// Fake IP + /// Useful for interfacing with code that assumes peers are identified using an IPv4 address + /// / Return true if an IPv4 address is one that might be used as a "fake" one. + /// / This function is fast; it just does some logical tests on the IP and does + /// / not need to do any lookup operations. + /// + public static bool IsFakeIPv4(uint nIPv4) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_IsFakeIPv4(CSteamAPIContext.GetSteamNetworkingUtils(), nIPv4); + } + + public static ESteamNetworkingFakeIPType GetIPv4FakeIPType(uint nIPv4) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetIPv4FakeIPType(CSteamAPIContext.GetSteamNetworkingUtils(), nIPv4); + } + + /// + /// / Get the real identity associated with a given FakeIP. + /// / + /// / On failure, returns: + /// / - k_EResultInvalidParam: the IP is not a FakeIP. + /// / - k_EResultNoMatch: we don't recognize that FakeIP and don't know the corresponding identity. + /// / + /// / FakeIP's used by active connections, or the FakeIPs assigned to local identities, + /// / will always work. FakeIPs for recently destroyed connections will continue to + /// / return results for a little while, but not forever. At some point, we will forget + /// / FakeIPs to save space. It's reasonably safe to assume that you can read back the + /// / real identity of a connection very soon after it is destroyed. But do not wait + /// / indefinitely. + /// + public static EResult GetRealIdentityForFakeIP(ref SteamNetworkingIPAddr fakeIP, out SteamNetworkingIdentity pOutRealIdentity) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetRealIdentityForFakeIP(CSteamAPIContext.GetSteamNetworkingUtils(), ref fakeIP, out pOutRealIdentity); + } + + /// + /// Set and get configuration values, see ESteamNetworkingConfigValue for individual descriptions. + /// Shortcuts for common cases. (Implemented as inline functions below) + /// Set global callbacks. If you do not want to use Steam's callback dispatch mechanism and you + /// want to use the same callback on all (or most) listen sockets and connections, then + /// simply install these callbacks first thing, and you are good to go. + /// See ISteamNetworkingSockets::RunCallbacks + /// / Set a configuration value. + /// / - eValue: which value is being set + /// / - eScope: Onto what type of object are you applying the setting? + /// / - scopeArg: Which object you want to change? (Ignored for global scope). E.g. connection handle, listen socket handle, interface pointer, etc. + /// / - eDataType: What type of data is in the buffer at pValue? This must match the type of the variable exactly! + /// / - pArg: Value to set it to. You can pass NULL to remove a non-global setting at this scope, + /// / causing the value for that object to use global defaults. Or at global scope, passing NULL + /// / will reset any custom value and restore it to the system default. + /// / NOTE: When setting pointers (e.g. callback functions), do not pass the function pointer directly. + /// / Your argument should be a pointer to a function pointer. + /// + public static bool SetConfigValue(ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigScope eScopeType, IntPtr scopeObj, ESteamNetworkingConfigDataType eDataType, IntPtr pArg) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_SetConfigValue(CSteamAPIContext.GetSteamNetworkingUtils(), eValue, eScopeType, scopeObj, eDataType, pArg); + } + + /// + /// / Set a configuration value, using a struct to pass the value. + /// / (This is just a convenience shortcut; see below for the implementation and + /// / a little insight into how SteamNetworkingConfigValue_t is used when + /// / setting config options during listen socket and connection creation.) + /// / Get a configuration value. + /// / - eValue: which value to fetch + /// / - eScopeType: query setting on what type of object + /// / - eScopeArg: the object to query the setting for + /// / - pOutDataType: If non-NULL, the data type of the value is returned. + /// / - pResult: Where to put the result. Pass NULL to query the required buffer size. (k_ESteamNetworkingGetConfigValue_BufferTooSmall will be returned.) + /// / - cbResult: IN: the size of your buffer. OUT: the number of bytes filled in or required. + /// + public static ESteamNetworkingGetConfigValueResult GetConfigValue(ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigScope eScopeType, IntPtr scopeObj, out ESteamNetworkingConfigDataType pOutDataType, IntPtr pResult, ref ulong cbResult) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_GetConfigValue(CSteamAPIContext.GetSteamNetworkingUtils(), eValue, eScopeType, scopeObj, out pOutDataType, pResult, ref cbResult); + } + + /// + /// / Get info about a configuration value. Returns the name of the value, + /// / or NULL if the value doesn't exist. Other output parameters can be NULL + /// / if you do not need them. + /// + public static string GetConfigValueInfo(ESteamNetworkingConfigValue eValue, out ESteamNetworkingConfigDataType pOutDataType, out ESteamNetworkingConfigScope pOutScope) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamNetworkingUtils_GetConfigValueInfo(CSteamAPIContext.GetSteamNetworkingUtils(), eValue, out pOutDataType, out pOutScope)); + } + + /// + /// / Iterate the list of all configuration values in the current environment that it might + /// / be possible to display or edit using a generic UI. To get the first iterable value, + /// / pass k_ESteamNetworkingConfig_Invalid. Returns k_ESteamNetworkingConfig_Invalid + /// / to signal end of list. + /// / + /// / The bEnumerateDevVars argument can be used to include "dev" vars. These are vars that + /// / are recommended to only be editable in "debug" or "dev" mode and typically should not be + /// / shown in a retail environment where a malicious local user might use this to cheat. + /// + public static ESteamNetworkingConfigValue IterateGenericEditableConfigValues(ESteamNetworkingConfigValue eCurrent, bool bEnumerateDevVars) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_IterateGenericEditableConfigValues(CSteamAPIContext.GetSteamNetworkingUtils(), eCurrent, bEnumerateDevVars); + } + + /// + /// String conversions. You'll usually access these using the respective + /// inline methods. + /// + public static void SteamNetworkingIPAddr_ToString(ref SteamNetworkingIPAddr addr, out string buf, uint cbBuf, bool bWithPort) { + InteropHelp.TestIfAvailableClient(); + IntPtr buf2 = Marshal.AllocHGlobal((int)cbBuf); + NativeMethods.ISteamNetworkingUtils_SteamNetworkingIPAddr_ToString(CSteamAPIContext.GetSteamNetworkingUtils(), ref addr, buf2, cbBuf, bWithPort); + buf = InteropHelp.PtrToStringUTF8(buf2); + Marshal.FreeHGlobal(buf2); + } + + public static bool SteamNetworkingIPAddr_ParseString(out SteamNetworkingIPAddr pAddr, string pszStr) { + InteropHelp.TestIfAvailableClient(); + using (var pszStr2 = new InteropHelp.UTF8StringHandle(pszStr)) { + return NativeMethods.ISteamNetworkingUtils_SteamNetworkingIPAddr_ParseString(CSteamAPIContext.GetSteamNetworkingUtils(), out pAddr, pszStr2); + } + } + + public static ESteamNetworkingFakeIPType SteamNetworkingIPAddr_GetFakeIPType(ref SteamNetworkingIPAddr addr) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamNetworkingUtils_SteamNetworkingIPAddr_GetFakeIPType(CSteamAPIContext.GetSteamNetworkingUtils(), ref addr); + } + + public static void SteamNetworkingIdentity_ToString(ref SteamNetworkingIdentity identity, out string buf, uint cbBuf) { + InteropHelp.TestIfAvailableClient(); + IntPtr buf2 = Marshal.AllocHGlobal((int)cbBuf); + NativeMethods.ISteamNetworkingUtils_SteamNetworkingIdentity_ToString(CSteamAPIContext.GetSteamNetworkingUtils(), ref identity, buf2, cbBuf); + buf = InteropHelp.PtrToStringUTF8(buf2); + Marshal.FreeHGlobal(buf2); + } + + public static bool SteamNetworkingIdentity_ParseString(out SteamNetworkingIdentity pIdentity, string pszStr) { + InteropHelp.TestIfAvailableClient(); + using (var pszStr2 = new InteropHelp.UTF8StringHandle(pszStr)) { + return NativeMethods.ISteamNetworkingUtils_SteamNetworkingIdentity_ParseString(CSteamAPIContext.GetSteamNetworkingUtils(), out pIdentity, pszStr2); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingutils.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingutils.cs.meta new file mode 100644 index 0000000..5d67557 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingutils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 28bd6c2bd8eef784abca992dc6409c98 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamparentalsettings.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamparentalsettings.cs new file mode 100644 index 0000000..b17ad7e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamparentalsettings.cs @@ -0,0 +1,51 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamParentalSettings { + public static bool BIsParentalLockEnabled() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParentalSettings_BIsParentalLockEnabled(CSteamAPIContext.GetSteamParentalSettings()); + } + + public static bool BIsParentalLockLocked() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParentalSettings_BIsParentalLockLocked(CSteamAPIContext.GetSteamParentalSettings()); + } + + public static bool BIsAppBlocked(AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParentalSettings_BIsAppBlocked(CSteamAPIContext.GetSteamParentalSettings(), nAppID); + } + + public static bool BIsAppInBlockList(AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParentalSettings_BIsAppInBlockList(CSteamAPIContext.GetSteamParentalSettings(), nAppID); + } + + public static bool BIsFeatureBlocked(EParentalFeature eFeature) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParentalSettings_BIsFeatureBlocked(CSteamAPIContext.GetSteamParentalSettings(), eFeature); + } + + public static bool BIsFeatureInBlockList(EParentalFeature eFeature) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamParentalSettings_BIsFeatureInBlockList(CSteamAPIContext.GetSteamParentalSettings(), eFeature); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamparentalsettings.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamparentalsettings.cs.meta new file mode 100644 index 0000000..e6b4250 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamparentalsettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6c5b074bfb8a404ab69b08240c3453d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremoteplay.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremoteplay.cs new file mode 100644 index 0000000..0cc08d8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremoteplay.cs @@ -0,0 +1,80 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamRemotePlay { + /// + /// Get the number of currently connected Steam Remote Play sessions + /// + public static uint GetSessionCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemotePlay_GetSessionCount(CSteamAPIContext.GetSteamRemotePlay()); + } + + /// + /// Get the currently connected Steam Remote Play session ID at the specified index. Returns zero if index is out of bounds. + /// + public static RemotePlaySessionID_t GetSessionID(int iSessionIndex) { + InteropHelp.TestIfAvailableClient(); + return (RemotePlaySessionID_t)NativeMethods.ISteamRemotePlay_GetSessionID(CSteamAPIContext.GetSteamRemotePlay(), iSessionIndex); + } + + /// + /// Get the SteamID of the connected user + /// + public static CSteamID GetSessionSteamID(RemotePlaySessionID_t unSessionID) { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamRemotePlay_GetSessionSteamID(CSteamAPIContext.GetSteamRemotePlay(), unSessionID); + } + + /// + /// Get the name of the session client device + /// This returns NULL if the sessionID is not valid + /// + public static string GetSessionClientName(RemotePlaySessionID_t unSessionID) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamRemotePlay_GetSessionClientName(CSteamAPIContext.GetSteamRemotePlay(), unSessionID)); + } + + /// + /// Get the form factor of the session client device + /// + public static ESteamDeviceFormFactor GetSessionClientFormFactor(RemotePlaySessionID_t unSessionID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemotePlay_GetSessionClientFormFactor(CSteamAPIContext.GetSteamRemotePlay(), unSessionID); + } + + /// + /// Get the resolution, in pixels, of the session client device + /// This is set to 0x0 if the resolution is not available + /// + public static bool BGetSessionClientResolution(RemotePlaySessionID_t unSessionID, out int pnResolutionX, out int pnResolutionY) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemotePlay_BGetSessionClientResolution(CSteamAPIContext.GetSteamRemotePlay(), unSessionID, out pnResolutionX, out pnResolutionY); + } + + /// + /// Invite a friend to Remote Play Together, or create a guest invite if steamIDFriend is empty + /// This returns false if the invite can't be sent + /// + public static bool BSendRemotePlayTogetherInvite(CSteamID steamIDFriend) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemotePlay_BSendRemotePlayTogetherInvite(CSteamAPIContext.GetSteamRemotePlay(), steamIDFriend); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremoteplay.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremoteplay.cs.meta new file mode 100644 index 0000000..c0f00c5 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremoteplay.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ce69a1658f2fa246a98b5124418b01c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremotestorage.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremotestorage.cs new file mode 100644 index 0000000..7bc699b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremotestorage.cs @@ -0,0 +1,434 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamRemoteStorage { + /// + /// NOTE + /// Filenames are case-insensitive, and will be converted to lowercase automatically. + /// So "foo.bar" and "Foo.bar" are the same file, and if you write "Foo.bar" then + /// iterate the files, the filename returned will be "foo.bar". + /// file operations + /// + public static bool FileWrite(string pchFile, byte[] pvData, int cubData) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_FileWrite(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, pvData, cubData); + } + } + + public static int FileRead(string pchFile, byte[] pvData, int cubDataToRead) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_FileRead(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, pvData, cubDataToRead); + } + } + + public static SteamAPICall_t FileWriteAsync(string pchFile, byte[] pvData, uint cubData) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_FileWriteAsync(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, pvData, cubData); + } + } + + public static SteamAPICall_t FileReadAsync(string pchFile, uint nOffset, uint cubToRead) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_FileReadAsync(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, nOffset, cubToRead); + } + } + + public static bool FileReadAsyncComplete(SteamAPICall_t hReadCall, byte[] pvBuffer, uint cubToRead) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_FileReadAsyncComplete(CSteamAPIContext.GetSteamRemoteStorage(), hReadCall, pvBuffer, cubToRead); + } + + public static bool FileForget(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_FileForget(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + public static bool FileDelete(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_FileDelete(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + public static SteamAPICall_t FileShare(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_FileShare(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + public static bool SetSyncPlatforms(string pchFile, ERemoteStoragePlatform eRemoteStoragePlatform) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_SetSyncPlatforms(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, eRemoteStoragePlatform); + } + } + + /// + /// file operations that cause network IO + /// + public static UGCFileWriteStreamHandle_t FileWriteStreamOpen(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return (UGCFileWriteStreamHandle_t)NativeMethods.ISteamRemoteStorage_FileWriteStreamOpen(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + public static bool FileWriteStreamWriteChunk(UGCFileWriteStreamHandle_t writeHandle, byte[] pvData, int cubData) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_FileWriteStreamWriteChunk(CSteamAPIContext.GetSteamRemoteStorage(), writeHandle, pvData, cubData); + } + + public static bool FileWriteStreamClose(UGCFileWriteStreamHandle_t writeHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_FileWriteStreamClose(CSteamAPIContext.GetSteamRemoteStorage(), writeHandle); + } + + public static bool FileWriteStreamCancel(UGCFileWriteStreamHandle_t writeHandle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_FileWriteStreamCancel(CSteamAPIContext.GetSteamRemoteStorage(), writeHandle); + } + + /// + /// file information + /// + public static bool FileExists(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_FileExists(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + public static bool FilePersisted(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_FilePersisted(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + public static int GetFileSize(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_GetFileSize(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + public static long GetFileTimestamp(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_GetFileTimestamp(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + public static ERemoteStoragePlatform GetSyncPlatforms(string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_GetSyncPlatforms(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2); + } + } + + /// + /// iteration + /// + public static int GetFileCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_GetFileCount(CSteamAPIContext.GetSteamRemoteStorage()); + } + + public static string GetFileNameAndSize(int iFile, out int pnFileSizeInBytes) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamRemoteStorage_GetFileNameAndSize(CSteamAPIContext.GetSteamRemoteStorage(), iFile, out pnFileSizeInBytes)); + } + + /// + /// configuration management + /// + public static bool GetQuota(out ulong pnTotalBytes, out ulong puAvailableBytes) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_GetQuota(CSteamAPIContext.GetSteamRemoteStorage(), out pnTotalBytes, out puAvailableBytes); + } + + public static bool IsCloudEnabledForAccount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_IsCloudEnabledForAccount(CSteamAPIContext.GetSteamRemoteStorage()); + } + + public static bool IsCloudEnabledForApp() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_IsCloudEnabledForApp(CSteamAPIContext.GetSteamRemoteStorage()); + } + + public static void SetCloudEnabledForApp(bool bEnabled) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamRemoteStorage_SetCloudEnabledForApp(CSteamAPIContext.GetSteamRemoteStorage(), bEnabled); + } + + /// + /// user generated content + /// Downloads a UGC file. A priority value of 0 will download the file immediately, + /// otherwise it will wait to download the file until all downloads with a lower priority + /// value are completed. Downloads with equal priority will occur simultaneously. + /// + public static SteamAPICall_t UGCDownload(UGCHandle_t hContent, uint unPriority) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_UGCDownload(CSteamAPIContext.GetSteamRemoteStorage(), hContent, unPriority); + } + + /// + /// Gets the amount of data downloaded so far for a piece of content. pnBytesExpected can be 0 if function returns false + /// or if the transfer hasn't started yet, so be careful to check for that before dividing to get a percentage + /// + public static bool GetUGCDownloadProgress(UGCHandle_t hContent, out int pnBytesDownloaded, out int pnBytesExpected) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_GetUGCDownloadProgress(CSteamAPIContext.GetSteamRemoteStorage(), hContent, out pnBytesDownloaded, out pnBytesExpected); + } + + /// + /// Gets metadata for a file after it has been downloaded. This is the same metadata given in the RemoteStorageDownloadUGCResult_t call result + /// + public static bool GetUGCDetails(UGCHandle_t hContent, out AppId_t pnAppID, out string ppchName, out int pnFileSizeInBytes, out CSteamID pSteamIDOwner) { + InteropHelp.TestIfAvailableClient(); + IntPtr ppchName2; + bool ret = NativeMethods.ISteamRemoteStorage_GetUGCDetails(CSteamAPIContext.GetSteamRemoteStorage(), hContent, out pnAppID, out ppchName2, out pnFileSizeInBytes, out pSteamIDOwner); + ppchName = ret ? InteropHelp.PtrToStringUTF8(ppchName2) : null; + return ret; + } + + /// + /// After download, gets the content of the file. + /// Small files can be read all at once by calling this function with an offset of 0 and cubDataToRead equal to the size of the file. + /// Larger files can be read in chunks to reduce memory usage (since both sides of the IPC client and the game itself must allocate + /// enough memory for each chunk). Once the last byte is read, the file is implicitly closed and further calls to UGCRead will fail + /// unless UGCDownload is called again. + /// For especially large files (anything over 100MB) it is a requirement that the file is read in chunks. + /// + public static int UGCRead(UGCHandle_t hContent, byte[] pvData, int cubDataToRead, uint cOffset, EUGCReadAction eAction) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_UGCRead(CSteamAPIContext.GetSteamRemoteStorage(), hContent, pvData, cubDataToRead, cOffset, eAction); + } + + /// + /// Functions to iterate through UGC that has finished downloading but has not yet been read via UGCRead() + /// + public static int GetCachedUGCCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_GetCachedUGCCount(CSteamAPIContext.GetSteamRemoteStorage()); + } + + public static UGCHandle_t GetCachedUGCHandle(int iCachedContent) { + InteropHelp.TestIfAvailableClient(); + return (UGCHandle_t)NativeMethods.ISteamRemoteStorage_GetCachedUGCHandle(CSteamAPIContext.GetSteamRemoteStorage(), iCachedContent); + } + + /// + /// publishing UGC + /// + public static SteamAPICall_t PublishWorkshopFile(string pchFile, string pchPreviewFile, AppId_t nConsumerAppId, string pchTitle, string pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, System.Collections.Generic.IList pTags, EWorkshopFileType eWorkshopFileType) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) + using (var pchPreviewFile2 = new InteropHelp.UTF8StringHandle(pchPreviewFile)) + using (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle)) + using (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) { + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_PublishWorkshopFile(CSteamAPIContext.GetSteamRemoteStorage(), pchFile2, pchPreviewFile2, nConsumerAppId, pchTitle2, pchDescription2, eVisibility, new InteropHelp.SteamParamStringArray(pTags), eWorkshopFileType); + } + } + + public static PublishedFileUpdateHandle_t CreatePublishedFileUpdateRequest(PublishedFileId_t unPublishedFileId) { + InteropHelp.TestIfAvailableClient(); + return (PublishedFileUpdateHandle_t)NativeMethods.ISteamRemoteStorage_CreatePublishedFileUpdateRequest(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId); + } + + public static bool UpdatePublishedFileFile(PublishedFileUpdateHandle_t updateHandle, string pchFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchFile2 = new InteropHelp.UTF8StringHandle(pchFile)) { + return NativeMethods.ISteamRemoteStorage_UpdatePublishedFileFile(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchFile2); + } + } + + public static bool UpdatePublishedFilePreviewFile(PublishedFileUpdateHandle_t updateHandle, string pchPreviewFile) { + InteropHelp.TestIfAvailableClient(); + using (var pchPreviewFile2 = new InteropHelp.UTF8StringHandle(pchPreviewFile)) { + return NativeMethods.ISteamRemoteStorage_UpdatePublishedFilePreviewFile(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchPreviewFile2); + } + } + + public static bool UpdatePublishedFileTitle(PublishedFileUpdateHandle_t updateHandle, string pchTitle) { + InteropHelp.TestIfAvailableClient(); + using (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle)) { + return NativeMethods.ISteamRemoteStorage_UpdatePublishedFileTitle(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchTitle2); + } + } + + public static bool UpdatePublishedFileDescription(PublishedFileUpdateHandle_t updateHandle, string pchDescription) { + InteropHelp.TestIfAvailableClient(); + using (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) { + return NativeMethods.ISteamRemoteStorage_UpdatePublishedFileDescription(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchDescription2); + } + } + + public static bool UpdatePublishedFileVisibility(PublishedFileUpdateHandle_t updateHandle, ERemoteStoragePublishedFileVisibility eVisibility) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_UpdatePublishedFileVisibility(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, eVisibility); + } + + public static bool UpdatePublishedFileTags(PublishedFileUpdateHandle_t updateHandle, System.Collections.Generic.IList pTags) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_UpdatePublishedFileTags(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, new InteropHelp.SteamParamStringArray(pTags)); + } + + public static SteamAPICall_t CommitPublishedFileUpdate(PublishedFileUpdateHandle_t updateHandle) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_CommitPublishedFileUpdate(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle); + } + + /// + /// Gets published file details for the given publishedfileid. If unMaxSecondsOld is greater than 0, + /// cached data may be returned, depending on how long ago it was cached. A value of 0 will force a refresh. + /// A value of k_WorkshopForceLoadPublishedFileDetailsFromCache will use cached data if it exists, no matter how old it is. + /// + public static SteamAPICall_t GetPublishedFileDetails(PublishedFileId_t unPublishedFileId, uint unMaxSecondsOld) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_GetPublishedFileDetails(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId, unMaxSecondsOld); + } + + public static SteamAPICall_t DeletePublishedFile(PublishedFileId_t unPublishedFileId) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_DeletePublishedFile(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId); + } + + /// + /// enumerate the files that the current user published with this app + /// + public static SteamAPICall_t EnumerateUserPublishedFiles(uint unStartIndex) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumerateUserPublishedFiles(CSteamAPIContext.GetSteamRemoteStorage(), unStartIndex); + } + + public static SteamAPICall_t SubscribePublishedFile(PublishedFileId_t unPublishedFileId) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_SubscribePublishedFile(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId); + } + + public static SteamAPICall_t EnumerateUserSubscribedFiles(uint unStartIndex) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumerateUserSubscribedFiles(CSteamAPIContext.GetSteamRemoteStorage(), unStartIndex); + } + + public static SteamAPICall_t UnsubscribePublishedFile(PublishedFileId_t unPublishedFileId) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_UnsubscribePublishedFile(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId); + } + + public static bool UpdatePublishedFileSetChangeDescription(PublishedFileUpdateHandle_t updateHandle, string pchChangeDescription) { + InteropHelp.TestIfAvailableClient(); + using (var pchChangeDescription2 = new InteropHelp.UTF8StringHandle(pchChangeDescription)) { + return NativeMethods.ISteamRemoteStorage_UpdatePublishedFileSetChangeDescription(CSteamAPIContext.GetSteamRemoteStorage(), updateHandle, pchChangeDescription2); + } + } + + public static SteamAPICall_t GetPublishedItemVoteDetails(PublishedFileId_t unPublishedFileId) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_GetPublishedItemVoteDetails(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId); + } + + public static SteamAPICall_t UpdateUserPublishedItemVote(PublishedFileId_t unPublishedFileId, bool bVoteUp) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_UpdateUserPublishedItemVote(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId, bVoteUp); + } + + public static SteamAPICall_t GetUserPublishedItemVoteDetails(PublishedFileId_t unPublishedFileId) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_GetUserPublishedItemVoteDetails(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId); + } + + public static SteamAPICall_t EnumerateUserSharedWorkshopFiles(CSteamID steamId, uint unStartIndex, System.Collections.Generic.IList pRequiredTags, System.Collections.Generic.IList pExcludedTags) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumerateUserSharedWorkshopFiles(CSteamAPIContext.GetSteamRemoteStorage(), steamId, unStartIndex, new InteropHelp.SteamParamStringArray(pRequiredTags), new InteropHelp.SteamParamStringArray(pExcludedTags)); + } + + public static SteamAPICall_t PublishVideo(EWorkshopVideoProvider eVideoProvider, string pchVideoAccount, string pchVideoIdentifier, string pchPreviewFile, AppId_t nConsumerAppId, string pchTitle, string pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, System.Collections.Generic.IList pTags) { + InteropHelp.TestIfAvailableClient(); + using (var pchVideoAccount2 = new InteropHelp.UTF8StringHandle(pchVideoAccount)) + using (var pchVideoIdentifier2 = new InteropHelp.UTF8StringHandle(pchVideoIdentifier)) + using (var pchPreviewFile2 = new InteropHelp.UTF8StringHandle(pchPreviewFile)) + using (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle)) + using (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) { + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_PublishVideo(CSteamAPIContext.GetSteamRemoteStorage(), eVideoProvider, pchVideoAccount2, pchVideoIdentifier2, pchPreviewFile2, nConsumerAppId, pchTitle2, pchDescription2, eVisibility, new InteropHelp.SteamParamStringArray(pTags)); + } + } + + public static SteamAPICall_t SetUserPublishedFileAction(PublishedFileId_t unPublishedFileId, EWorkshopFileAction eAction) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_SetUserPublishedFileAction(CSteamAPIContext.GetSteamRemoteStorage(), unPublishedFileId, eAction); + } + + public static SteamAPICall_t EnumeratePublishedFilesByUserAction(EWorkshopFileAction eAction, uint unStartIndex) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumeratePublishedFilesByUserAction(CSteamAPIContext.GetSteamRemoteStorage(), eAction, unStartIndex); + } + + /// + /// this method enumerates the public view of workshop files + /// + public static SteamAPICall_t EnumeratePublishedWorkshopFiles(EWorkshopEnumerationType eEnumerationType, uint unStartIndex, uint unCount, uint unDays, System.Collections.Generic.IList pTags, System.Collections.Generic.IList pUserTags) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_EnumeratePublishedWorkshopFiles(CSteamAPIContext.GetSteamRemoteStorage(), eEnumerationType, unStartIndex, unCount, unDays, new InteropHelp.SteamParamStringArray(pTags), new InteropHelp.SteamParamStringArray(pUserTags)); + } + + public static SteamAPICall_t UGCDownloadToLocation(UGCHandle_t hContent, string pchLocation, uint unPriority) { + InteropHelp.TestIfAvailableClient(); + using (var pchLocation2 = new InteropHelp.UTF8StringHandle(pchLocation)) { + return (SteamAPICall_t)NativeMethods.ISteamRemoteStorage_UGCDownloadToLocation(CSteamAPIContext.GetSteamRemoteStorage(), hContent, pchLocation2, unPriority); + } + } + + /// + /// Cloud dynamic state change notification + /// + public static int GetLocalFileChangeCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_GetLocalFileChangeCount(CSteamAPIContext.GetSteamRemoteStorage()); + } + + public static string GetLocalFileChange(int iFile, out ERemoteStorageLocalFileChange pEChangeType, out ERemoteStorageFilePathType pEFilePathType) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamRemoteStorage_GetLocalFileChange(CSteamAPIContext.GetSteamRemoteStorage(), iFile, out pEChangeType, out pEFilePathType)); + } + + /// + /// Indicate to Steam the beginning / end of a set of local file + /// operations - for example, writing a game save that requires updating two files. + /// + public static bool BeginFileWriteBatch() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_BeginFileWriteBatch(CSteamAPIContext.GetSteamRemoteStorage()); + } + + public static bool EndFileWriteBatch() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamRemoteStorage_EndFileWriteBatch(CSteamAPIContext.GetSteamRemoteStorage()); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremotestorage.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremotestorage.cs.meta new file mode 100644 index 0000000..a46f402 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremotestorage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01f81133916375e49be0c353f5c1766c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamscreenshots.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamscreenshots.cs new file mode 100644 index 0000000..4c123ec --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamscreenshots.cs @@ -0,0 +1,111 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamScreenshots { + /// + /// Writes a screenshot to the user's screenshot library given the raw image data, which must be in RGB format. + /// The return value is a handle that is valid for the duration of the game process and can be used to apply tags. + /// + public static ScreenshotHandle WriteScreenshot(byte[] pubRGB, uint cubRGB, int nWidth, int nHeight) { + InteropHelp.TestIfAvailableClient(); + return (ScreenshotHandle)NativeMethods.ISteamScreenshots_WriteScreenshot(CSteamAPIContext.GetSteamScreenshots(), pubRGB, cubRGB, nWidth, nHeight); + } + + /// + /// Adds a screenshot to the user's screenshot library from disk. If a thumbnail is provided, it must be 200 pixels wide and the same aspect ratio + /// as the screenshot, otherwise a thumbnail will be generated if the user uploads the screenshot. The screenshots must be in either JPEG or TGA format. + /// The return value is a handle that is valid for the duration of the game process and can be used to apply tags. + /// JPEG, TGA, and PNG formats are supported. + /// + public static ScreenshotHandle AddScreenshotToLibrary(string pchFilename, string pchThumbnailFilename, int nWidth, int nHeight) { + InteropHelp.TestIfAvailableClient(); + using (var pchFilename2 = new InteropHelp.UTF8StringHandle(pchFilename)) + using (var pchThumbnailFilename2 = new InteropHelp.UTF8StringHandle(pchThumbnailFilename)) { + return (ScreenshotHandle)NativeMethods.ISteamScreenshots_AddScreenshotToLibrary(CSteamAPIContext.GetSteamScreenshots(), pchFilename2, pchThumbnailFilename2, nWidth, nHeight); + } + } + + /// + /// Causes the Steam overlay to take a screenshot. If screenshots are being hooked by the game then a ScreenshotRequested_t callback is sent back to the game instead. + /// + public static void TriggerScreenshot() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamScreenshots_TriggerScreenshot(CSteamAPIContext.GetSteamScreenshots()); + } + + /// + /// Toggles whether the overlay handles screenshots when the user presses the screenshot hotkey, or the game handles them. If the game is hooking screenshots, + /// then the ScreenshotRequested_t callback will be sent if the user presses the hotkey, and the game is expected to call WriteScreenshot or AddScreenshotToLibrary + /// in response. + /// + public static void HookScreenshots(bool bHook) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamScreenshots_HookScreenshots(CSteamAPIContext.GetSteamScreenshots(), bHook); + } + + /// + /// Sets metadata about a screenshot's location (for example, the name of the map) + /// + public static bool SetLocation(ScreenshotHandle hScreenshot, string pchLocation) { + InteropHelp.TestIfAvailableClient(); + using (var pchLocation2 = new InteropHelp.UTF8StringHandle(pchLocation)) { + return NativeMethods.ISteamScreenshots_SetLocation(CSteamAPIContext.GetSteamScreenshots(), hScreenshot, pchLocation2); + } + } + + /// + /// Tags a user as being visible in the screenshot + /// + public static bool TagUser(ScreenshotHandle hScreenshot, CSteamID steamID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamScreenshots_TagUser(CSteamAPIContext.GetSteamScreenshots(), hScreenshot, steamID); + } + + /// + /// Tags a published file as being visible in the screenshot + /// + public static bool TagPublishedFile(ScreenshotHandle hScreenshot, PublishedFileId_t unPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamScreenshots_TagPublishedFile(CSteamAPIContext.GetSteamScreenshots(), hScreenshot, unPublishedFileID); + } + + /// + /// Returns true if the app has hooked the screenshot + /// + public static bool IsScreenshotsHooked() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamScreenshots_IsScreenshotsHooked(CSteamAPIContext.GetSteamScreenshots()); + } + + /// + /// Adds a VR screenshot to the user's screenshot library from disk in the supported type. + /// pchFilename should be the normal 2D image used in the library view + /// pchVRFilename should contain the image that matches the correct type + /// The return value is a handle that is valid for the duration of the game process and can be used to apply tags. + /// JPEG, TGA, and PNG formats are supported. + /// + public static ScreenshotHandle AddVRScreenshotToLibrary(EVRScreenshotType eType, string pchFilename, string pchVRFilename) { + InteropHelp.TestIfAvailableClient(); + using (var pchFilename2 = new InteropHelp.UTF8StringHandle(pchFilename)) + using (var pchVRFilename2 = new InteropHelp.UTF8StringHandle(pchVRFilename)) { + return (ScreenshotHandle)NativeMethods.ISteamScreenshots_AddVRScreenshotToLibrary(CSteamAPIContext.GetSteamScreenshots(), eType, pchFilename2, pchVRFilename2); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamscreenshots.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamscreenshots.cs.meta new file mode 100644 index 0000000..beea647 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamscreenshots.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f49256fe5fff4fd478b5b499f4a0beb2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamugc.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamugc.cs new file mode 100644 index 0000000..0bbb312 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamugc.cs @@ -0,0 +1,709 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamUGC { + /// + /// Query UGC associated with a user. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1. + /// + public static UGCQueryHandle_t CreateQueryUserUGCRequest(AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage) { + InteropHelp.TestIfAvailableClient(); + return (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryUserUGCRequest(CSteamAPIContext.GetSteamUGC(), unAccountID, eListType, eMatchingUGCType, eSortOrder, nCreatorAppID, nConsumerAppID, unPage); + } + + /// + /// Query for all matching UGC. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1. + /// + public static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint unPage) { + InteropHelp.TestIfAvailableClient(); + return (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryAllUGCRequestPage(CSteamAPIContext.GetSteamUGC(), eQueryType, eMatchingeMatchingUGCTypeFileType, nCreatorAppID, nConsumerAppID, unPage); + } + + /// + /// Query for all matching UGC using the new deep paging interface. Creator app id or consumer app id must be valid and be set to the current running app. pchCursor should be set to NULL or "*" to get the first result set. + /// + public static UGCQueryHandle_t CreateQueryAllUGCRequest(EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, string pchCursor = null) { + InteropHelp.TestIfAvailableClient(); + using (var pchCursor2 = new InteropHelp.UTF8StringHandle(pchCursor)) { + return (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryAllUGCRequestCursor(CSteamAPIContext.GetSteamUGC(), eQueryType, eMatchingeMatchingUGCTypeFileType, nCreatorAppID, nConsumerAppID, pchCursor2); + } + } + + /// + /// Query for the details of the given published file ids (the RequestUGCDetails call is deprecated and replaced with this) + /// + public static UGCQueryHandle_t CreateQueryUGCDetailsRequest(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) { + InteropHelp.TestIfAvailableClient(); + return (UGCQueryHandle_t)NativeMethods.ISteamUGC_CreateQueryUGCDetailsRequest(CSteamAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs); + } + + /// + /// Send the query to Steam + /// + public static SteamAPICall_t SendQueryUGCRequest(UGCQueryHandle_t handle) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_SendQueryUGCRequest(CSteamAPIContext.GetSteamUGC(), handle); + } + + /// + /// Retrieve an individual result after receiving the callback for querying UGC + /// + public static bool GetQueryUGCResult(UGCQueryHandle_t handle, uint index, out SteamUGCDetails_t pDetails) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetQueryUGCResult(CSteamAPIContext.GetSteamUGC(), handle, index, out pDetails); + } + + public static uint GetQueryUGCNumTags(UGCQueryHandle_t handle, uint index) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetQueryUGCNumTags(CSteamAPIContext.GetSteamUGC(), handle, index); + } + + public static bool GetQueryUGCTag(UGCQueryHandle_t handle, uint index, uint indexTag, out string pchValue, uint cchValueSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCTag(CSteamAPIContext.GetSteamUGC(), handle, index, indexTag, pchValue2, cchValueSize); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + + public static bool GetQueryUGCTagDisplayName(UGCQueryHandle_t handle, uint index, uint indexTag, out string pchValue, uint cchValueSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCTagDisplayName(CSteamAPIContext.GetSteamUGC(), handle, index, indexTag, pchValue2, cchValueSize); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + + public static bool GetQueryUGCPreviewURL(UGCQueryHandle_t handle, uint index, out string pchURL, uint cchURLSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchURL2 = Marshal.AllocHGlobal((int)cchURLSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCPreviewURL(CSteamAPIContext.GetSteamUGC(), handle, index, pchURL2, cchURLSize); + pchURL = ret ? InteropHelp.PtrToStringUTF8(pchURL2) : null; + Marshal.FreeHGlobal(pchURL2); + return ret; + } + + public static bool GetQueryUGCMetadata(UGCQueryHandle_t handle, uint index, out string pchMetadata, uint cchMetadatasize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchMetadata2 = Marshal.AllocHGlobal((int)cchMetadatasize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCMetadata(CSteamAPIContext.GetSteamUGC(), handle, index, pchMetadata2, cchMetadatasize); + pchMetadata = ret ? InteropHelp.PtrToStringUTF8(pchMetadata2) : null; + Marshal.FreeHGlobal(pchMetadata2); + return ret; + } + + public static bool GetQueryUGCChildren(UGCQueryHandle_t handle, uint index, PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetQueryUGCChildren(CSteamAPIContext.GetSteamUGC(), handle, index, pvecPublishedFileID, cMaxEntries); + } + + public static bool GetQueryUGCStatistic(UGCQueryHandle_t handle, uint index, EItemStatistic eStatType, out ulong pStatValue) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetQueryUGCStatistic(CSteamAPIContext.GetSteamUGC(), handle, index, eStatType, out pStatValue); + } + + public static uint GetQueryUGCNumAdditionalPreviews(UGCQueryHandle_t handle, uint index) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetQueryUGCNumAdditionalPreviews(CSteamAPIContext.GetSteamUGC(), handle, index); + } + + public static bool GetQueryUGCAdditionalPreview(UGCQueryHandle_t handle, uint index, uint previewIndex, out string pchURLOrVideoID, uint cchURLSize, out string pchOriginalFileName, uint cchOriginalFileNameSize, out EItemPreviewType pPreviewType) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchURLOrVideoID2 = Marshal.AllocHGlobal((int)cchURLSize); + IntPtr pchOriginalFileName2 = Marshal.AllocHGlobal((int)cchOriginalFileNameSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCAdditionalPreview(CSteamAPIContext.GetSteamUGC(), handle, index, previewIndex, pchURLOrVideoID2, cchURLSize, pchOriginalFileName2, cchOriginalFileNameSize, out pPreviewType); + pchURLOrVideoID = ret ? InteropHelp.PtrToStringUTF8(pchURLOrVideoID2) : null; + Marshal.FreeHGlobal(pchURLOrVideoID2); + pchOriginalFileName = ret ? InteropHelp.PtrToStringUTF8(pchOriginalFileName2) : null; + Marshal.FreeHGlobal(pchOriginalFileName2); + return ret; + } + + public static uint GetQueryUGCNumKeyValueTags(UGCQueryHandle_t handle, uint index) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetQueryUGCNumKeyValueTags(CSteamAPIContext.GetSteamUGC(), handle, index); + } + + public static bool GetQueryUGCKeyValueTag(UGCQueryHandle_t handle, uint index, uint keyValueTagIndex, out string pchKey, uint cchKeySize, out string pchValue, uint cchValueSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchKey2 = Marshal.AllocHGlobal((int)cchKeySize); + IntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize); + bool ret = NativeMethods.ISteamUGC_GetQueryUGCKeyValueTag(CSteamAPIContext.GetSteamUGC(), handle, index, keyValueTagIndex, pchKey2, cchKeySize, pchValue2, cchValueSize); + pchKey = ret ? InteropHelp.PtrToStringUTF8(pchKey2) : null; + Marshal.FreeHGlobal(pchKey2); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + + /// + /// Return the first value matching the pchKey. Note that a key may map to multiple values. Returns false if there was an error or no matching value was found. + /// + public static bool GetQueryUGCKeyValueTag(UGCQueryHandle_t handle, uint index, string pchKey, out string pchValue, uint cchValueSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchValue2 = Marshal.AllocHGlobal((int)cchValueSize); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + bool ret = NativeMethods.ISteamUGC_GetQueryFirstUGCKeyValueTag(CSteamAPIContext.GetSteamUGC(), handle, index, pchKey2, pchValue2, cchValueSize); + pchValue = ret ? InteropHelp.PtrToStringUTF8(pchValue2) : null; + Marshal.FreeHGlobal(pchValue2); + return ret; + } + } + + public static uint GetQueryUGCContentDescriptors(UGCQueryHandle_t handle, uint index, out EUGCContentDescriptorID pvecDescriptors, uint cMaxEntries) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetQueryUGCContentDescriptors(CSteamAPIContext.GetSteamUGC(), handle, index, out pvecDescriptors, cMaxEntries); + } + + /// + /// Release the request to free up memory, after retrieving results + /// + public static bool ReleaseQueryUGCRequest(UGCQueryHandle_t handle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_ReleaseQueryUGCRequest(CSteamAPIContext.GetSteamUGC(), handle); + } + + /// + /// Options to set for querying UGC + /// + public static bool AddRequiredTag(UGCQueryHandle_t handle, string pTagName) { + InteropHelp.TestIfAvailableClient(); + using (var pTagName2 = new InteropHelp.UTF8StringHandle(pTagName)) { + return NativeMethods.ISteamUGC_AddRequiredTag(CSteamAPIContext.GetSteamUGC(), handle, pTagName2); + } + } + + /// + /// match any of the tags in this group + /// + public static bool AddRequiredTagGroup(UGCQueryHandle_t handle, System.Collections.Generic.IList pTagGroups) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_AddRequiredTagGroup(CSteamAPIContext.GetSteamUGC(), handle, new InteropHelp.SteamParamStringArray(pTagGroups)); + } + + public static bool AddExcludedTag(UGCQueryHandle_t handle, string pTagName) { + InteropHelp.TestIfAvailableClient(); + using (var pTagName2 = new InteropHelp.UTF8StringHandle(pTagName)) { + return NativeMethods.ISteamUGC_AddExcludedTag(CSteamAPIContext.GetSteamUGC(), handle, pTagName2); + } + } + + public static bool SetReturnOnlyIDs(UGCQueryHandle_t handle, bool bReturnOnlyIDs) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetReturnOnlyIDs(CSteamAPIContext.GetSteamUGC(), handle, bReturnOnlyIDs); + } + + public static bool SetReturnKeyValueTags(UGCQueryHandle_t handle, bool bReturnKeyValueTags) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetReturnKeyValueTags(CSteamAPIContext.GetSteamUGC(), handle, bReturnKeyValueTags); + } + + public static bool SetReturnLongDescription(UGCQueryHandle_t handle, bool bReturnLongDescription) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetReturnLongDescription(CSteamAPIContext.GetSteamUGC(), handle, bReturnLongDescription); + } + + public static bool SetReturnMetadata(UGCQueryHandle_t handle, bool bReturnMetadata) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetReturnMetadata(CSteamAPIContext.GetSteamUGC(), handle, bReturnMetadata); + } + + public static bool SetReturnChildren(UGCQueryHandle_t handle, bool bReturnChildren) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetReturnChildren(CSteamAPIContext.GetSteamUGC(), handle, bReturnChildren); + } + + public static bool SetReturnAdditionalPreviews(UGCQueryHandle_t handle, bool bReturnAdditionalPreviews) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetReturnAdditionalPreviews(CSteamAPIContext.GetSteamUGC(), handle, bReturnAdditionalPreviews); + } + + public static bool SetReturnTotalOnly(UGCQueryHandle_t handle, bool bReturnTotalOnly) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetReturnTotalOnly(CSteamAPIContext.GetSteamUGC(), handle, bReturnTotalOnly); + } + + public static bool SetReturnPlaytimeStats(UGCQueryHandle_t handle, uint unDays) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetReturnPlaytimeStats(CSteamAPIContext.GetSteamUGC(), handle, unDays); + } + + public static bool SetLanguage(UGCQueryHandle_t handle, string pchLanguage) { + InteropHelp.TestIfAvailableClient(); + using (var pchLanguage2 = new InteropHelp.UTF8StringHandle(pchLanguage)) { + return NativeMethods.ISteamUGC_SetLanguage(CSteamAPIContext.GetSteamUGC(), handle, pchLanguage2); + } + } + + public static bool SetAllowCachedResponse(UGCQueryHandle_t handle, uint unMaxAgeSeconds) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetAllowCachedResponse(CSteamAPIContext.GetSteamUGC(), handle, unMaxAgeSeconds); + } + + /// + /// Options only for querying user UGC + /// + public static bool SetCloudFileNameFilter(UGCQueryHandle_t handle, string pMatchCloudFileName) { + InteropHelp.TestIfAvailableClient(); + using (var pMatchCloudFileName2 = new InteropHelp.UTF8StringHandle(pMatchCloudFileName)) { + return NativeMethods.ISteamUGC_SetCloudFileNameFilter(CSteamAPIContext.GetSteamUGC(), handle, pMatchCloudFileName2); + } + } + + /// + /// Options only for querying all UGC + /// + public static bool SetMatchAnyTag(UGCQueryHandle_t handle, bool bMatchAnyTag) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetMatchAnyTag(CSteamAPIContext.GetSteamUGC(), handle, bMatchAnyTag); + } + + public static bool SetSearchText(UGCQueryHandle_t handle, string pSearchText) { + InteropHelp.TestIfAvailableClient(); + using (var pSearchText2 = new InteropHelp.UTF8StringHandle(pSearchText)) { + return NativeMethods.ISteamUGC_SetSearchText(CSteamAPIContext.GetSteamUGC(), handle, pSearchText2); + } + } + + public static bool SetRankedByTrendDays(UGCQueryHandle_t handle, uint unDays) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetRankedByTrendDays(CSteamAPIContext.GetSteamUGC(), handle, unDays); + } + + public static bool SetTimeCreatedDateRange(UGCQueryHandle_t handle, uint rtStart, uint rtEnd) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetTimeCreatedDateRange(CSteamAPIContext.GetSteamUGC(), handle, rtStart, rtEnd); + } + + public static bool SetTimeUpdatedDateRange(UGCQueryHandle_t handle, uint rtStart, uint rtEnd) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetTimeUpdatedDateRange(CSteamAPIContext.GetSteamUGC(), handle, rtStart, rtEnd); + } + + public static bool AddRequiredKeyValueTag(UGCQueryHandle_t handle, string pKey, string pValue) { + InteropHelp.TestIfAvailableClient(); + using (var pKey2 = new InteropHelp.UTF8StringHandle(pKey)) + using (var pValue2 = new InteropHelp.UTF8StringHandle(pValue)) { + return NativeMethods.ISteamUGC_AddRequiredKeyValueTag(CSteamAPIContext.GetSteamUGC(), handle, pKey2, pValue2); + } + } + + /// + /// DEPRECATED - Use CreateQueryUGCDetailsRequest call above instead! + /// + public static SteamAPICall_t RequestUGCDetails(PublishedFileId_t nPublishedFileID, uint unMaxAgeSeconds) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_RequestUGCDetails(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, unMaxAgeSeconds); + } + + /// + /// Steam Workshop Creator API + /// create new item for this app with no content attached yet + /// + public static SteamAPICall_t CreateItem(AppId_t nConsumerAppId, EWorkshopFileType eFileType) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_CreateItem(CSteamAPIContext.GetSteamUGC(), nConsumerAppId, eFileType); + } + + /// + /// start an UGC item update. Set changed properties before commiting update with CommitItemUpdate() + /// + public static UGCUpdateHandle_t StartItemUpdate(AppId_t nConsumerAppId, PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (UGCUpdateHandle_t)NativeMethods.ISteamUGC_StartItemUpdate(CSteamAPIContext.GetSteamUGC(), nConsumerAppId, nPublishedFileID); + } + + /// + /// change the title of an UGC item + /// + public static bool SetItemTitle(UGCUpdateHandle_t handle, string pchTitle) { + InteropHelp.TestIfAvailableClient(); + using (var pchTitle2 = new InteropHelp.UTF8StringHandle(pchTitle)) { + return NativeMethods.ISteamUGC_SetItemTitle(CSteamAPIContext.GetSteamUGC(), handle, pchTitle2); + } + } + + /// + /// change the description of an UGC item + /// + public static bool SetItemDescription(UGCUpdateHandle_t handle, string pchDescription) { + InteropHelp.TestIfAvailableClient(); + using (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) { + return NativeMethods.ISteamUGC_SetItemDescription(CSteamAPIContext.GetSteamUGC(), handle, pchDescription2); + } + } + + /// + /// specify the language of the title or description that will be set + /// + public static bool SetItemUpdateLanguage(UGCUpdateHandle_t handle, string pchLanguage) { + InteropHelp.TestIfAvailableClient(); + using (var pchLanguage2 = new InteropHelp.UTF8StringHandle(pchLanguage)) { + return NativeMethods.ISteamUGC_SetItemUpdateLanguage(CSteamAPIContext.GetSteamUGC(), handle, pchLanguage2); + } + } + + /// + /// change the metadata of an UGC item (max = k_cchDeveloperMetadataMax) + /// + public static bool SetItemMetadata(UGCUpdateHandle_t handle, string pchMetaData) { + InteropHelp.TestIfAvailableClient(); + using (var pchMetaData2 = new InteropHelp.UTF8StringHandle(pchMetaData)) { + return NativeMethods.ISteamUGC_SetItemMetadata(CSteamAPIContext.GetSteamUGC(), handle, pchMetaData2); + } + } + + /// + /// change the visibility of an UGC item + /// + public static bool SetItemVisibility(UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility eVisibility) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetItemVisibility(CSteamAPIContext.GetSteamUGC(), handle, eVisibility); + } + + /// + /// change the tags of an UGC item + /// + public static bool SetItemTags(UGCUpdateHandle_t updateHandle, System.Collections.Generic.IList pTags) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetItemTags(CSteamAPIContext.GetSteamUGC(), updateHandle, new InteropHelp.SteamParamStringArray(pTags)); + } + + /// + /// update item content from this local folder + /// + public static bool SetItemContent(UGCUpdateHandle_t handle, string pszContentFolder) { + InteropHelp.TestIfAvailableClient(); + using (var pszContentFolder2 = new InteropHelp.UTF8StringHandle(pszContentFolder)) { + return NativeMethods.ISteamUGC_SetItemContent(CSteamAPIContext.GetSteamUGC(), handle, pszContentFolder2); + } + } + + /// + /// change preview image file for this item. pszPreviewFile points to local image file, which must be under 1MB in size + /// + public static bool SetItemPreview(UGCUpdateHandle_t handle, string pszPreviewFile) { + InteropHelp.TestIfAvailableClient(); + using (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) { + return NativeMethods.ISteamUGC_SetItemPreview(CSteamAPIContext.GetSteamUGC(), handle, pszPreviewFile2); + } + } + + /// + /// use legacy upload for a single small file. The parameter to SetItemContent() should either be a directory with one file or the full path to the file. The file must also be less than 10MB in size. + /// + public static bool SetAllowLegacyUpload(UGCUpdateHandle_t handle, bool bAllowLegacyUpload) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_SetAllowLegacyUpload(CSteamAPIContext.GetSteamUGC(), handle, bAllowLegacyUpload); + } + + /// + /// remove all existing key-value tags (you can add new ones via the AddItemKeyValueTag function) + /// + public static bool RemoveAllItemKeyValueTags(UGCUpdateHandle_t handle) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_RemoveAllItemKeyValueTags(CSteamAPIContext.GetSteamUGC(), handle); + } + + /// + /// remove any existing key-value tags with the specified key + /// + public static bool RemoveItemKeyValueTags(UGCUpdateHandle_t handle, string pchKey) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + return NativeMethods.ISteamUGC_RemoveItemKeyValueTags(CSteamAPIContext.GetSteamUGC(), handle, pchKey2); + } + } + + /// + /// add new key-value tags for the item. Note that there can be multiple values for a tag. + /// + public static bool AddItemKeyValueTag(UGCUpdateHandle_t handle, string pchKey, string pchValue) { + InteropHelp.TestIfAvailableClient(); + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) + using (var pchValue2 = new InteropHelp.UTF8StringHandle(pchValue)) { + return NativeMethods.ISteamUGC_AddItemKeyValueTag(CSteamAPIContext.GetSteamUGC(), handle, pchKey2, pchValue2); + } + } + + /// + /// add preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size + /// + public static bool AddItemPreviewFile(UGCUpdateHandle_t handle, string pszPreviewFile, EItemPreviewType type) { + InteropHelp.TestIfAvailableClient(); + using (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) { + return NativeMethods.ISteamUGC_AddItemPreviewFile(CSteamAPIContext.GetSteamUGC(), handle, pszPreviewFile2, type); + } + } + + /// + /// add preview video for this item + /// + public static bool AddItemPreviewVideo(UGCUpdateHandle_t handle, string pszVideoID) { + InteropHelp.TestIfAvailableClient(); + using (var pszVideoID2 = new InteropHelp.UTF8StringHandle(pszVideoID)) { + return NativeMethods.ISteamUGC_AddItemPreviewVideo(CSteamAPIContext.GetSteamUGC(), handle, pszVideoID2); + } + } + + /// + /// updates an existing preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size + /// + public static bool UpdateItemPreviewFile(UGCUpdateHandle_t handle, uint index, string pszPreviewFile) { + InteropHelp.TestIfAvailableClient(); + using (var pszPreviewFile2 = new InteropHelp.UTF8StringHandle(pszPreviewFile)) { + return NativeMethods.ISteamUGC_UpdateItemPreviewFile(CSteamAPIContext.GetSteamUGC(), handle, index, pszPreviewFile2); + } + } + + /// + /// updates an existing preview video for this item + /// + public static bool UpdateItemPreviewVideo(UGCUpdateHandle_t handle, uint index, string pszVideoID) { + InteropHelp.TestIfAvailableClient(); + using (var pszVideoID2 = new InteropHelp.UTF8StringHandle(pszVideoID)) { + return NativeMethods.ISteamUGC_UpdateItemPreviewVideo(CSteamAPIContext.GetSteamUGC(), handle, index, pszVideoID2); + } + } + + /// + /// remove a preview by index starting at 0 (previews are sorted) + /// + public static bool RemoveItemPreview(UGCUpdateHandle_t handle, uint index) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_RemoveItemPreview(CSteamAPIContext.GetSteamUGC(), handle, index); + } + + public static bool AddContentDescriptor(UGCUpdateHandle_t handle, EUGCContentDescriptorID descid) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_AddContentDescriptor(CSteamAPIContext.GetSteamUGC(), handle, descid); + } + + public static bool RemoveContentDescriptor(UGCUpdateHandle_t handle, EUGCContentDescriptorID descid) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_RemoveContentDescriptor(CSteamAPIContext.GetSteamUGC(), handle, descid); + } + + /// + /// commit update process started with StartItemUpdate() + /// + public static SteamAPICall_t SubmitItemUpdate(UGCUpdateHandle_t handle, string pchChangeNote) { + InteropHelp.TestIfAvailableClient(); + using (var pchChangeNote2 = new InteropHelp.UTF8StringHandle(pchChangeNote)) { + return (SteamAPICall_t)NativeMethods.ISteamUGC_SubmitItemUpdate(CSteamAPIContext.GetSteamUGC(), handle, pchChangeNote2); + } + } + + public static EItemUpdateStatus GetItemUpdateProgress(UGCUpdateHandle_t handle, out ulong punBytesProcessed, out ulong punBytesTotal) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetItemUpdateProgress(CSteamAPIContext.GetSteamUGC(), handle, out punBytesProcessed, out punBytesTotal); + } + + /// + /// Steam Workshop Consumer API + /// + public static SteamAPICall_t SetUserItemVote(PublishedFileId_t nPublishedFileID, bool bVoteUp) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_SetUserItemVote(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, bVoteUp); + } + + public static SteamAPICall_t GetUserItemVote(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_GetUserItemVote(CSteamAPIContext.GetSteamUGC(), nPublishedFileID); + } + + public static SteamAPICall_t AddItemToFavorites(AppId_t nAppId, PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_AddItemToFavorites(CSteamAPIContext.GetSteamUGC(), nAppId, nPublishedFileID); + } + + public static SteamAPICall_t RemoveItemFromFavorites(AppId_t nAppId, PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveItemFromFavorites(CSteamAPIContext.GetSteamUGC(), nAppId, nPublishedFileID); + } + + /// + /// subscribe to this item, will be installed ASAP + /// + public static SteamAPICall_t SubscribeItem(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_SubscribeItem(CSteamAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// unsubscribe from this item, will be uninstalled after game quits + /// + public static SteamAPICall_t UnsubscribeItem(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_UnsubscribeItem(CSteamAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// number of subscribed items + /// + public static uint GetNumSubscribedItems() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetNumSubscribedItems(CSteamAPIContext.GetSteamUGC()); + } + + /// + /// all subscribed item PublishFileIDs + /// + public static uint GetSubscribedItems(PublishedFileId_t[] pvecPublishedFileID, uint cMaxEntries) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetSubscribedItems(CSteamAPIContext.GetSteamUGC(), pvecPublishedFileID, cMaxEntries); + } + + /// + /// get EItemState flags about item on this client + /// + public static uint GetItemState(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetItemState(CSteamAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// get info about currently installed content on disc for items that have k_EItemStateInstalled set + /// if k_EItemStateLegacyItem is set, pchFolder contains the path to the legacy file itself (not a folder) + /// + public static bool GetItemInstallInfo(PublishedFileId_t nPublishedFileID, out ulong punSizeOnDisk, out string pchFolder, uint cchFolderSize, out uint punTimeStamp) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchFolder2 = Marshal.AllocHGlobal((int)cchFolderSize); + bool ret = NativeMethods.ISteamUGC_GetItemInstallInfo(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, out punSizeOnDisk, pchFolder2, cchFolderSize, out punTimeStamp); + pchFolder = ret ? InteropHelp.PtrToStringUTF8(pchFolder2) : null; + Marshal.FreeHGlobal(pchFolder2); + return ret; + } + + /// + /// get info about pending update for items that have k_EItemStateNeedsUpdate set. punBytesTotal will be valid after download started once + /// + public static bool GetItemDownloadInfo(PublishedFileId_t nPublishedFileID, out ulong punBytesDownloaded, out ulong punBytesTotal) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_GetItemDownloadInfo(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, out punBytesDownloaded, out punBytesTotal); + } + + /// + /// download new or update already installed item. If function returns true, wait for DownloadItemResult_t. If the item is already installed, + /// then files on disk should not be used until callback received. If item is not subscribed to, it will be cached for some time. + /// If bHighPriority is set, any other item download will be suspended and this item downloaded ASAP. + /// + public static bool DownloadItem(PublishedFileId_t nPublishedFileID, bool bHighPriority) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_DownloadItem(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, bHighPriority); + } + + /// + /// game servers can set a specific workshop folder before issuing any UGC commands. + /// This is helpful if you want to support multiple game servers running out of the same install folder + /// + public static bool BInitWorkshopForGameServer(DepotId_t unWorkshopDepotID, string pszFolder) { + InteropHelp.TestIfAvailableClient(); + using (var pszFolder2 = new InteropHelp.UTF8StringHandle(pszFolder)) { + return NativeMethods.ISteamUGC_BInitWorkshopForGameServer(CSteamAPIContext.GetSteamUGC(), unWorkshopDepotID, pszFolder2); + } + } + + /// + /// SuspendDownloads( true ) will suspend all workshop downloads until SuspendDownloads( false ) is called or the game ends + /// + public static void SuspendDownloads(bool bSuspend) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUGC_SuspendDownloads(CSteamAPIContext.GetSteamUGC(), bSuspend); + } + + /// + /// usage tracking + /// + public static SteamAPICall_t StartPlaytimeTracking(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_StartPlaytimeTracking(CSteamAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs); + } + + public static SteamAPICall_t StopPlaytimeTracking(PublishedFileId_t[] pvecPublishedFileID, uint unNumPublishedFileIDs) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_StopPlaytimeTracking(CSteamAPIContext.GetSteamUGC(), pvecPublishedFileID, unNumPublishedFileIDs); + } + + public static SteamAPICall_t StopPlaytimeTrackingForAllItems() { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_StopPlaytimeTrackingForAllItems(CSteamAPIContext.GetSteamUGC()); + } + + /// + /// parent-child relationship or dependency management + /// + public static SteamAPICall_t AddDependency(PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_AddDependency(CSteamAPIContext.GetSteamUGC(), nParentPublishedFileID, nChildPublishedFileID); + } + + public static SteamAPICall_t RemoveDependency(PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveDependency(CSteamAPIContext.GetSteamUGC(), nParentPublishedFileID, nChildPublishedFileID); + } + + /// + /// add/remove app dependence/requirements (usually DLC) + /// + public static SteamAPICall_t AddAppDependency(PublishedFileId_t nPublishedFileID, AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_AddAppDependency(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, nAppID); + } + + public static SteamAPICall_t RemoveAppDependency(PublishedFileId_t nPublishedFileID, AppId_t nAppID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_RemoveAppDependency(CSteamAPIContext.GetSteamUGC(), nPublishedFileID, nAppID); + } + + /// + /// request app dependencies. note that whatever callback you register for GetAppDependenciesResult_t may be called multiple times + /// until all app dependencies have been returned + /// + public static SteamAPICall_t GetAppDependencies(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_GetAppDependencies(CSteamAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// delete the item without prompting the user + /// + public static SteamAPICall_t DeleteItem(PublishedFileId_t nPublishedFileID) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_DeleteItem(CSteamAPIContext.GetSteamUGC(), nPublishedFileID); + } + + /// + /// Show the app's latest Workshop EULA to the user in an overlay window, where they can accept it or not + /// + public static bool ShowWorkshopEULA() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUGC_ShowWorkshopEULA(CSteamAPIContext.GetSteamUGC()); + } + + /// + /// Retrieve information related to the user's acceptance or not of the app's specific Workshop EULA + /// + public static SteamAPICall_t GetWorkshopEULAStatus() { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUGC_GetWorkshopEULAStatus(CSteamAPIContext.GetSteamUGC()); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamugc.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamugc.cs.meta new file mode 100644 index 0000000..a939549 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamugc.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c0cc287de2de90479be73251828d936 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuser.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuser.cs new file mode 100644 index 0000000..7fff6ac --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuser.cs @@ -0,0 +1,381 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamUser { + /// + /// returns the HSteamUser this interface represents + /// this is only used internally by the API, and by a few select interfaces that support multi-user + /// + public static HSteamUser GetHSteamUser() { + InteropHelp.TestIfAvailableClient(); + return (HSteamUser)NativeMethods.ISteamUser_GetHSteamUser(CSteamAPIContext.GetSteamUser()); + } + + /// + /// returns true if the Steam client current has a live connection to the Steam servers. + /// If false, it means there is no active connection due to either a networking issue on the local machine, or the Steam server is down/busy. + /// The Steam client will automatically be trying to recreate the connection as often as possible. + /// + public static bool BLoggedOn() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_BLoggedOn(CSteamAPIContext.GetSteamUser()); + } + + /// + /// returns the CSteamID of the account currently logged into the Steam client + /// a CSteamID is a unique identifier for an account, and used to differentiate users in all parts of the Steamworks API + /// + public static CSteamID GetSteamID() { + InteropHelp.TestIfAvailableClient(); + return (CSteamID)NativeMethods.ISteamUser_GetSteamID(CSteamAPIContext.GetSteamUser()); + } + + /// + /// Multiplayer Authentication functions + /// InitiateGameConnection() starts the state machine for authenticating the game client with the game server + /// It is the client portion of a three-way handshake between the client, the game server, and the steam servers + /// Parameters: + /// void *pAuthBlob - a pointer to empty memory that will be filled in with the authentication token. + /// int cbMaxAuthBlob - the number of bytes of allocated memory in pBlob. Should be at least 2048 bytes. + /// CSteamID steamIDGameServer - the steamID of the game server, received from the game server by the client + /// CGameID gameID - the ID of the current game. For games without mods, this is just CGameID( <appID> ) + /// uint32 unIPServer, uint16 usPortServer - the IP address of the game server + /// bool bSecure - whether or not the client thinks that the game server is reporting itself as secure (i.e. VAC is running) + /// return value - returns the number of bytes written to pBlob. If the return is 0, then the buffer passed in was too small, and the call has failed + /// The contents of pBlob should then be sent to the game server, for it to use to complete the authentication process. + /// DEPRECATED! This function will be removed from the SDK in an upcoming version. + /// Please migrate to BeginAuthSession and related functions. + /// + public static int InitiateGameConnection_DEPRECATED(byte[] pAuthBlob, int cbMaxAuthBlob, CSteamID steamIDGameServer, uint unIPServer, ushort usPortServer, bool bSecure) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_InitiateGameConnection_DEPRECATED(CSteamAPIContext.GetSteamUser(), pAuthBlob, cbMaxAuthBlob, steamIDGameServer, unIPServer, usPortServer, bSecure); + } + + /// + /// notify of disconnect + /// needs to occur when the game client leaves the specified game server, needs to match with the InitiateGameConnection() call + /// DEPRECATED! This function will be removed from the SDK in an upcoming version. + /// Please migrate to BeginAuthSession and related functions. + /// + public static void TerminateGameConnection_DEPRECATED(uint unIPServer, ushort usPortServer) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUser_TerminateGameConnection_DEPRECATED(CSteamAPIContext.GetSteamUser(), unIPServer, usPortServer); + } + + /// + /// Legacy functions + /// used by only a few games to track usage events + /// + public static void TrackAppUsageEvent(CGameID gameID, int eAppUsageEvent, string pchExtraInfo = "") { + InteropHelp.TestIfAvailableClient(); + using (var pchExtraInfo2 = new InteropHelp.UTF8StringHandle(pchExtraInfo)) { + NativeMethods.ISteamUser_TrackAppUsageEvent(CSteamAPIContext.GetSteamUser(), gameID, eAppUsageEvent, pchExtraInfo2); + } + } + + /// + /// get the local storage folder for current Steam account to write application data, e.g. save games, configs etc. + /// this will usually be something like "C:\Progam Files\Steam\userdata\<SteamID>\<AppID>\local" + /// + public static bool GetUserDataFolder(out string pchBuffer, int cubBuffer) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchBuffer2 = Marshal.AllocHGlobal(cubBuffer); + bool ret = NativeMethods.ISteamUser_GetUserDataFolder(CSteamAPIContext.GetSteamUser(), pchBuffer2, cubBuffer); + pchBuffer = ret ? InteropHelp.PtrToStringUTF8(pchBuffer2) : null; + Marshal.FreeHGlobal(pchBuffer2); + return ret; + } + + /// + /// Starts voice recording. Once started, use GetVoice() to get the data + /// + public static void StartVoiceRecording() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUser_StartVoiceRecording(CSteamAPIContext.GetSteamUser()); + } + + /// + /// Stops voice recording. Because people often release push-to-talk keys early, the system will keep recording for + /// a little bit after this function is called. GetVoice() should continue to be called until it returns + /// k_eVoiceResultNotRecording + /// + public static void StopVoiceRecording() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUser_StopVoiceRecording(CSteamAPIContext.GetSteamUser()); + } + + /// + /// Determine the size of captured audio data that is available from GetVoice. + /// Most applications will only use compressed data and should ignore the other + /// parameters, which exist primarily for backwards compatibility. See comments + /// below for further explanation of "uncompressed" data. + /// + public static EVoiceResult GetAvailableVoice(out uint pcbCompressed) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_GetAvailableVoice(CSteamAPIContext.GetSteamUser(), out pcbCompressed, IntPtr.Zero, 0); + } + + /// + /// --------------------------------------------------------------------------- + /// NOTE: "uncompressed" audio is a deprecated feature and should not be used + /// by most applications. It is raw single-channel 16-bit PCM wave data which + /// may have been run through preprocessing filters and/or had silence removed, + /// so the uncompressed audio could have a shorter duration than you expect. + /// There may be no data at all during long periods of silence. Also, fetching + /// uncompressed audio will cause GetVoice to discard any leftover compressed + /// audio, so you must fetch both types at once. Finally, GetAvailableVoice is + /// not precisely accurate when the uncompressed size is requested. So if you + /// really need to use uncompressed audio, you should call GetVoice frequently + /// with two very large (20kb+) output buffers instead of trying to allocate + /// perfectly-sized buffers. But most applications should ignore all of these + /// details and simply leave the "uncompressed" parameters as NULL/zero. + /// --------------------------------------------------------------------------- + /// Read captured audio data from the microphone buffer. This should be called + /// at least once per frame, and preferably every few milliseconds, to keep the + /// microphone input delay as low as possible. Most applications will only use + /// compressed data and should pass NULL/zero for the "uncompressed" parameters. + /// Compressed data can be transmitted by your application and decoded into raw + /// using the DecompressVoice function below. + /// + public static EVoiceResult GetVoice(bool bWantCompressed, byte[] pDestBuffer, uint cbDestBufferSize, out uint nBytesWritten) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_GetVoice(CSteamAPIContext.GetSteamUser(), bWantCompressed, pDestBuffer, cbDestBufferSize, out nBytesWritten, false, IntPtr.Zero, 0, IntPtr.Zero, 0); + } + + /// + /// Decodes the compressed voice data returned by GetVoice. The output data is + /// raw single-channel 16-bit PCM audio. The decoder supports any sample rate + /// from 11025 to 48000; see GetVoiceOptimalSampleRate() below for details. + /// If the output buffer is not large enough, then *nBytesWritten will be set + /// to the required buffer size, and k_EVoiceResultBufferTooSmall is returned. + /// It is suggested to start with a 20kb buffer and reallocate as necessary. + /// + public static EVoiceResult DecompressVoice(byte[] pCompressed, uint cbCompressed, byte[] pDestBuffer, uint cbDestBufferSize, out uint nBytesWritten, uint nDesiredSampleRate) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_DecompressVoice(CSteamAPIContext.GetSteamUser(), pCompressed, cbCompressed, pDestBuffer, cbDestBufferSize, out nBytesWritten, nDesiredSampleRate); + } + + /// + /// This returns the native sample rate of the Steam voice decompressor; using + /// this sample rate for DecompressVoice will perform the least CPU processing. + /// However, the final audio quality will depend on how well the audio device + /// (and/or your application's audio output SDK) deals with lower sample rates. + /// You may find that you get the best audio output quality when you ignore + /// this function and use the native sample rate of your audio output device, + /// which is usually 48000 or 44100. + /// + public static uint GetVoiceOptimalSampleRate() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_GetVoiceOptimalSampleRate(CSteamAPIContext.GetSteamUser()); + } + + /// + /// Retrieve ticket to be sent to the entity who wishes to authenticate you. + /// pcbTicket retrieves the length of the actual ticket. + /// SteamNetworkingIdentity is an optional input parameter to hold the public IP address or SteamID of the entity you are connecting to + /// if an IP address is passed Steam will only allow the ticket to be used by an entity with that IP address + /// if a Steam ID is passed Steam will only allow the ticket to be used by that Steam ID + /// not to be used for "ISteamUserAuth\AuthenticateUserTicket" - it will fail + /// + public static HAuthTicket GetAuthSessionTicket(byte[] pTicket, int cbMaxTicket, out uint pcbTicket, ref SteamNetworkingIdentity pSteamNetworkingIdentity) { + InteropHelp.TestIfAvailableClient(); + return (HAuthTicket)NativeMethods.ISteamUser_GetAuthSessionTicket(CSteamAPIContext.GetSteamUser(), pTicket, cbMaxTicket, out pcbTicket, ref pSteamNetworkingIdentity); + } + + /// + /// Request a ticket which will be used for webapi "ISteamUserAuth\AuthenticateUserTicket" + /// pchIdentity is an optional input parameter to identify the service the ticket will be sent to + /// the ticket will be returned in callback GetTicketForWebApiResponse_t + /// + public static HAuthTicket GetAuthTicketForWebApi(string pchIdentity) { + InteropHelp.TestIfAvailableClient(); + using (var pchIdentity2 = new InteropHelp.UTF8StringHandle(pchIdentity)) { + return (HAuthTicket)NativeMethods.ISteamUser_GetAuthTicketForWebApi(CSteamAPIContext.GetSteamUser(), pchIdentity2); + } + } + + /// + /// Authenticate ticket from entity steamID to be sure it is valid and isnt reused + /// Registers for callbacks if the entity goes offline or cancels the ticket ( see ValidateAuthTicketResponse_t callback and EAuthSessionResponse ) + /// + public static EBeginAuthSessionResult BeginAuthSession(byte[] pAuthTicket, int cbAuthTicket, CSteamID steamID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_BeginAuthSession(CSteamAPIContext.GetSteamUser(), pAuthTicket, cbAuthTicket, steamID); + } + + /// + /// Stop tracking started by BeginAuthSession - called when no longer playing game with this entity + /// + public static void EndAuthSession(CSteamID steamID) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUser_EndAuthSession(CSteamAPIContext.GetSteamUser(), steamID); + } + + /// + /// Cancel auth ticket from GetAuthSessionTicket, called when no longer playing game with the entity you gave the ticket to + /// + public static void CancelAuthTicket(HAuthTicket hAuthTicket) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUser_CancelAuthTicket(CSteamAPIContext.GetSteamUser(), hAuthTicket); + } + + /// + /// After receiving a user's authentication data, and passing it to BeginAuthSession, use this function + /// to determine if the user owns downloadable content specified by the provided AppID. + /// + public static EUserHasLicenseForAppResult UserHasLicenseForApp(CSteamID steamID, AppId_t appID) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_UserHasLicenseForApp(CSteamAPIContext.GetSteamUser(), steamID, appID); + } + + /// + /// returns true if this users looks like they are behind a NAT device. Only valid once the user has connected to steam + /// (i.e a SteamServersConnected_t has been issued) and may not catch all forms of NAT. + /// + public static bool BIsBehindNAT() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_BIsBehindNAT(CSteamAPIContext.GetSteamUser()); + } + + /// + /// set data to be replicated to friends so that they can join your game + /// CSteamID steamIDGameServer - the steamID of the game server, received from the game server by the client + /// uint32 unIPServer, uint16 usPortServer - the IP address of the game server + /// + public static void AdvertiseGame(CSteamID steamIDGameServer, uint unIPServer, ushort usPortServer) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUser_AdvertiseGame(CSteamAPIContext.GetSteamUser(), steamIDGameServer, unIPServer, usPortServer); + } + + /// + /// Requests a ticket encrypted with an app specific shared key + /// pDataToInclude, cbDataToInclude will be encrypted into the ticket + /// ( This is asynchronous, you must wait for the ticket to be completed by the server ) + /// + public static SteamAPICall_t RequestEncryptedAppTicket(byte[] pDataToInclude, int cbDataToInclude) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUser_RequestEncryptedAppTicket(CSteamAPIContext.GetSteamUser(), pDataToInclude, cbDataToInclude); + } + + /// + /// Retrieves a finished ticket. + /// If no ticket is available, or your buffer is too small, returns false. + /// Upon exit, *pcbTicket will be either the size of the ticket copied into your buffer + /// (if true was returned), or the size needed (if false was returned). To determine the + /// proper size of the ticket, you can pass pTicket=NULL and cbMaxTicket=0; if a ticket + /// is available, *pcbTicket will contain the size needed, otherwise it will be zero. + /// + public static bool GetEncryptedAppTicket(byte[] pTicket, int cbMaxTicket, out uint pcbTicket) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_GetEncryptedAppTicket(CSteamAPIContext.GetSteamUser(), pTicket, cbMaxTicket, out pcbTicket); + } + + /// + /// Trading Card badges data access + /// if you only have one set of cards, the series will be 1 + /// the user has can have two different badges for a series; the regular (max level 5) and the foil (max level 1) + /// + public static int GetGameBadgeLevel(int nSeries, bool bFoil) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_GetGameBadgeLevel(CSteamAPIContext.GetSteamUser(), nSeries, bFoil); + } + + /// + /// gets the Steam Level of the user, as shown on their profile + /// + public static int GetPlayerSteamLevel() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_GetPlayerSteamLevel(CSteamAPIContext.GetSteamUser()); + } + + /// + /// Requests a URL which authenticates an in-game browser for store check-out, + /// and then redirects to the specified URL. As long as the in-game browser + /// accepts and handles session cookies, Steam microtransaction checkout pages + /// will automatically recognize the user instead of presenting a login page. + /// The result of this API call will be a StoreAuthURLResponse_t callback. + /// NOTE: The URL has a very short lifetime to prevent history-snooping attacks, + /// so you should only call this API when you are about to launch the browser, + /// or else immediately navigate to the result URL using a hidden browser window. + /// NOTE 2: The resulting authorization cookie has an expiration time of one day, + /// so it would be a good idea to request and visit a new auth URL every 12 hours. + /// + public static SteamAPICall_t RequestStoreAuthURL(string pchRedirectURL) { + InteropHelp.TestIfAvailableClient(); + using (var pchRedirectURL2 = new InteropHelp.UTF8StringHandle(pchRedirectURL)) { + return (SteamAPICall_t)NativeMethods.ISteamUser_RequestStoreAuthURL(CSteamAPIContext.GetSteamUser(), pchRedirectURL2); + } + } + + /// + /// gets whether the users phone number is verified + /// + public static bool BIsPhoneVerified() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_BIsPhoneVerified(CSteamAPIContext.GetSteamUser()); + } + + /// + /// gets whether the user has two factor enabled on their account + /// + public static bool BIsTwoFactorEnabled() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_BIsTwoFactorEnabled(CSteamAPIContext.GetSteamUser()); + } + + /// + /// gets whether the users phone number is identifying + /// + public static bool BIsPhoneIdentifying() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_BIsPhoneIdentifying(CSteamAPIContext.GetSteamUser()); + } + + /// + /// gets whether the users phone number is awaiting (re)verification + /// + public static bool BIsPhoneRequiringVerification() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_BIsPhoneRequiringVerification(CSteamAPIContext.GetSteamUser()); + } + + public static SteamAPICall_t GetMarketEligibility() { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUser_GetMarketEligibility(CSteamAPIContext.GetSteamUser()); + } + + /// + /// Retrieves anti indulgence / duration control for current user + /// + public static SteamAPICall_t GetDurationControl() { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUser_GetDurationControl(CSteamAPIContext.GetSteamUser()); + } + + /// + /// Advise steam china duration control system about the online state of the game. + /// This will prevent offline gameplay time from counting against a user's + /// playtime limits. + /// + public static bool BSetDurationControlOnlineState(EDurationControlOnlineState eNewState) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUser_BSetDurationControlOnlineState(CSteamAPIContext.GetSteamUser(), eNewState); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuser.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuser.cs.meta new file mode 100644 index 0000000..bf3276b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b73c7aa3e2082434c854c9c7e17ccfd8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuserstats.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuserstats.cs new file mode 100644 index 0000000..97bf38a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuserstats.cs @@ -0,0 +1,474 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamUserStats { + /// + /// Ask the server to send down this user's data and achievements for this game + /// + public static bool RequestCurrentStats() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUserStats_RequestCurrentStats(CSteamAPIContext.GetSteamUserStats()); + } + + /// + /// Data accessors + /// + public static bool GetStat(string pchName, out int pData) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetStatInt32(CSteamAPIContext.GetSteamUserStats(), pchName2, out pData); + } + } + + public static bool GetStat(string pchName, out float pData) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetStatFloat(CSteamAPIContext.GetSteamUserStats(), pchName2, out pData); + } + } + + /// + /// Set / update data + /// + public static bool SetStat(string pchName, int nData) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_SetStatInt32(CSteamAPIContext.GetSteamUserStats(), pchName2, nData); + } + } + + public static bool SetStat(string pchName, float fData) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_SetStatFloat(CSteamAPIContext.GetSteamUserStats(), pchName2, fData); + } + } + + public static bool UpdateAvgRateStat(string pchName, float flCountThisSession, double dSessionLength) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_UpdateAvgRateStat(CSteamAPIContext.GetSteamUserStats(), pchName2, flCountThisSession, dSessionLength); + } + } + + /// + /// Achievement flag accessors + /// + public static bool GetAchievement(string pchName, out bool pbAchieved) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetAchievement(CSteamAPIContext.GetSteamUserStats(), pchName2, out pbAchieved); + } + } + + public static bool SetAchievement(string pchName) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_SetAchievement(CSteamAPIContext.GetSteamUserStats(), pchName2); + } + } + + public static bool ClearAchievement(string pchName) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_ClearAchievement(CSteamAPIContext.GetSteamUserStats(), pchName2); + } + } + + /// + /// Get the achievement status, and the time it was unlocked if unlocked. + /// If the return value is true, but the unlock time is zero, that means it was unlocked before Steam + /// began tracking achievement unlock times (December 2009). Time is seconds since January 1, 1970. + /// + public static bool GetAchievementAndUnlockTime(string pchName, out bool pbAchieved, out uint punUnlockTime) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetAchievementAndUnlockTime(CSteamAPIContext.GetSteamUserStats(), pchName2, out pbAchieved, out punUnlockTime); + } + } + + /// + /// Store the current data on the server, will get a callback when set + /// And one callback for every new achievement + /// If the callback has a result of k_EResultInvalidParam, one or more stats + /// uploaded has been rejected, either because they broke constraints + /// or were out of date. In this case the server sends back updated values. + /// The stats should be re-iterated to keep in sync. + /// + public static bool StoreStats() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUserStats_StoreStats(CSteamAPIContext.GetSteamUserStats()); + } + + /// + /// Achievement / GroupAchievement metadata + /// Gets the icon of the achievement, which is a handle to be used in ISteamUtils::GetImageRGBA(), or 0 if none set. + /// A return value of 0 may indicate we are still fetching data, and you can wait for the UserAchievementIconFetched_t callback + /// which will notify you when the bits are ready. If the callback still returns zero, then there is no image set for the + /// specified achievement. + /// + public static int GetAchievementIcon(string pchName) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetAchievementIcon(CSteamAPIContext.GetSteamUserStats(), pchName2); + } + } + + /// + /// Get general attributes for an achievement. Accepts the following keys: + /// - "name" and "desc" for retrieving the localized achievement name and description (returned in UTF8) + /// - "hidden" for retrieving if an achievement is hidden (returns "0" when not hidden, "1" when hidden) + /// + public static string GetAchievementDisplayAttribute(string pchName, string pchKey) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) + using (var pchKey2 = new InteropHelp.UTF8StringHandle(pchKey)) { + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUserStats_GetAchievementDisplayAttribute(CSteamAPIContext.GetSteamUserStats(), pchName2, pchKey2)); + } + } + + /// + /// Achievement progress - triggers an AchievementProgress callback, that is all. + /// Calling this w/ N out of N progress will NOT set the achievement, the game must still do that. + /// + public static bool IndicateAchievementProgress(string pchName, uint nCurProgress, uint nMaxProgress) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_IndicateAchievementProgress(CSteamAPIContext.GetSteamUserStats(), pchName2, nCurProgress, nMaxProgress); + } + } + + /// + /// Used for iterating achievements. In general games should not need these functions because they should have a + /// list of existing achievements compiled into them + /// + public static uint GetNumAchievements() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUserStats_GetNumAchievements(CSteamAPIContext.GetSteamUserStats()); + } + + /// + /// Get achievement name iAchievement in [0,GetNumAchievements) + /// + public static string GetAchievementName(uint iAchievement) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUserStats_GetAchievementName(CSteamAPIContext.GetSteamUserStats(), iAchievement)); + } + + /// + /// Friends stats & achievements + /// downloads stats for the user + /// returns a UserStatsReceived_t received when completed + /// if the other user has no stats, UserStatsReceived_t.m_eResult will be set to k_EResultFail + /// these stats won't be auto-updated; you'll need to call RequestUserStats() again to refresh any data + /// + public static SteamAPICall_t RequestUserStats(CSteamID steamIDUser) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUserStats_RequestUserStats(CSteamAPIContext.GetSteamUserStats(), steamIDUser); + } + + /// + /// requests stat information for a user, usable after a successful call to RequestUserStats() + /// + public static bool GetUserStat(CSteamID steamIDUser, string pchName, out int pData) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetUserStatInt32(CSteamAPIContext.GetSteamUserStats(), steamIDUser, pchName2, out pData); + } + } + + public static bool GetUserStat(CSteamID steamIDUser, string pchName, out float pData) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetUserStatFloat(CSteamAPIContext.GetSteamUserStats(), steamIDUser, pchName2, out pData); + } + } + + public static bool GetUserAchievement(CSteamID steamIDUser, string pchName, out bool pbAchieved) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetUserAchievement(CSteamAPIContext.GetSteamUserStats(), steamIDUser, pchName2, out pbAchieved); + } + } + + /// + /// See notes for GetAchievementAndUnlockTime above + /// + public static bool GetUserAchievementAndUnlockTime(CSteamID steamIDUser, string pchName, out bool pbAchieved, out uint punUnlockTime) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetUserAchievementAndUnlockTime(CSteamAPIContext.GetSteamUserStats(), steamIDUser, pchName2, out pbAchieved, out punUnlockTime); + } + } + + /// + /// Reset stats + /// + public static bool ResetAllStats(bool bAchievementsToo) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUserStats_ResetAllStats(CSteamAPIContext.GetSteamUserStats(), bAchievementsToo); + } + + /// + /// Leaderboard functions + /// asks the Steam back-end for a leaderboard by name, and will create it if it's not yet + /// This call is asynchronous, with the result returned in LeaderboardFindResult_t + /// + public static SteamAPICall_t FindOrCreateLeaderboard(string pchLeaderboardName, ELeaderboardSortMethod eLeaderboardSortMethod, ELeaderboardDisplayType eLeaderboardDisplayType) { + InteropHelp.TestIfAvailableClient(); + using (var pchLeaderboardName2 = new InteropHelp.UTF8StringHandle(pchLeaderboardName)) { + return (SteamAPICall_t)NativeMethods.ISteamUserStats_FindOrCreateLeaderboard(CSteamAPIContext.GetSteamUserStats(), pchLeaderboardName2, eLeaderboardSortMethod, eLeaderboardDisplayType); + } + } + + /// + /// as above, but won't create the leaderboard if it's not found + /// This call is asynchronous, with the result returned in LeaderboardFindResult_t + /// + public static SteamAPICall_t FindLeaderboard(string pchLeaderboardName) { + InteropHelp.TestIfAvailableClient(); + using (var pchLeaderboardName2 = new InteropHelp.UTF8StringHandle(pchLeaderboardName)) { + return (SteamAPICall_t)NativeMethods.ISteamUserStats_FindLeaderboard(CSteamAPIContext.GetSteamUserStats(), pchLeaderboardName2); + } + } + + /// + /// returns the name of a leaderboard + /// + public static string GetLeaderboardName(SteamLeaderboard_t hSteamLeaderboard) { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUserStats_GetLeaderboardName(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard)); + } + + /// + /// returns the total number of entries in a leaderboard, as of the last request + /// + public static int GetLeaderboardEntryCount(SteamLeaderboard_t hSteamLeaderboard) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUserStats_GetLeaderboardEntryCount(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard); + } + + /// + /// returns the sort method of the leaderboard + /// + public static ELeaderboardSortMethod GetLeaderboardSortMethod(SteamLeaderboard_t hSteamLeaderboard) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUserStats_GetLeaderboardSortMethod(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard); + } + + /// + /// returns the display type of the leaderboard + /// + public static ELeaderboardDisplayType GetLeaderboardDisplayType(SteamLeaderboard_t hSteamLeaderboard) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUserStats_GetLeaderboardDisplayType(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard); + } + + /// + /// Asks the Steam back-end for a set of rows in the leaderboard. + /// This call is asynchronous, with the result returned in LeaderboardScoresDownloaded_t + /// LeaderboardScoresDownloaded_t will contain a handle to pull the results from GetDownloadedLeaderboardEntries() (below) + /// You can ask for more entries than exist, and it will return as many as do exist. + /// k_ELeaderboardDataRequestGlobal requests rows in the leaderboard from the full table, with nRangeStart & nRangeEnd in the range [1, TotalEntries] + /// k_ELeaderboardDataRequestGlobalAroundUser requests rows around the current user, nRangeStart being negate + /// e.g. DownloadLeaderboardEntries( hLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -3, 3 ) will return 7 rows, 3 before the user, 3 after + /// k_ELeaderboardDataRequestFriends requests all the rows for friends of the current user + /// + public static SteamAPICall_t DownloadLeaderboardEntries(SteamLeaderboard_t hSteamLeaderboard, ELeaderboardDataRequest eLeaderboardDataRequest, int nRangeStart, int nRangeEnd) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUserStats_DownloadLeaderboardEntries(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard, eLeaderboardDataRequest, nRangeStart, nRangeEnd); + } + + /// + /// as above, but downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is k_ELeaderboardDataRequestUsers + /// if a user doesn't have a leaderboard entry, they won't be included in the result + /// a max of 100 users can be downloaded at a time, with only one outstanding call at a time + /// + public static SteamAPICall_t DownloadLeaderboardEntriesForUsers(SteamLeaderboard_t hSteamLeaderboard, CSteamID[] prgUsers, int cUsers) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUserStats_DownloadLeaderboardEntriesForUsers(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard, prgUsers, cUsers); + } + + /// + /// Returns data about a single leaderboard entry + /// use a for loop from 0 to LeaderboardScoresDownloaded_t::m_cEntryCount to get all the downloaded entries + /// e.g. + /// void OnLeaderboardScoresDownloaded( LeaderboardScoresDownloaded_t *pLeaderboardScoresDownloaded ) + /// { + /// for ( int index = 0; index < pLeaderboardScoresDownloaded->m_cEntryCount; index++ ) + /// { + /// LeaderboardEntry_t leaderboardEntry; + /// int32 details[3]; // we know this is how many we've stored previously + /// GetDownloadedLeaderboardEntry( pLeaderboardScoresDownloaded->m_hSteamLeaderboardEntries, index, &leaderboardEntry, details, 3 ); + /// assert( leaderboardEntry.m_cDetails == 3 ); + /// ... + /// } + /// once you've accessed all the entries, the data will be free'd, and the SteamLeaderboardEntries_t handle will become invalid + /// + public static bool GetDownloadedLeaderboardEntry(SteamLeaderboardEntries_t hSteamLeaderboardEntries, int index, out LeaderboardEntry_t pLeaderboardEntry, int[] pDetails, int cDetailsMax) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUserStats_GetDownloadedLeaderboardEntry(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboardEntries, index, out pLeaderboardEntry, pDetails, cDetailsMax); + } + + /// + /// Uploads a user score to the Steam back-end. + /// This call is asynchronous, with the result returned in LeaderboardScoreUploaded_t + /// Details are extra game-defined information regarding how the user got that score + /// pScoreDetails points to an array of int32's, cScoreDetailsCount is the number of int32's in the list + /// + public static SteamAPICall_t UploadLeaderboardScore(SteamLeaderboard_t hSteamLeaderboard, ELeaderboardUploadScoreMethod eLeaderboardUploadScoreMethod, int nScore, int[] pScoreDetails, int cScoreDetailsCount) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUserStats_UploadLeaderboardScore(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard, eLeaderboardUploadScoreMethod, nScore, pScoreDetails, cScoreDetailsCount); + } + + /// + /// Attaches a piece of user generated content the user's entry on a leaderboard. + /// hContent is a handle to a piece of user generated content that was shared using ISteamUserRemoteStorage::FileShare(). + /// This call is asynchronous, with the result returned in LeaderboardUGCSet_t. + /// + public static SteamAPICall_t AttachLeaderboardUGC(SteamLeaderboard_t hSteamLeaderboard, UGCHandle_t hUGC) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUserStats_AttachLeaderboardUGC(CSteamAPIContext.GetSteamUserStats(), hSteamLeaderboard, hUGC); + } + + /// + /// Retrieves the number of players currently playing your game (online + offline) + /// This call is asynchronous, with the result returned in NumberOfCurrentPlayers_t + /// + public static SteamAPICall_t GetNumberOfCurrentPlayers() { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUserStats_GetNumberOfCurrentPlayers(CSteamAPIContext.GetSteamUserStats()); + } + + /// + /// Requests that Steam fetch data on the percentage of players who have received each achievement + /// for the game globally. + /// This call is asynchronous, with the result returned in GlobalAchievementPercentagesReady_t. + /// + public static SteamAPICall_t RequestGlobalAchievementPercentages() { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUserStats_RequestGlobalAchievementPercentages(CSteamAPIContext.GetSteamUserStats()); + } + + /// + /// Get the info on the most achieved achievement for the game, returns an iterator index you can use to fetch + /// the next most achieved afterwards. Will return -1 if there is no data on achievement + /// percentages (ie, you haven't called RequestGlobalAchievementPercentages and waited on the callback). + /// + public static int GetMostAchievedAchievementInfo(out string pchName, uint unNameBufLen, out float pflPercent, out bool pbAchieved) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchName2 = Marshal.AllocHGlobal((int)unNameBufLen); + int ret = NativeMethods.ISteamUserStats_GetMostAchievedAchievementInfo(CSteamAPIContext.GetSteamUserStats(), pchName2, unNameBufLen, out pflPercent, out pbAchieved); + pchName = ret != -1 ? InteropHelp.PtrToStringUTF8(pchName2) : null; + Marshal.FreeHGlobal(pchName2); + return ret; + } + + /// + /// Get the info on the next most achieved achievement for the game. Call this after GetMostAchievedAchievementInfo or another + /// GetNextMostAchievedAchievementInfo call passing the iterator from the previous call. Returns -1 after the last + /// achievement has been iterated. + /// + public static int GetNextMostAchievedAchievementInfo(int iIteratorPrevious, out string pchName, uint unNameBufLen, out float pflPercent, out bool pbAchieved) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchName2 = Marshal.AllocHGlobal((int)unNameBufLen); + int ret = NativeMethods.ISteamUserStats_GetNextMostAchievedAchievementInfo(CSteamAPIContext.GetSteamUserStats(), iIteratorPrevious, pchName2, unNameBufLen, out pflPercent, out pbAchieved); + pchName = ret != -1 ? InteropHelp.PtrToStringUTF8(pchName2) : null; + Marshal.FreeHGlobal(pchName2); + return ret; + } + + /// + /// Returns the percentage of users who have achieved the specified achievement. + /// + public static bool GetAchievementAchievedPercent(string pchName, out float pflPercent) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetAchievementAchievedPercent(CSteamAPIContext.GetSteamUserStats(), pchName2, out pflPercent); + } + } + + /// + /// Requests global stats data, which is available for stats marked as "aggregated". + /// This call is asynchronous, with the results returned in GlobalStatsReceived_t. + /// nHistoryDays specifies how many days of day-by-day history to retrieve in addition + /// to the overall totals. The limit is 60. + /// + public static SteamAPICall_t RequestGlobalStats(int nHistoryDays) { + InteropHelp.TestIfAvailableClient(); + return (SteamAPICall_t)NativeMethods.ISteamUserStats_RequestGlobalStats(CSteamAPIContext.GetSteamUserStats(), nHistoryDays); + } + + /// + /// Gets the lifetime totals for an aggregated stat + /// + public static bool GetGlobalStat(string pchStatName, out long pData) { + InteropHelp.TestIfAvailableClient(); + using (var pchStatName2 = new InteropHelp.UTF8StringHandle(pchStatName)) { + return NativeMethods.ISteamUserStats_GetGlobalStatInt64(CSteamAPIContext.GetSteamUserStats(), pchStatName2, out pData); + } + } + + public static bool GetGlobalStat(string pchStatName, out double pData) { + InteropHelp.TestIfAvailableClient(); + using (var pchStatName2 = new InteropHelp.UTF8StringHandle(pchStatName)) { + return NativeMethods.ISteamUserStats_GetGlobalStatDouble(CSteamAPIContext.GetSteamUserStats(), pchStatName2, out pData); + } + } + + /// + /// Gets history for an aggregated stat. pData will be filled with daily values, starting with today. + /// So when called, pData[0] will be today, pData[1] will be yesterday, and pData[2] will be two days ago, + /// etc. cubData is the size in bytes of the pubData buffer. Returns the number of + /// elements actually set. + /// + public static int GetGlobalStatHistory(string pchStatName, long[] pData, uint cubData) { + InteropHelp.TestIfAvailableClient(); + using (var pchStatName2 = new InteropHelp.UTF8StringHandle(pchStatName)) { + return NativeMethods.ISteamUserStats_GetGlobalStatHistoryInt64(CSteamAPIContext.GetSteamUserStats(), pchStatName2, pData, cubData); + } + } + + public static int GetGlobalStatHistory(string pchStatName, double[] pData, uint cubData) { + InteropHelp.TestIfAvailableClient(); + using (var pchStatName2 = new InteropHelp.UTF8StringHandle(pchStatName)) { + return NativeMethods.ISteamUserStats_GetGlobalStatHistoryDouble(CSteamAPIContext.GetSteamUserStats(), pchStatName2, pData, cubData); + } + } + + /// + /// For achievements that have related Progress stats, use this to query what the bounds of that progress are. + /// You may want this info to selectively call IndicateAchievementProgress when appropriate milestones of progress + /// have been made, to show a progress notification to the user. + /// + public static bool GetAchievementProgressLimits(string pchName, out int pnMinProgress, out int pnMaxProgress) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetAchievementProgressLimitsInt32(CSteamAPIContext.GetSteamUserStats(), pchName2, out pnMinProgress, out pnMaxProgress); + } + } + + public static bool GetAchievementProgressLimits(string pchName, out float pfMinProgress, out float pfMaxProgress) { + InteropHelp.TestIfAvailableClient(); + using (var pchName2 = new InteropHelp.UTF8StringHandle(pchName)) { + return NativeMethods.ISteamUserStats_GetAchievementProgressLimitsFloat(CSteamAPIContext.GetSteamUserStats(), pchName2, out pfMinProgress, out pfMaxProgress); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuserstats.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuserstats.cs.meta new file mode 100644 index 0000000..87748eb --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuserstats.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c63c24edcbb001443a96ccfd6bb09d30 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamutils.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamutils.cs new file mode 100644 index 0000000..1952b10 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamutils.cs @@ -0,0 +1,356 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamUtils { + /// + /// return the number of seconds since the user + /// + public static uint GetSecondsSinceAppActive() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetSecondsSinceAppActive(CSteamAPIContext.GetSteamUtils()); + } + + public static uint GetSecondsSinceComputerActive() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetSecondsSinceComputerActive(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// the universe this client is connecting to + /// + public static EUniverse GetConnectedUniverse() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetConnectedUniverse(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Steam server time. Number of seconds since January 1, 1970, GMT (i.e unix time) + /// + public static uint GetServerRealTime() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetServerRealTime(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via an IP-to-location database) + /// e.g "US" or "UK". + /// + public static string GetIPCountry() { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUtils_GetIPCountry(CSteamAPIContext.GetSteamUtils())); + } + + /// + /// returns true if the image exists, and valid sizes were filled out + /// + public static bool GetImageSize(int iImage, out uint pnWidth, out uint pnHeight) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetImageSize(CSteamAPIContext.GetSteamUtils(), iImage, out pnWidth, out pnHeight); + } + + /// + /// returns true if the image exists, and the buffer was successfully filled out + /// results are returned in RGBA format + /// the destination buffer size should be 4 * height * width * sizeof(char) + /// + public static bool GetImageRGBA(int iImage, byte[] pubDest, int nDestBufferSize) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetImageRGBA(CSteamAPIContext.GetSteamUtils(), iImage, pubDest, nDestBufferSize); + } + + /// + /// return the amount of battery power left in the current system in % [0..100], 255 for being on AC power + /// + public static byte GetCurrentBatteryPower() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetCurrentBatteryPower(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// returns the appID of the current process + /// + public static AppId_t GetAppID() { + InteropHelp.TestIfAvailableClient(); + return (AppId_t)NativeMethods.ISteamUtils_GetAppID(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Sets the position where the overlay instance for the currently calling game should show notifications. + /// This position is per-game and if this function is called from outside of a game context it will do nothing. + /// + public static void SetOverlayNotificationPosition(ENotificationPosition eNotificationPosition) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUtils_SetOverlayNotificationPosition(CSteamAPIContext.GetSteamUtils(), eNotificationPosition); + } + + /// + /// API asynchronous call results + /// can be used directly, but more commonly used via the callback dispatch API (see steam_api.h) + /// + public static bool IsAPICallCompleted(SteamAPICall_t hSteamAPICall, out bool pbFailed) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_IsAPICallCompleted(CSteamAPIContext.GetSteamUtils(), hSteamAPICall, out pbFailed); + } + + public static ESteamAPICallFailure GetAPICallFailureReason(SteamAPICall_t hSteamAPICall) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetAPICallFailureReason(CSteamAPIContext.GetSteamUtils(), hSteamAPICall); + } + + public static bool GetAPICallResult(SteamAPICall_t hSteamAPICall, IntPtr pCallback, int cubCallback, int iCallbackExpected, out bool pbFailed) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetAPICallResult(CSteamAPIContext.GetSteamUtils(), hSteamAPICall, pCallback, cubCallback, iCallbackExpected, out pbFailed); + } + + /// + /// returns the number of IPC calls made since the last time this function was called + /// Used for perf debugging so you can understand how many IPC calls your game makes per frame + /// Every IPC call is at minimum a thread context switch if not a process one so you want to rate + /// control how often you do them. + /// + public static uint GetIPCCallCount() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetIPCCallCount(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// API warning handling + /// 'int' is the severity; 0 for msg, 1 for warning + /// 'const char *' is the text of the message + /// callbacks will occur directly after the API function is called that generated the warning or message + /// + public static void SetWarningMessageHook(SteamAPIWarningMessageHook_t pFunction) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUtils_SetWarningMessageHook(CSteamAPIContext.GetSteamUtils(), pFunction); + } + + /// + /// Returns true if the overlay is running & the user can access it. The overlay process could take a few seconds to + /// start & hook the game process, so this function will initially return false while the overlay is loading. + /// + public static bool IsOverlayEnabled() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_IsOverlayEnabled(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Normally this call is unneeded if your game has a constantly running frame loop that calls the + /// D3D Present API, or OGL SwapBuffers API every frame. + /// However, if you have a game that only refreshes the screen on an event driven basis then that can break + /// the overlay, as it uses your Present/SwapBuffers calls to drive it's internal frame loop and it may also + /// need to Present() to the screen any time an even needing a notification happens or when the overlay is + /// brought up over the game by a user. You can use this API to ask the overlay if it currently need a present + /// in that case, and then you can check for this periodically (roughly 33hz is desirable) and make sure you + /// refresh the screen with Present or SwapBuffers to allow the overlay to do it's work. + /// + public static bool BOverlayNeedsPresent() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_BOverlayNeedsPresent(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Asynchronous call to check if an executable file has been signed using the public key set on the signing tab + /// of the partner site, for example to refuse to load modified executable files. + /// The result is returned in CheckFileSignature_t. + /// k_ECheckFileSignatureNoSignaturesFoundForThisApp - This app has not been configured on the signing tab of the partner site to enable this function. + /// k_ECheckFileSignatureNoSignaturesFoundForThisFile - This file is not listed on the signing tab for the partner site. + /// k_ECheckFileSignatureFileNotFound - The file does not exist on disk. + /// k_ECheckFileSignatureInvalidSignature - The file exists, and the signing tab has been set for this file, but the file is either not signed or the signature does not match. + /// k_ECheckFileSignatureValidSignature - The file is signed and the signature is valid. + /// + public static SteamAPICall_t CheckFileSignature(string szFileName) { + InteropHelp.TestIfAvailableClient(); + using (var szFileName2 = new InteropHelp.UTF8StringHandle(szFileName)) { + return (SteamAPICall_t)NativeMethods.ISteamUtils_CheckFileSignature(CSteamAPIContext.GetSteamUtils(), szFileName2); + } + } + + /// + /// Activates the full-screen text input dialog which takes a initial text string and returns the text the user has typed + /// + public static bool ShowGamepadTextInput(EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, string pchDescription, uint unCharMax, string pchExistingText) { + InteropHelp.TestIfAvailableClient(); + using (var pchDescription2 = new InteropHelp.UTF8StringHandle(pchDescription)) + using (var pchExistingText2 = new InteropHelp.UTF8StringHandle(pchExistingText)) { + return NativeMethods.ISteamUtils_ShowGamepadTextInput(CSteamAPIContext.GetSteamUtils(), eInputMode, eLineInputMode, pchDescription2, unCharMax, pchExistingText2); + } + } + + /// + /// Returns previously entered text & length + /// + public static uint GetEnteredGamepadTextLength() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetEnteredGamepadTextLength(CSteamAPIContext.GetSteamUtils()); + } + + public static bool GetEnteredGamepadTextInput(out string pchText, uint cchText) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchText2 = Marshal.AllocHGlobal((int)cchText); + bool ret = NativeMethods.ISteamUtils_GetEnteredGamepadTextInput(CSteamAPIContext.GetSteamUtils(), pchText2, cchText); + pchText = ret ? InteropHelp.PtrToStringUTF8(pchText2) : null; + Marshal.FreeHGlobal(pchText2); + return ret; + } + + /// + /// returns the language the steam client is running in, you probably want ISteamApps::GetCurrentGameLanguage instead, this is for very special usage cases + /// + public static string GetSteamUILanguage() { + InteropHelp.TestIfAvailableClient(); + return InteropHelp.PtrToStringUTF8(NativeMethods.ISteamUtils_GetSteamUILanguage(CSteamAPIContext.GetSteamUtils())); + } + + /// + /// returns true if Steam itself is running in VR mode + /// + public static bool IsSteamRunningInVR() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_IsSteamRunningInVR(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Sets the inset of the overlay notification from the corner specified by SetOverlayNotificationPosition. + /// + public static void SetOverlayNotificationInset(int nHorizontalInset, int nVerticalInset) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUtils_SetOverlayNotificationInset(CSteamAPIContext.GetSteamUtils(), nHorizontalInset, nVerticalInset); + } + + /// + /// returns true if Steam & the Steam Overlay are running in Big Picture mode + /// Games much be launched through the Steam client to enable the Big Picture overlay. During development, + /// a game can be added as a non-steam game to the developers library to test this feature + /// + public static bool IsSteamInBigPictureMode() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_IsSteamInBigPictureMode(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// ask SteamUI to create and render its OpenVR dashboard + /// + public static void StartVRDashboard() { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUtils_StartVRDashboard(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Returns true if the HMD content will be streamed via Steam Remote Play + /// + public static bool IsVRHeadsetStreamingEnabled() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_IsVRHeadsetStreamingEnabled(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Set whether the HMD content will be streamed via Steam Remote Play + /// If this is set to true, then the scene in the HMD headset will be streamed, and remote input will not be allowed. + /// If this is set to false, then the application window will be streamed instead, and remote input will be allowed. + /// The default is true unless "VRHeadsetStreaming" "0" is in the extended appinfo for a game. + /// (this is useful for games that have asymmetric multiplayer gameplay) + /// + public static void SetVRHeadsetStreamingEnabled(bool bEnabled) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUtils_SetVRHeadsetStreamingEnabled(CSteamAPIContext.GetSteamUtils(), bEnabled); + } + + /// + /// Returns whether this steam client is a Steam China specific client, vs the global client. + /// + public static bool IsSteamChinaLauncher() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_IsSteamChinaLauncher(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Initializes text filtering, loading dictionaries for the language the game is running in. + /// unFilterOptions are reserved for future use and should be set to 0 + /// Returns false if filtering is unavailable for the game's language, in which case FilterText() will act as a passthrough. + /// Users can customize the text filter behavior in their Steam Account preferences: + /// https://store.steampowered.com/account/preferences#CommunityContentPreferences + /// + public static bool InitFilterText(uint unFilterOptions = 0) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_InitFilterText(CSteamAPIContext.GetSteamUtils(), unFilterOptions); + } + + /// + /// Filters the provided input message and places the filtered result into pchOutFilteredText, using legally required filtering and additional filtering based on the context and user settings + /// eContext is the type of content in the input string + /// sourceSteamID is the Steam ID that is the source of the input string (e.g. the player with the name, or who said the chat text) + /// pchInputText is the input string that should be filtered, which can be ASCII or UTF-8 + /// pchOutFilteredText is where the output will be placed, even if no filtering is performed + /// nByteSizeOutFilteredText is the size (in bytes) of pchOutFilteredText, should be at least strlen(pchInputText)+1 + /// Returns the number of characters (not bytes) filtered + /// + public static int FilterText(ETextFilteringContext eContext, CSteamID sourceSteamID, string pchInputMessage, out string pchOutFilteredText, uint nByteSizeOutFilteredText) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchOutFilteredText2 = Marshal.AllocHGlobal((int)nByteSizeOutFilteredText); + using (var pchInputMessage2 = new InteropHelp.UTF8StringHandle(pchInputMessage)) { + int ret = NativeMethods.ISteamUtils_FilterText(CSteamAPIContext.GetSteamUtils(), eContext, sourceSteamID, pchInputMessage2, pchOutFilteredText2, nByteSizeOutFilteredText); + pchOutFilteredText = ret != -1 ? InteropHelp.PtrToStringUTF8(pchOutFilteredText2) : null; + Marshal.FreeHGlobal(pchOutFilteredText2); + return ret; + } + } + + /// + /// Return what we believe your current ipv6 connectivity to "the internet" is on the specified protocol. + /// This does NOT tell you if the Steam client is currently connected to Steam via ipv6. + /// + public static ESteamIPv6ConnectivityState GetIPv6ConnectivityState(ESteamIPv6ConnectivityProtocol eProtocol) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_GetIPv6ConnectivityState(CSteamAPIContext.GetSteamUtils(), eProtocol); + } + + /// + /// returns true if currently running on the Steam Deck device + /// + public static bool IsSteamRunningOnSteamDeck() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_IsSteamRunningOnSteamDeck(CSteamAPIContext.GetSteamUtils()); + } + + /// + /// Opens a floating keyboard over the game content and sends OS keyboard keys directly to the game. + /// The text field position is specified in pixels relative the origin of the game window and is used to position the floating keyboard in a way that doesn't cover the text field + /// + public static bool ShowFloatingGamepadTextInput(EFloatingGamepadTextInputMode eKeyboardMode, int nTextFieldXPosition, int nTextFieldYPosition, int nTextFieldWidth, int nTextFieldHeight) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_ShowFloatingGamepadTextInput(CSteamAPIContext.GetSteamUtils(), eKeyboardMode, nTextFieldXPosition, nTextFieldYPosition, nTextFieldWidth, nTextFieldHeight); + } + + /// + /// In game launchers that don't have controller support you can call this to have Steam Input translate the controller input into mouse/kb to navigate the launcher + /// + public static void SetGameLauncherMode(bool bLauncherMode) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamUtils_SetGameLauncherMode(CSteamAPIContext.GetSteamUtils(), bLauncherMode); + } + + /// + /// Dismisses the floating keyboard. + /// + public static bool DismissFloatingGamepadTextInput() { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamUtils_DismissFloatingGamepadTextInput(CSteamAPIContext.GetSteamUtils()); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamutils.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamutils.cs.meta new file mode 100644 index 0000000..52ae12a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamutils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d33733b93da525840ba9be149aae03cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamvideo.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamvideo.cs new file mode 100644 index 0000000..451a6c1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamvideo.cs @@ -0,0 +1,54 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + public static class SteamVideo { + /// + /// Get a URL suitable for streaming the given Video app ID's video + /// + public static void GetVideoURL(AppId_t unVideoAppID) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamVideo_GetVideoURL(CSteamAPIContext.GetSteamVideo(), unVideoAppID); + } + + /// + /// returns true if user is uploading a live broadcast + /// + public static bool IsBroadcasting(out int pnNumViewers) { + InteropHelp.TestIfAvailableClient(); + return NativeMethods.ISteamVideo_IsBroadcasting(CSteamAPIContext.GetSteamVideo(), out pnNumViewers); + } + + /// + /// Get the OPF Details for 360 Video Playback + /// + public static void GetOPFSettings(AppId_t unVideoAppID) { + InteropHelp.TestIfAvailableClient(); + NativeMethods.ISteamVideo_GetOPFSettings(CSteamAPIContext.GetSteamVideo(), unVideoAppID); + } + + public static bool GetOPFStringForApp(AppId_t unVideoAppID, out string pchBuffer, ref int pnBufferSize) { + InteropHelp.TestIfAvailableClient(); + IntPtr pchBuffer2 = Marshal.AllocHGlobal((int)pnBufferSize); + bool ret = NativeMethods.ISteamVideo_GetOPFStringForApp(CSteamAPIContext.GetSteamVideo(), unVideoAppID, pchBuffer2, ref pnBufferSize); + pchBuffer = ret ? InteropHelp.PtrToStringUTF8(pchBuffer2) : null; + Marshal.FreeHGlobal(pchBuffer2); + return ret; + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamvideo.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamvideo.cs.meta new file mode 100644 index 0000000..12e5f5a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamvideo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f702c2a8bafa974794196681323eccf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/com.rlabrecque.steamworks.net.asmdef b/Assets/com.rlabrecque.steamworks.net/Runtime/com.rlabrecque.steamworks.net.asmdef new file mode 100644 index 0000000..2692f32 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/com.rlabrecque.steamworks.net.asmdef @@ -0,0 +1,20 @@ +{ + "name": "com.rlabrecque.steamworks.net", + "rootNamespace": "", + "references": [], + "includePlatforms": [ + "Editor", + "LinuxStandalone64", + "macOSStandalone", + "WindowsStandalone32", + "WindowsStandalone64" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/com.rlabrecque.steamworks.net.asmdef.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/com.rlabrecque.steamworks.net.asmdef.meta new file mode 100644 index 0000000..0106b1d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/com.rlabrecque.steamworks.net.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 68bd7fdb68ef2684e982e8a9825b18a5 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types.meta new file mode 100644 index 0000000..d0eee01 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d7506b9f621a5348b763eb9c2bd92bc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes.meta new file mode 100644 index 0000000..0ebcf26 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48b4fdd7ddbfb9c47914ec93dea90b67 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/gameserveritem_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/gameserveritem_t.cs new file mode 100644 index 0000000..b9b2e40 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/gameserveritem_t.cs @@ -0,0 +1,106 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +using System.Text; + +namespace Steamworks { + //----------------------------------------------------------------------------- + // Purpose: Data describing a single server + //----------------------------------------------------------------------------- + [StructLayout(LayoutKind.Sequential, Size = 372, Pack = 4)] + [System.Serializable] + public class gameserveritem_t { + public string GetGameDir() { + return Encoding.UTF8.GetString(m_szGameDir, 0, System.Array.IndexOf(m_szGameDir, 0)); + } + + public void SetGameDir(string dir) { + m_szGameDir = Encoding.UTF8.GetBytes(dir + '\0'); + } + + public string GetMap() { + return Encoding.UTF8.GetString(m_szMap, 0, System.Array.IndexOf(m_szMap, 0)); + } + + public void SetMap(string map) { + m_szMap = Encoding.UTF8.GetBytes(map + '\0'); + } + + public string GetGameDescription() { + return Encoding.UTF8.GetString(m_szGameDescription, 0, System.Array.IndexOf(m_szGameDescription, 0)); + } + + public void SetGameDescription(string desc) { + m_szGameDescription = Encoding.UTF8.GetBytes(desc + '\0'); + } + + public string GetServerName() { + // Use the IP address as the name if nothing is set yet. + if (m_szServerName[0] == 0) + return m_NetAdr.GetConnectionAddressString(); + else + return Encoding.UTF8.GetString(m_szServerName, 0, System.Array.IndexOf(m_szServerName, 0)); + } + + public void SetServerName(string name) { + m_szServerName = Encoding.UTF8.GetBytes(name + '\0'); + } + + public string GetGameTags() { + return Encoding.UTF8.GetString(m_szGameTags, 0, System.Array.IndexOf(m_szGameTags, 0)); + } + + public void SetGameTags(string tags) { + m_szGameTags = Encoding.UTF8.GetBytes(tags + '\0'); + } + + public servernetadr_t m_NetAdr; ///< IP/Query Port/Connection Port for this server + public int m_nPing; ///< current ping time in milliseconds + [MarshalAs(UnmanagedType.I1)] + public bool m_bHadSuccessfulResponse; ///< server has responded successfully in the past + [MarshalAs(UnmanagedType.I1)] + public bool m_bDoNotRefresh; ///< server is marked as not responding and should no longer be refreshed + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerGameDir)] + private byte[] m_szGameDir; ///< current game directory + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerMapName)] + private byte[] m_szMap; ///< current map + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerGameDescription)] + private byte[] m_szGameDescription; ///< game description + public uint m_nAppID; ///< Steam App ID of this server + public int m_nPlayers; ///< total number of players currently on the server. INCLUDES BOTS!! + public int m_nMaxPlayers; ///< Maximum players that can join this server + public int m_nBotPlayers; ///< Number of bots (i.e simulated players) on this server + [MarshalAs(UnmanagedType.I1)] + public bool m_bPassword; ///< true if this server needs a password to join + [MarshalAs(UnmanagedType.I1)] + public bool m_bSecure; ///< Is this server protected by VAC + public uint m_ulTimeLastPlayed; ///< time (in unix time) when this server was last played on (for favorite/history servers) + public int m_nServerVersion; ///< server version as reported to Steam + + // Game server name + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerName)] + private byte[] m_szServerName; + + // the tags this server exposes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cbMaxGameServerTags)] + private byte[] m_szGameTags; + + // steamID of the game server - invalid if it's doesn't have one (old server, or not connected to Steam) + public CSteamID m_steamID; + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/gameserveritem_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/gameserveritem_t.cs.meta new file mode 100644 index 0000000..5723447 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/gameserveritem_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7cb77ebece51f6c4ca56e4fb79a2767a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/servernetadr_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/servernetadr_t.cs new file mode 100644 index 0000000..66f555d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/servernetadr_t.cs @@ -0,0 +1,116 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + // servernetadr_t is all the addressing info the serverbrowser needs to know about a game server, + // namely: its IP, its connection port, and its query port. + [System.Serializable] + public struct servernetadr_t { + private ushort m_usConnectionPort; // (in HOST byte order) + private ushort m_usQueryPort; + private uint m_unIP; + + public void Init(uint ip, ushort usQueryPort, ushort usConnectionPort) { + m_unIP = ip; + m_usQueryPort = usQueryPort; + m_usConnectionPort = usConnectionPort; + } + +#if NETADR_H + public netadr_t GetIPAndQueryPort() { + return netadr_t( m_unIP, m_usQueryPort ); + } +#endif + + // Access the query port. + public ushort GetQueryPort() { + return m_usQueryPort; + } + + public void SetQueryPort(ushort usPort) { + m_usQueryPort = usPort; + } + + // Access the connection port. + public ushort GetConnectionPort() { + return m_usConnectionPort; + } + + public void SetConnectionPort(ushort usPort) { + m_usConnectionPort = usPort; + } + + // Access the IP + public uint GetIP() { + return m_unIP; + } + + public void SetIP(uint unIP) { + m_unIP = unIP; + } + + // This gets the 'a.b.c.d:port' string with the connection port (instead of the query port). + public string GetConnectionAddressString() { + return ToString(m_unIP, m_usConnectionPort); + } + + public string GetQueryAddressString() { + return ToString(m_unIP, m_usQueryPort); + } + + public static string ToString(uint unIP, ushort usPort) { +#if VALVE_BIG_ENDIAN + return string.Format("{0}.{1}.{2}.{3}:{4}", unIP & 0xFFul, (unIP >> 8) & 0xFFul, (unIP >> 16) & 0xFFul, (unIP >> 24) & 0xFFul, usPort); +#else + return string.Format("{0}.{1}.{2}.{3}:{4}", (unIP >> 24) & 0xFFul, (unIP >> 16) & 0xFFul, (unIP >> 8) & 0xFFul, unIP & 0xFFul, usPort); +#endif + } + + public static bool operator <(servernetadr_t x, servernetadr_t y) { + return (x.m_unIP < y.m_unIP) || (x.m_unIP == y.m_unIP && x.m_usQueryPort < y.m_usQueryPort); + } + + public static bool operator >(servernetadr_t x, servernetadr_t y) { + return (x.m_unIP > y.m_unIP) || (x.m_unIP == y.m_unIP && x.m_usQueryPort > y.m_usQueryPort); + } + + public override bool Equals(object other) { + return other is servernetadr_t && this == (servernetadr_t)other; + } + + public override int GetHashCode() { + return m_unIP.GetHashCode() + m_usQueryPort.GetHashCode() + m_usConnectionPort.GetHashCode(); + } + + public static bool operator ==(servernetadr_t x, servernetadr_t y) { + return (x.m_unIP == y.m_unIP) && (x.m_usQueryPort == y.m_usQueryPort) && (x.m_usConnectionPort == y.m_usConnectionPort); + } + + public static bool operator !=(servernetadr_t x, servernetadr_t y) { + return !(x == y); + } + + public bool Equals(servernetadr_t other) { + return (m_unIP == other.m_unIP) && (m_usQueryPort == other.m_usQueryPort) && (m_usConnectionPort == other.m_usConnectionPort); + } + + public int CompareTo(servernetadr_t other) { + return m_unIP.CompareTo(other.m_unIP) + m_usQueryPort.CompareTo(other.m_usQueryPort) + m_usConnectionPort.CompareTo(other.m_usConnectionPort); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/servernetadr_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/servernetadr_t.cs.meta new file mode 100644 index 0000000..51d247f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/servernetadr_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 543f6ec65c2a352408c8e28d4f0b3cbc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient.meta new file mode 100644 index 0000000..ada6785 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 660090ac78ff49a4caa3154940c83333 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPIWarningMessageHook_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPIWarningMessageHook_t.cs new file mode 100644 index 0000000..832d1a2 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPIWarningMessageHook_t.cs @@ -0,0 +1,22 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Runtime.InteropServices.UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + public delegate void SteamAPIWarningMessageHook_t(int nSeverity, System.Text.StringBuilder pchDebugText); +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPIWarningMessageHook_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPIWarningMessageHook_t.cs.meta new file mode 100644 index 0000000..db40181 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPIWarningMessageHook_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c98e0ee75c73f444abb8ace148379c6e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs new file mode 100644 index 0000000..a7ed915 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs @@ -0,0 +1,22 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Runtime.InteropServices.UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.StdCall)] // TODO: This is probably wrong, will likely crash on some platform. + public delegate void SteamAPI_CheckCallbackRegistered_t(int iCallbackNum); +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs.meta new file mode 100644 index 0000000..3739991 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 89d1afa2baf7a77459997121dfb8e872 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic.meta new file mode 100644 index 0000000..e7908e1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7a1f79686d425ae4e9380256e58f4b56 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CGameID.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CGameID.cs new file mode 100644 index 0000000..689a0e2 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CGameID.cs @@ -0,0 +1,154 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct CGameID : System.IEquatable, System.IComparable { + public ulong m_GameID; + + public enum EGameIDType { + k_EGameIDTypeApp = 0, + k_EGameIDTypeGameMod = 1, + k_EGameIDTypeShortcut = 2, + k_EGameIDTypeP2P = 3, + }; + + public CGameID(ulong GameID) { + m_GameID = GameID; + } + + public CGameID(AppId_t nAppID) { + m_GameID = 0; + SetAppID(nAppID); + } + + public CGameID(AppId_t nAppID, uint nModID) { + m_GameID = 0; + SetAppID(nAppID); + SetType(EGameIDType.k_EGameIDTypeGameMod); + SetModID(nModID); + } + + public bool IsSteamApp() { + return Type() == EGameIDType.k_EGameIDTypeApp; + } + + public bool IsMod() { + return Type() == EGameIDType.k_EGameIDTypeGameMod; + } + + public bool IsShortcut() { + return Type() == EGameIDType.k_EGameIDTypeShortcut; + } + + public bool IsP2PFile() { + return Type() == EGameIDType.k_EGameIDTypeP2P; + } + + public AppId_t AppID() { + return new AppId_t((uint)(m_GameID & 0xFFFFFFul)); + } + + public EGameIDType Type() { + return (EGameIDType)((m_GameID >> 24) & 0xFFul); + } + + public uint ModID() { + return (uint)((m_GameID >> 32) & 0xFFFFFFFFul); + } + + public bool IsValid() { + // Each type has it's own invalid fixed point: + switch (Type()) { + case EGameIDType.k_EGameIDTypeApp: + return AppID() != AppId_t.Invalid; + + case EGameIDType.k_EGameIDTypeGameMod: + return AppID() != AppId_t.Invalid && (ModID() & 0x80000000) != 0; + + case EGameIDType.k_EGameIDTypeShortcut: + return (ModID() & 0x80000000) != 0; + + case EGameIDType.k_EGameIDTypeP2P: + return AppID() == AppId_t.Invalid && (ModID() & 0x80000000) != 0; + + default: + return false; + } + } + + public void Reset() { + m_GameID = 0; + } + + public void Set(ulong GameID) { + m_GameID = GameID; + } + + #region Private Setters for internal use + private void SetAppID(AppId_t other) { + m_GameID = (m_GameID & ~(0xFFFFFFul << (ushort)0)) | (((ulong)(other) & 0xFFFFFFul) << (ushort)0); + } + + private void SetType(EGameIDType other) { + m_GameID = (m_GameID & ~(0xFFul << (ushort)24)) | (((ulong)(other) & 0xFFul) << (ushort)24); + } + + private void SetModID(uint other) { + m_GameID = (m_GameID & ~(0xFFFFFFFFul << (ushort)32)) | (((ulong)(other) & 0xFFFFFFFFul) << (ushort)32); + } + #endregion + + #region Overrides + public override string ToString() { + return m_GameID.ToString(); + } + + public override bool Equals(object other) { + return other is CGameID && this == (CGameID)other; + } + + public override int GetHashCode() { + return m_GameID.GetHashCode(); + } + + public static bool operator ==(CGameID x, CGameID y) { + return x.m_GameID == y.m_GameID; + } + + public static bool operator !=(CGameID x, CGameID y) { + return !(x == y); + } + + public static explicit operator CGameID(ulong value) { + return new CGameID(value); + } + public static explicit operator ulong(CGameID that) { + return that.m_GameID; + } + + public bool Equals(CGameID other) { + return m_GameID == other.m_GameID; + } + + public int CompareTo(CGameID other) { + return m_GameID.CompareTo(other.m_GameID); + } + #endregion + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CGameID.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CGameID.cs.meta new file mode 100644 index 0000000..280ba90 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CGameID.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e32604c61cbc4a843873d96c61d7c673 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CSteamID.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CSteamID.cs new file mode 100644 index 0000000..3e4a1b1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CSteamID.cs @@ -0,0 +1,269 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 4)] + public struct CSteamID : System.IEquatable, System.IComparable { + public static readonly CSteamID Nil = new CSteamID(); + public static readonly CSteamID OutofDateGS = new CSteamID(new AccountID_t(0), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid); + public static readonly CSteamID LanModeGS = new CSteamID(new AccountID_t(0), 0, EUniverse.k_EUniversePublic, EAccountType.k_EAccountTypeInvalid); + public static readonly CSteamID NotInitYetGS = new CSteamID(new AccountID_t(1), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid); + public static readonly CSteamID NonSteamGS = new CSteamID(new AccountID_t(2), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid); + public ulong m_SteamID; + + public CSteamID(AccountID_t unAccountID, EUniverse eUniverse, EAccountType eAccountType) { + m_SteamID = 0; + Set(unAccountID, eUniverse, eAccountType); + } + + public CSteamID(AccountID_t unAccountID, uint unAccountInstance, EUniverse eUniverse, EAccountType eAccountType) { + m_SteamID = 0; +#if _SERVER && Assert + Assert( ! ( ( EAccountType.k_EAccountTypeIndividual == eAccountType ) && ( unAccountInstance > k_unSteamUserWebInstance ) ) ); // enforce that for individual accounts, instance is always 1 +#endif // _SERVER + InstancedSet(unAccountID, unAccountInstance, eUniverse, eAccountType); + } + + public CSteamID(ulong ulSteamID) { + m_SteamID = ulSteamID; + } + + public void Set(AccountID_t unAccountID, EUniverse eUniverse, EAccountType eAccountType) { + SetAccountID(unAccountID); + SetEUniverse(eUniverse); + SetEAccountType(eAccountType); + + if (eAccountType == EAccountType.k_EAccountTypeClan || eAccountType == EAccountType.k_EAccountTypeGameServer) { + SetAccountInstance(0); + } + else { + SetAccountInstance(Constants.k_unSteamUserDefaultInstance); + } + } + + public void InstancedSet(AccountID_t unAccountID, uint unInstance, EUniverse eUniverse, EAccountType eAccountType) { + SetAccountID(unAccountID); + SetEUniverse(eUniverse); + SetEAccountType(eAccountType); + SetAccountInstance(unInstance); + } + + public void Clear() { + m_SteamID = 0; + } + + public void CreateBlankAnonLogon(EUniverse eUniverse) { + SetAccountID(new AccountID_t(0)); + SetEUniverse(eUniverse); + SetEAccountType(EAccountType.k_EAccountTypeAnonGameServer); + SetAccountInstance(0); + } + + public void CreateBlankAnonUserLogon(EUniverse eUniverse) { + SetAccountID(new AccountID_t(0)); + SetEUniverse(eUniverse); + SetEAccountType(EAccountType.k_EAccountTypeAnonUser); + SetAccountInstance(0); + } + + //----------------------------------------------------------------------------- + // Purpose: Is this an anonymous game server login that will be filled in? + //----------------------------------------------------------------------------- + public bool BBlankAnonAccount() { + return GetAccountID() == new AccountID_t(0) && BAnonAccount() && GetUnAccountInstance() == 0; + } + + //----------------------------------------------------------------------------- + // Purpose: Is this a game server account id? (Either persistent or anonymous) + //----------------------------------------------------------------------------- + public bool BGameServerAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeGameServer || GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer; + } + + //----------------------------------------------------------------------------- + // Purpose: Is this a persistent (not anonymous) game server account id? + //----------------------------------------------------------------------------- + public bool BPersistentGameServerAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeGameServer; + } + + //----------------------------------------------------------------------------- + // Purpose: Is this an anonymous game server account id? + //----------------------------------------------------------------------------- + public bool BAnonGameServerAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer; + } + + //----------------------------------------------------------------------------- + // Purpose: Is this a content server account id? + //----------------------------------------------------------------------------- + public bool BContentServerAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeContentServer; + } + + + //----------------------------------------------------------------------------- + // Purpose: Is this a clan account id? + //----------------------------------------------------------------------------- + public bool BClanAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeClan; + } + + + //----------------------------------------------------------------------------- + // Purpose: Is this a chat account id? + //----------------------------------------------------------------------------- + public bool BChatAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeChat; + } + + //----------------------------------------------------------------------------- + // Purpose: Is this a chat account id? + //----------------------------------------------------------------------------- + public bool IsLobby() { + return (GetEAccountType() == EAccountType.k_EAccountTypeChat) + && (GetUnAccountInstance() & (int)EChatSteamIDInstanceFlags.k_EChatInstanceFlagLobby) != 0; + } + + + //----------------------------------------------------------------------------- + // Purpose: Is this an individual user account id? + //----------------------------------------------------------------------------- + public bool BIndividualAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeIndividual || GetEAccountType() == EAccountType.k_EAccountTypeConsoleUser; + } + + + //----------------------------------------------------------------------------- + // Purpose: Is this an anonymous account? + //----------------------------------------------------------------------------- + public bool BAnonAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeAnonUser || GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer; + } + + //----------------------------------------------------------------------------- + // Purpose: Is this an anonymous user account? ( used to create an account or reset a password ) + //----------------------------------------------------------------------------- + public bool BAnonUserAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeAnonUser; + } + + //----------------------------------------------------------------------------- + // Purpose: Is this a faked up Steam ID for a PSN friend account? + //----------------------------------------------------------------------------- + public bool BConsoleUserAccount() { + return GetEAccountType() == EAccountType.k_EAccountTypeConsoleUser; + } + + public void SetAccountID(AccountID_t other) { + m_SteamID = (m_SteamID & ~(0xFFFFFFFFul << (ushort)0)) | (((ulong)(other) & 0xFFFFFFFFul) << (ushort)0); + } + + public void SetAccountInstance(uint other) { + m_SteamID = (m_SteamID & ~(0xFFFFFul << (ushort)32)) | (((ulong)(other) & 0xFFFFFul) << (ushort)32); + } + + // This is a non standard/custom function not found in C++ Steamworks + public void SetEAccountType(EAccountType other) { + m_SteamID = (m_SteamID & ~(0xFul << (ushort)52)) | (((ulong)(other) & 0xFul) << (ushort)52); + } + + public void SetEUniverse(EUniverse other) { + m_SteamID = (m_SteamID & ~(0xFFul << (ushort)56)) | (((ulong)(other) & 0xFFul) << (ushort)56); + } + + public AccountID_t GetAccountID() { + return new AccountID_t((uint)(m_SteamID & 0xFFFFFFFFul)); + } + + public uint GetUnAccountInstance() { + return (uint)((m_SteamID >> 32) & 0xFFFFFul); + } + + public EAccountType GetEAccountType() { + return (EAccountType)((m_SteamID >> 52) & 0xFul); + } + + public EUniverse GetEUniverse() { + return (EUniverse)((m_SteamID >> 56) & 0xFFul); + } + + public bool IsValid() { + if (GetEAccountType() <= EAccountType.k_EAccountTypeInvalid || GetEAccountType() >= EAccountType.k_EAccountTypeMax) + return false; + + if (GetEUniverse() <= EUniverse.k_EUniverseInvalid || GetEUniverse() >= EUniverse.k_EUniverseMax) + return false; + + if (GetEAccountType() == EAccountType.k_EAccountTypeIndividual) { + if (GetAccountID() == new AccountID_t(0) || GetUnAccountInstance() > Constants.k_unSteamUserDefaultInstance) + return false; + } + + if (GetEAccountType() == EAccountType.k_EAccountTypeClan) { + if (GetAccountID() == new AccountID_t(0) || GetUnAccountInstance() != 0) + return false; + } + + if (GetEAccountType() == EAccountType.k_EAccountTypeGameServer) { + if (GetAccountID() == new AccountID_t(0)) + return false; + // Any limit on instances? We use them for local users and bots + } + return true; + } + + #region Overrides + public override string ToString() { + return m_SteamID.ToString(); + } + + public override bool Equals(object other) { + return other is CSteamID && this == (CSteamID)other; + } + + public override int GetHashCode() { + return m_SteamID.GetHashCode(); + } + + public static bool operator ==(CSteamID x, CSteamID y) { + return x.m_SteamID == y.m_SteamID; + } + + public static bool operator !=(CSteamID x, CSteamID y) { + return !(x == y); + } + + public static explicit operator CSteamID(ulong value) { + return new CSteamID(value); + } + public static explicit operator ulong(CSteamID that) { + return that.m_SteamID; + } + + public bool Equals(CSteamID other) { + return m_SteamID == other.m_SteamID; + } + + public int CompareTo(CSteamID other) { + return m_SteamID.CompareTo(other.m_SteamID); + } + #endregion + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CSteamID.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CSteamID.cs.meta new file mode 100644 index 0000000..385f77f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CSteamID.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ceefc77ec6409724c9c766ce839f8ef7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/HAuthTicket.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/HAuthTicket.cs new file mode 100644 index 0000000..f395589 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/HAuthTicket.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HAuthTicket : System.IEquatable, System.IComparable { + public static readonly HAuthTicket Invalid = new HAuthTicket(0); + public uint m_HAuthTicket; + + public HAuthTicket(uint value) { + m_HAuthTicket = value; + } + + public override string ToString() { + return m_HAuthTicket.ToString(); + } + + public override bool Equals(object other) { + return other is HAuthTicket && this == (HAuthTicket)other; + } + + public override int GetHashCode() { + return m_HAuthTicket.GetHashCode(); + } + + public static bool operator ==(HAuthTicket x, HAuthTicket y) { + return x.m_HAuthTicket == y.m_HAuthTicket; + } + + public static bool operator !=(HAuthTicket x, HAuthTicket y) { + return !(x == y); + } + + public static explicit operator HAuthTicket(uint value) { + return new HAuthTicket(value); + } + + public static explicit operator uint(HAuthTicket that) { + return that.m_HAuthTicket; + } + + public bool Equals(HAuthTicket other) { + return m_HAuthTicket == other.m_HAuthTicket; + } + + public int CompareTo(HAuthTicket other) { + return m_HAuthTicket.CompareTo(other.m_HAuthTicket); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/HAuthTicket.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/HAuthTicket.cs.meta new file mode 100644 index 0000000..5bbc927 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/HAuthTicket.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15820f55fe73cd74e9a944843ff7e2a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets.meta new file mode 100644 index 0000000..47b2408 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d5b00c2194afdc241825fc97bb39480b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramHostedAddress.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramHostedAddress.cs new file mode 100644 index 0000000..95bebfe --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramHostedAddress.cs @@ -0,0 +1,44 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// Network-routable identifier for a service. This is an intentionally + /// opaque byte blob. The relays know how to use this to forward it on + /// to the intended destination, but otherwise clients really should not + /// need to know what's inside. (Indeed, we don't really want them to + /// know, as it could reveal information useful to an attacker.) + [System.Serializable] + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamDatagramHostedAddress + { + // Size of data blob. + public int m_cbSize; + + // Opaque + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + public byte[] m_data; + + // Reset to empty state + public void Clear() + { + m_cbSize = 0; + m_data = new byte[128]; + } + } +} + +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramHostedAddress.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramHostedAddress.cs.meta new file mode 100644 index 0000000..dd30dfe --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramHostedAddress.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4b911b6f317d4b4dbc03443afe5f5b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramRelayAuthTicket.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramRelayAuthTicket.cs new file mode 100644 index 0000000..88b8885 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramRelayAuthTicket.cs @@ -0,0 +1,144 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// Network-routable identifier for a service. This is an intentionally + /// opaque byte blob. The relays know how to use this to forward it on + /// to the intended destination, but otherwise clients really should not + /// need to know what's inside. (Indeed, we don't really want them to + /// know, as it could reveal information useful to an attacker.) + [System.Serializable] + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + public struct SteamDatagramRelayAuthTicket + { + /// Identity of the gameserver we want to talk to. This is required. + SteamNetworkingIdentity m_identityGameserver; + + /// Identity of the person who was authorized. This is required. + SteamNetworkingIdentity m_identityAuthorizedClient; + + /// SteamID is authorized to send from a particular public IP. If this + /// is 0, then the sender is not restricted to a particular IP. + /// + /// Recommend to leave this set to zero. + uint m_unPublicIP; + + /// Time when the ticket expires. Recommended: take the current + /// time and add 6 hours, or maybe a bit longer if your gameplay + /// sessions are longer. + /// + /// NOTE: relays may reject tickets with expiry times excessively + /// far in the future, so contact us if you wish to use an expiry + /// longer than, say, 24 hours. + RTime32 m_rtimeTicketExpiry; + + /// Routing information where the gameserver is listening for + /// relayed traffic. You should fill this in when generating + /// a ticket. + /// + /// When generating tickets on your backend: + /// - In production: The gameserver knows the proper routing + /// information, so you need to call + /// ISteamNetworkingSockets::GetHostedDedicatedServerAddress + /// and send the info to your backend. + /// - In development, you will need to provide public IP + /// of the server using SteamDatagramServiceNetID::SetDevAddress. + /// Relays need to be able to send UDP + /// packets to this server. Since it's very likely that + /// your server is behind a firewall/NAT, make sure that + /// the address is the one that the outside world can use. + /// The traffic from the relays will be "unsolicited", so + /// stateful firewalls won't work -- you will probably have + /// to set up an explicit port forward. + /// On the client: + /// - this field will always be blank. + SteamDatagramHostedAddress m_routing; + + /// App ID this is for. This is required, and should be the + /// App ID the client is running. (Even if your gameserver + /// uses a different App ID.) + uint m_nAppID; + + /// Restrict this ticket to be used for a particular virtual port? + /// Set to -1 to allow any virtual port. + /// + /// This is useful as a security measure, and also so the client will + /// use the right ticket (which might have extra fields that are useful + /// for proper analytics), if the client happens to have more than one + /// appropriate ticket. + /// + /// Note: if a client has more that one acceptable ticket, they will + /// always use the one expiring the latest. + int m_nRestrictToVirtualPort; + + // + // Extra fields. + // + // These are collected for backend analytics. For example, you might + // send a MatchID so that all of the records for a particular match can + // be located. Or send a game mode field so that you can compare + // the network characteristics of different game modes. + // + // (At the time of this writing we don't have a way to expose the data + // we collect to partners, but we hope to in the future so that you can + // get visibility into network conditions.) + // + [StructLayout(LayoutKind.Sequential, Pack = Packsize.value)] + struct ExtraField + { + enum EType + { + k_EType_String, + k_EType_Int, // For most small integral values. Uses google protobuf sint64, so it's small on the wire. WARNING: In some places this value may be transmitted in JSON, in which case precision may be lost in backend analytics. Don't use this for an "identifier", use it for a scalar quantity. + k_EType_Fixed64, // 64 arbitrary bits. This value is treated as an "identifier". In places where JSON format is used, it will be serialized as a string. No aggregation / analytics can be performed on this value. + }; + EType m_eType; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] + byte[] m_szName; + + [StructLayout(LayoutKind.Explicit)] + struct OptionValue + { + [FieldOffset(0)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + byte[] m_szStringValue; + + [FieldOffset(0)] + long m_nIntValue; + + [FieldOffset(0)] + ulong m_nFixed64Value; + } + OptionValue m_val; + }; + + const int k_nMaxExtraFields = 16; + + int m_nExtraFields; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = k_nMaxExtraFields)] + ExtraField[] m_vecExtraFields; + + // Reset all fields + public void Clear() + { + } + } +} + +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramRelayAuthTicket.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramRelayAuthTicket.cs.meta new file mode 100644 index 0000000..c1464d4 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramRelayAuthTicket.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15e38ab651a746e43b5ed10db54a0d3e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends.meta new file mode 100644 index 0000000..589fe94 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2093c750a2e614a418d09290c2161965 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends/FriendsGroupID_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends/FriendsGroupID_t.cs new file mode 100644 index 0000000..b9b94f1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends/FriendsGroupID_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct FriendsGroupID_t : System.IEquatable, System.IComparable { + public static readonly FriendsGroupID_t Invalid = new FriendsGroupID_t(-1); + public short m_FriendsGroupID; + + public FriendsGroupID_t(short value) { + m_FriendsGroupID = value; + } + + public override string ToString() { + return m_FriendsGroupID.ToString(); + } + + public override bool Equals(object other) { + return other is FriendsGroupID_t && this == (FriendsGroupID_t)other; + } + + public override int GetHashCode() { + return m_FriendsGroupID.GetHashCode(); + } + + public static bool operator ==(FriendsGroupID_t x, FriendsGroupID_t y) { + return x.m_FriendsGroupID == y.m_FriendsGroupID; + } + + public static bool operator !=(FriendsGroupID_t x, FriendsGroupID_t y) { + return !(x == y); + } + + public static explicit operator FriendsGroupID_t(short value) { + return new FriendsGroupID_t(value); + } + + public static explicit operator short(FriendsGroupID_t that) { + return that.m_FriendsGroupID; + } + + public bool Equals(FriendsGroupID_t other) { + return m_FriendsGroupID == other.m_FriendsGroupID; + } + + public int CompareTo(FriendsGroupID_t other) { + return m_FriendsGroupID.CompareTo(other.m_FriendsGroupID); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends/FriendsGroupID_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends/FriendsGroupID_t.cs.meta new file mode 100644 index 0000000..c8f5d46 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends/FriendsGroupID_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90d54edccd5581d44816f5e28bfd8a79 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface.meta new file mode 100644 index 0000000..d539a87 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5a8b07e2178653546b35486633c13d9e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface/HHTMLBrowser.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface/HHTMLBrowser.cs new file mode 100644 index 0000000..a016a45 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface/HHTMLBrowser.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HHTMLBrowser : System.IEquatable, System.IComparable { + public static readonly HHTMLBrowser Invalid = new HHTMLBrowser(0); + public uint m_HHTMLBrowser; + + public HHTMLBrowser(uint value) { + m_HHTMLBrowser = value; + } + + public override string ToString() { + return m_HHTMLBrowser.ToString(); + } + + public override bool Equals(object other) { + return other is HHTMLBrowser && this == (HHTMLBrowser)other; + } + + public override int GetHashCode() { + return m_HHTMLBrowser.GetHashCode(); + } + + public static bool operator ==(HHTMLBrowser x, HHTMLBrowser y) { + return x.m_HHTMLBrowser == y.m_HHTMLBrowser; + } + + public static bool operator !=(HHTMLBrowser x, HHTMLBrowser y) { + return !(x == y); + } + + public static explicit operator HHTMLBrowser(uint value) { + return new HHTMLBrowser(value); + } + + public static explicit operator uint(HHTMLBrowser that) { + return that.m_HHTMLBrowser; + } + + public bool Equals(HHTMLBrowser other) { + return m_HHTMLBrowser == other.m_HHTMLBrowser; + } + + public int CompareTo(HHTMLBrowser other) { + return m_HHTMLBrowser.CompareTo(other.m_HHTMLBrowser); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface/HHTMLBrowser.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface/HHTMLBrowser.cs.meta new file mode 100644 index 0000000..8fac214 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface/HHTMLBrowser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 81d58fa9c521a8846974e9c906c53ca6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP.meta new file mode 100644 index 0000000..db16262 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 646c6e2e130c5324da7f64ee70e64deb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPCookieContainerHandle.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPCookieContainerHandle.cs new file mode 100644 index 0000000..34fa5af --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPCookieContainerHandle.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HTTPCookieContainerHandle : System.IEquatable, System.IComparable { + public static readonly HTTPCookieContainerHandle Invalid = new HTTPCookieContainerHandle(0); + public uint m_HTTPCookieContainerHandle; + + public HTTPCookieContainerHandle(uint value) { + m_HTTPCookieContainerHandle = value; + } + + public override string ToString() { + return m_HTTPCookieContainerHandle.ToString(); + } + + public override bool Equals(object other) { + return other is HTTPCookieContainerHandle && this == (HTTPCookieContainerHandle)other; + } + + public override int GetHashCode() { + return m_HTTPCookieContainerHandle.GetHashCode(); + } + + public static bool operator ==(HTTPCookieContainerHandle x, HTTPCookieContainerHandle y) { + return x.m_HTTPCookieContainerHandle == y.m_HTTPCookieContainerHandle; + } + + public static bool operator !=(HTTPCookieContainerHandle x, HTTPCookieContainerHandle y) { + return !(x == y); + } + + public static explicit operator HTTPCookieContainerHandle(uint value) { + return new HTTPCookieContainerHandle(value); + } + + public static explicit operator uint(HTTPCookieContainerHandle that) { + return that.m_HTTPCookieContainerHandle; + } + + public bool Equals(HTTPCookieContainerHandle other) { + return m_HTTPCookieContainerHandle == other.m_HTTPCookieContainerHandle; + } + + public int CompareTo(HTTPCookieContainerHandle other) { + return m_HTTPCookieContainerHandle.CompareTo(other.m_HTTPCookieContainerHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPCookieContainerHandle.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPCookieContainerHandle.cs.meta new file mode 100644 index 0000000..13252b7 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPCookieContainerHandle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46e53a176d1039a499132c5707543617 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPRequestHandle.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPRequestHandle.cs new file mode 100644 index 0000000..eddd6a8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPRequestHandle.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HTTPRequestHandle : System.IEquatable, System.IComparable { + public static readonly HTTPRequestHandle Invalid = new HTTPRequestHandle(0); + public uint m_HTTPRequestHandle; + + public HTTPRequestHandle(uint value) { + m_HTTPRequestHandle = value; + } + + public override string ToString() { + return m_HTTPRequestHandle.ToString(); + } + + public override bool Equals(object other) { + return other is HTTPRequestHandle && this == (HTTPRequestHandle)other; + } + + public override int GetHashCode() { + return m_HTTPRequestHandle.GetHashCode(); + } + + public static bool operator ==(HTTPRequestHandle x, HTTPRequestHandle y) { + return x.m_HTTPRequestHandle == y.m_HTTPRequestHandle; + } + + public static bool operator !=(HTTPRequestHandle x, HTTPRequestHandle y) { + return !(x == y); + } + + public static explicit operator HTTPRequestHandle(uint value) { + return new HTTPRequestHandle(value); + } + + public static explicit operator uint(HTTPRequestHandle that) { + return that.m_HTTPRequestHandle; + } + + public bool Equals(HTTPRequestHandle other) { + return m_HTTPRequestHandle == other.m_HTTPRequestHandle; + } + + public int CompareTo(HTTPRequestHandle other) { + return m_HTTPRequestHandle.CompareTo(other.m_HTTPRequestHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPRequestHandle.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPRequestHandle.cs.meta new file mode 100644 index 0000000..aa852ee --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPRequestHandle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1a1dd2d769e5494188be1ede500917b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput.meta new file mode 100644 index 0000000..1b9541b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 84e7f79a56edb674d8d20505cf8a3670 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputActionSetHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputActionSetHandle_t.cs new file mode 100644 index 0000000..c8836ed --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputActionSetHandle_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct InputActionSetHandle_t : System.IEquatable, System.IComparable { + public ulong m_InputActionSetHandle; + + public InputActionSetHandle_t(ulong value) { + m_InputActionSetHandle = value; + } + + public override string ToString() { + return m_InputActionSetHandle.ToString(); + } + + public override bool Equals(object other) { + return other is InputActionSetHandle_t && this == (InputActionSetHandle_t)other; + } + + public override int GetHashCode() { + return m_InputActionSetHandle.GetHashCode(); + } + + public static bool operator ==(InputActionSetHandle_t x, InputActionSetHandle_t y) { + return x.m_InputActionSetHandle == y.m_InputActionSetHandle; + } + + public static bool operator !=(InputActionSetHandle_t x, InputActionSetHandle_t y) { + return !(x == y); + } + + public static explicit operator InputActionSetHandle_t(ulong value) { + return new InputActionSetHandle_t(value); + } + + public static explicit operator ulong(InputActionSetHandle_t that) { + return that.m_InputActionSetHandle; + } + + public bool Equals(InputActionSetHandle_t other) { + return m_InputActionSetHandle == other.m_InputActionSetHandle; + } + + public int CompareTo(InputActionSetHandle_t other) { + return m_InputActionSetHandle.CompareTo(other.m_InputActionSetHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputActionSetHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputActionSetHandle_t.cs.meta new file mode 100644 index 0000000..78ca451 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputActionSetHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2933ebab378eea243a8bb0cd63811d37 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputAnalogActionHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputAnalogActionHandle_t.cs new file mode 100644 index 0000000..7b8148c --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputAnalogActionHandle_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct InputAnalogActionHandle_t : System.IEquatable, System.IComparable { + public ulong m_InputAnalogActionHandle; + + public InputAnalogActionHandle_t(ulong value) { + m_InputAnalogActionHandle = value; + } + + public override string ToString() { + return m_InputAnalogActionHandle.ToString(); + } + + public override bool Equals(object other) { + return other is InputAnalogActionHandle_t && this == (InputAnalogActionHandle_t)other; + } + + public override int GetHashCode() { + return m_InputAnalogActionHandle.GetHashCode(); + } + + public static bool operator ==(InputAnalogActionHandle_t x, InputAnalogActionHandle_t y) { + return x.m_InputAnalogActionHandle == y.m_InputAnalogActionHandle; + } + + public static bool operator !=(InputAnalogActionHandle_t x, InputAnalogActionHandle_t y) { + return !(x == y); + } + + public static explicit operator InputAnalogActionHandle_t(ulong value) { + return new InputAnalogActionHandle_t(value); + } + + public static explicit operator ulong(InputAnalogActionHandle_t that) { + return that.m_InputAnalogActionHandle; + } + + public bool Equals(InputAnalogActionHandle_t other) { + return m_InputAnalogActionHandle == other.m_InputAnalogActionHandle; + } + + public int CompareTo(InputAnalogActionHandle_t other) { + return m_InputAnalogActionHandle.CompareTo(other.m_InputAnalogActionHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputAnalogActionHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputAnalogActionHandle_t.cs.meta new file mode 100644 index 0000000..f9dd523 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputAnalogActionHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f878bf26706ae2849a17a61a5b31a863 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputDigitalActionHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputDigitalActionHandle_t.cs new file mode 100644 index 0000000..28eb630 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputDigitalActionHandle_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct InputDigitalActionHandle_t : System.IEquatable, System.IComparable { + public ulong m_InputDigitalActionHandle; + + public InputDigitalActionHandle_t(ulong value) { + m_InputDigitalActionHandle = value; + } + + public override string ToString() { + return m_InputDigitalActionHandle.ToString(); + } + + public override bool Equals(object other) { + return other is InputDigitalActionHandle_t && this == (InputDigitalActionHandle_t)other; + } + + public override int GetHashCode() { + return m_InputDigitalActionHandle.GetHashCode(); + } + + public static bool operator ==(InputDigitalActionHandle_t x, InputDigitalActionHandle_t y) { + return x.m_InputDigitalActionHandle == y.m_InputDigitalActionHandle; + } + + public static bool operator !=(InputDigitalActionHandle_t x, InputDigitalActionHandle_t y) { + return !(x == y); + } + + public static explicit operator InputDigitalActionHandle_t(ulong value) { + return new InputDigitalActionHandle_t(value); + } + + public static explicit operator ulong(InputDigitalActionHandle_t that) { + return that.m_InputDigitalActionHandle; + } + + public bool Equals(InputDigitalActionHandle_t other) { + return m_InputDigitalActionHandle == other.m_InputDigitalActionHandle; + } + + public int CompareTo(InputDigitalActionHandle_t other) { + return m_InputDigitalActionHandle.CompareTo(other.m_InputDigitalActionHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputDigitalActionHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputDigitalActionHandle_t.cs.meta new file mode 100644 index 0000000..58a317d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputDigitalActionHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b7e0225fbabbd2443914046575983874 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputHandle_t.cs new file mode 100644 index 0000000..c686634 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputHandle_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct InputHandle_t : System.IEquatable, System.IComparable { + public ulong m_InputHandle; + + public InputHandle_t(ulong value) { + m_InputHandle = value; + } + + public override string ToString() { + return m_InputHandle.ToString(); + } + + public override bool Equals(object other) { + return other is InputHandle_t && this == (InputHandle_t)other; + } + + public override int GetHashCode() { + return m_InputHandle.GetHashCode(); + } + + public static bool operator ==(InputHandle_t x, InputHandle_t y) { + return x.m_InputHandle == y.m_InputHandle; + } + + public static bool operator !=(InputHandle_t x, InputHandle_t y) { + return !(x == y); + } + + public static explicit operator InputHandle_t(ulong value) { + return new InputHandle_t(value); + } + + public static explicit operator ulong(InputHandle_t that) { + return that.m_InputHandle; + } + + public bool Equals(InputHandle_t other) { + return m_InputHandle == other.m_InputHandle; + } + + public int CompareTo(InputHandle_t other) { + return m_InputHandle.CompareTo(other.m_InputHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputHandle_t.cs.meta new file mode 100644 index 0000000..b4a0c51 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9efdfe120ed0c24db8d9d397543e583 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEventCallbackPointer.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEventCallbackPointer.cs new file mode 100644 index 0000000..78f3c7b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEventCallbackPointer.cs @@ -0,0 +1,22 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Runtime.InteropServices.UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + public delegate void SteamInputActionEventCallbackPointer(IntPtr /* SteamInputActionEvent_t* */ SteamInputActionEvent); +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEventCallbackPointer.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEventCallbackPointer.cs.meta new file mode 100644 index 0000000..6415ad7 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEventCallbackPointer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40f4d6fda0f15ff47a9866d0afa2be32 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEvent_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEvent_t.cs new file mode 100644 index 0000000..ceeaf31 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEvent_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + //----------------------------------------------------------------------------- + // Purpose: when callbacks are enabled this fires each time a controller action + // state changes + //----------------------------------------------------------------------------- + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct SteamInputActionEvent_t + { + public InputHandle_t controllerHandle; + + public ESteamInputActionEventType eEventType; + + /// Option value + public OptionValue m_val; + + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct AnalogAction_t + { + public InputAnalogActionHandle_t actionHandle; + + public InputAnalogActionData_t analogActionData; + } + + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct DigitalAction_t + { + public InputDigitalActionHandle_t actionHandle; + + public InputDigitalActionData_t digitalActionData; + } + + [System.Serializable] + [StructLayout(LayoutKind.Explicit)] + public struct OptionValue + { + [FieldOffset(0)] + public AnalogAction_t analogAction; + + [FieldOffset(0)] + public DigitalAction_t digitalAction; + } + } +} + +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEvent_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEvent_t.cs.meta new file mode 100644 index 0000000..43f2d64 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEvent_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 31fd8b9eec8549a4f94d7059185ef204 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory.meta new file mode 100644 index 0000000..e224e9d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 09b34f6991630564fa297d7142bb3be4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryResult_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryResult_t.cs new file mode 100644 index 0000000..308a8a9 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryResult_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamInventoryResult_t : System.IEquatable, System.IComparable { + public static readonly SteamInventoryResult_t Invalid = new SteamInventoryResult_t(-1); + public int m_SteamInventoryResult; + + public SteamInventoryResult_t(int value) { + m_SteamInventoryResult = value; + } + + public override string ToString() { + return m_SteamInventoryResult.ToString(); + } + + public override bool Equals(object other) { + return other is SteamInventoryResult_t && this == (SteamInventoryResult_t)other; + } + + public override int GetHashCode() { + return m_SteamInventoryResult.GetHashCode(); + } + + public static bool operator ==(SteamInventoryResult_t x, SteamInventoryResult_t y) { + return x.m_SteamInventoryResult == y.m_SteamInventoryResult; + } + + public static bool operator !=(SteamInventoryResult_t x, SteamInventoryResult_t y) { + return !(x == y); + } + + public static explicit operator SteamInventoryResult_t(int value) { + return new SteamInventoryResult_t(value); + } + + public static explicit operator int(SteamInventoryResult_t that) { + return that.m_SteamInventoryResult; + } + + public bool Equals(SteamInventoryResult_t other) { + return m_SteamInventoryResult == other.m_SteamInventoryResult; + } + + public int CompareTo(SteamInventoryResult_t other) { + return m_SteamInventoryResult.CompareTo(other.m_SteamInventoryResult); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryResult_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryResult_t.cs.meta new file mode 100644 index 0000000..afa527e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryResult_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3655fc26cc26d1247913e462173de930 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryUpdateHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryUpdateHandle_t.cs new file mode 100644 index 0000000..25b5719 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryUpdateHandle_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamInventoryUpdateHandle_t : System.IEquatable, System.IComparable { + public static readonly SteamInventoryUpdateHandle_t Invalid = new SteamInventoryUpdateHandle_t(0xffffffffffffffff); + public ulong m_SteamInventoryUpdateHandle; + + public SteamInventoryUpdateHandle_t(ulong value) { + m_SteamInventoryUpdateHandle = value; + } + + public override string ToString() { + return m_SteamInventoryUpdateHandle.ToString(); + } + + public override bool Equals(object other) { + return other is SteamInventoryUpdateHandle_t && this == (SteamInventoryUpdateHandle_t)other; + } + + public override int GetHashCode() { + return m_SteamInventoryUpdateHandle.GetHashCode(); + } + + public static bool operator ==(SteamInventoryUpdateHandle_t x, SteamInventoryUpdateHandle_t y) { + return x.m_SteamInventoryUpdateHandle == y.m_SteamInventoryUpdateHandle; + } + + public static bool operator !=(SteamInventoryUpdateHandle_t x, SteamInventoryUpdateHandle_t y) { + return !(x == y); + } + + public static explicit operator SteamInventoryUpdateHandle_t(ulong value) { + return new SteamInventoryUpdateHandle_t(value); + } + + public static explicit operator ulong(SteamInventoryUpdateHandle_t that) { + return that.m_SteamInventoryUpdateHandle; + } + + public bool Equals(SteamInventoryUpdateHandle_t other) { + return m_SteamInventoryUpdateHandle == other.m_SteamInventoryUpdateHandle; + } + + public int CompareTo(SteamInventoryUpdateHandle_t other) { + return m_SteamInventoryUpdateHandle.CompareTo(other.m_SteamInventoryUpdateHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryUpdateHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryUpdateHandle_t.cs.meta new file mode 100644 index 0000000..245c45d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryUpdateHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb6aaeded4c5b154a9addb247ec4b530 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemDef_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemDef_t.cs new file mode 100644 index 0000000..974c2fc --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemDef_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamItemDef_t : System.IEquatable, System.IComparable { + public int m_SteamItemDef; + + public SteamItemDef_t(int value) { + m_SteamItemDef = value; + } + + public override string ToString() { + return m_SteamItemDef.ToString(); + } + + public override bool Equals(object other) { + return other is SteamItemDef_t && this == (SteamItemDef_t)other; + } + + public override int GetHashCode() { + return m_SteamItemDef.GetHashCode(); + } + + public static bool operator ==(SteamItemDef_t x, SteamItemDef_t y) { + return x.m_SteamItemDef == y.m_SteamItemDef; + } + + public static bool operator !=(SteamItemDef_t x, SteamItemDef_t y) { + return !(x == y); + } + + public static explicit operator SteamItemDef_t(int value) { + return new SteamItemDef_t(value); + } + + public static explicit operator int(SteamItemDef_t that) { + return that.m_SteamItemDef; + } + + public bool Equals(SteamItemDef_t other) { + return m_SteamItemDef == other.m_SteamItemDef; + } + + public int CompareTo(SteamItemDef_t other) { + return m_SteamItemDef.CompareTo(other.m_SteamItemDef); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemDef_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemDef_t.cs.meta new file mode 100644 index 0000000..4302da6 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemDef_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cbb744003026c674aa18c48cedffb1d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemInstanceID_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemInstanceID_t.cs new file mode 100644 index 0000000..339d892 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemInstanceID_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamItemInstanceID_t : System.IEquatable, System.IComparable { + public static readonly SteamItemInstanceID_t Invalid = new SteamItemInstanceID_t(0xFFFFFFFFFFFFFFFF); + public ulong m_SteamItemInstanceID; + + public SteamItemInstanceID_t(ulong value) { + m_SteamItemInstanceID = value; + } + + public override string ToString() { + return m_SteamItemInstanceID.ToString(); + } + + public override bool Equals(object other) { + return other is SteamItemInstanceID_t && this == (SteamItemInstanceID_t)other; + } + + public override int GetHashCode() { + return m_SteamItemInstanceID.GetHashCode(); + } + + public static bool operator ==(SteamItemInstanceID_t x, SteamItemInstanceID_t y) { + return x.m_SteamItemInstanceID == y.m_SteamItemInstanceID; + } + + public static bool operator !=(SteamItemInstanceID_t x, SteamItemInstanceID_t y) { + return !(x == y); + } + + public static explicit operator SteamItemInstanceID_t(ulong value) { + return new SteamItemInstanceID_t(value); + } + + public static explicit operator ulong(SteamItemInstanceID_t that) { + return that.m_SteamItemInstanceID; + } + + public bool Equals(SteamItemInstanceID_t other) { + return m_SteamItemInstanceID == other.m_SteamItemInstanceID; + } + + public int CompareTo(SteamItemInstanceID_t other) { + return m_SteamItemInstanceID.CompareTo(other.m_SteamItemInstanceID); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemInstanceID_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemInstanceID_t.cs.meta new file mode 100644 index 0000000..238071c --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemInstanceID_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 342c072be17625543a7335f6657a1d6a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking.meta new file mode 100644 index 0000000..0bca0dd --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f7461f6b90d23648a087ee81fe7639b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerListRequest.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerListRequest.cs new file mode 100644 index 0000000..60bfa9e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerListRequest.cs @@ -0,0 +1,61 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HServerListRequest : System.IEquatable { + public static readonly HServerListRequest Invalid = new HServerListRequest(System.IntPtr.Zero); + public System.IntPtr m_HServerListRequest; + + public HServerListRequest(System.IntPtr value) { + m_HServerListRequest = value; + } + + public override string ToString() { + return m_HServerListRequest.ToString(); + } + + public override bool Equals(object other) { + return other is HServerListRequest && this == (HServerListRequest)other; + } + + public override int GetHashCode() { + return m_HServerListRequest.GetHashCode(); + } + + public static bool operator ==(HServerListRequest x, HServerListRequest y) { + return x.m_HServerListRequest == y.m_HServerListRequest; + } + + public static bool operator !=(HServerListRequest x, HServerListRequest y) { + return !(x == y); + } + + public static explicit operator HServerListRequest(System.IntPtr value) { + return new HServerListRequest(value); + } + + public static explicit operator System.IntPtr(HServerListRequest that) { + return that.m_HServerListRequest; + } + + public bool Equals(HServerListRequest other) { + return m_HServerListRequest == other.m_HServerListRequest; + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerListRequest.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerListRequest.cs.meta new file mode 100644 index 0000000..b4bdc80 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerListRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fcc822173185aef4bb50a5a5713a3d5e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerQuery.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerQuery.cs new file mode 100644 index 0000000..6d92d23 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerQuery.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HServerQuery : System.IEquatable, System.IComparable { + public static readonly HServerQuery Invalid = new HServerQuery(-1); + public int m_HServerQuery; + + public HServerQuery(int value) { + m_HServerQuery = value; + } + + public override string ToString() { + return m_HServerQuery.ToString(); + } + + public override bool Equals(object other) { + return other is HServerQuery && this == (HServerQuery)other; + } + + public override int GetHashCode() { + return m_HServerQuery.GetHashCode(); + } + + public static bool operator ==(HServerQuery x, HServerQuery y) { + return x.m_HServerQuery == y.m_HServerQuery; + } + + public static bool operator !=(HServerQuery x, HServerQuery y) { + return !(x == y); + } + + public static explicit operator HServerQuery(int value) { + return new HServerQuery(value); + } + + public static explicit operator int(HServerQuery that) { + return that.m_HServerQuery; + } + + public bool Equals(HServerQuery other) { + return m_HServerQuery == other.m_HServerQuery; + } + + public int CompareTo(HServerQuery other) { + return m_HServerQuery.CompareTo(other.m_HServerQuery); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerQuery.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerQuery.cs.meta new file mode 100644 index 0000000..0d03768 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerQuery.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b3ebfd1441df2ab43b6ff570a5434825 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking.meta new file mode 100644 index 0000000..4f60e36 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5dac59af1c5f6e84e80775c18fbe1a39 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetListenSocket_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetListenSocket_t.cs new file mode 100644 index 0000000..13d9668 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetListenSocket_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SNetListenSocket_t : System.IEquatable, System.IComparable { + public uint m_SNetListenSocket; + + public SNetListenSocket_t(uint value) { + m_SNetListenSocket = value; + } + + public override string ToString() { + return m_SNetListenSocket.ToString(); + } + + public override bool Equals(object other) { + return other is SNetListenSocket_t && this == (SNetListenSocket_t)other; + } + + public override int GetHashCode() { + return m_SNetListenSocket.GetHashCode(); + } + + public static bool operator ==(SNetListenSocket_t x, SNetListenSocket_t y) { + return x.m_SNetListenSocket == y.m_SNetListenSocket; + } + + public static bool operator !=(SNetListenSocket_t x, SNetListenSocket_t y) { + return !(x == y); + } + + public static explicit operator SNetListenSocket_t(uint value) { + return new SNetListenSocket_t(value); + } + + public static explicit operator uint(SNetListenSocket_t that) { + return that.m_SNetListenSocket; + } + + public bool Equals(SNetListenSocket_t other) { + return m_SNetListenSocket == other.m_SNetListenSocket; + } + + public int CompareTo(SNetListenSocket_t other) { + return m_SNetListenSocket.CompareTo(other.m_SNetListenSocket); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetListenSocket_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetListenSocket_t.cs.meta new file mode 100644 index 0000000..761c032 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetListenSocket_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 64b4f5fdd688b0f44a78b8f79471aaa7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetSocket_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetSocket_t.cs new file mode 100644 index 0000000..52f6ac8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetSocket_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SNetSocket_t : System.IEquatable, System.IComparable { + public uint m_SNetSocket; + + public SNetSocket_t(uint value) { + m_SNetSocket = value; + } + + public override string ToString() { + return m_SNetSocket.ToString(); + } + + public override bool Equals(object other) { + return other is SNetSocket_t && this == (SNetSocket_t)other; + } + + public override int GetHashCode() { + return m_SNetSocket.GetHashCode(); + } + + public static bool operator ==(SNetSocket_t x, SNetSocket_t y) { + return x.m_SNetSocket == y.m_SNetSocket; + } + + public static bool operator !=(SNetSocket_t x, SNetSocket_t y) { + return !(x == y); + } + + public static explicit operator SNetSocket_t(uint value) { + return new SNetSocket_t(value); + } + + public static explicit operator uint(SNetSocket_t that) { + return that.m_SNetSocket; + } + + public bool Equals(SNetSocket_t other) { + return m_SNetSocket == other.m_SNetSocket; + } + + public int CompareTo(SNetSocket_t other) { + return m_SNetSocket.CompareTo(other.m_SNetSocket); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetSocket_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetSocket_t.cs.meta new file mode 100644 index 0000000..94493ec --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetSocket_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 513e29c43cea6fe43bae1ca068e814fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets.meta new file mode 100644 index 0000000..660e11a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 37be22eb1636ffe42880021313a27edd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingConnectionSignaling.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingConnectionSignaling.cs new file mode 100644 index 0000000..4dafa4d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingConnectionSignaling.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// Interface used to send signaling messages for a particular connection. + /// + /// - For connections initiated locally, you will construct it and pass + /// it to ISteamNetworkingSockets::ConnectP2PCustomSignaling. + /// - For connections initiated remotely and "accepted" locally, you + /// will return it from ISteamNetworkingSignalingRecvContext::OnConnectRequest + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct ISteamNetworkingConnectionSignaling + { + /// Called to send a rendezvous message to the remote peer. This may be called + /// from any thread, at any time, so you need to be thread-safe! Don't take + /// any locks that might hold while calling into SteamNetworkingSockets functions, + /// because this could lead to deadlocks. + /// + /// Note that when initiating a connection, we may not know the identity + /// of the peer, if you did not specify it in ConnectP2PCustomSignaling. + /// + /// Return true if a best-effort attempt was made to deliver the message. + /// If you return false, it is assumed that the situation is fatal; + /// the connection will be closed, and Release() will be called + /// eventually. + /// + /// Signaling objects will not be shared between connections. + /// You can assume that the same value of hConn will be used + /// every time. + public bool SendSignal(HSteamNetConnection hConn, ref SteamNetConnectionInfo_t info, IntPtr pMsg, int cbMsg) { + return NativeMethods.SteamAPI_ISteamNetworkingConnectionSignaling_SendSignal(ref this, hConn, ref info, pMsg, cbMsg); + } + + /// Called when the connection no longer needs to send signals. + /// Note that this happens eventually (but not immediately) after + /// the connection is closed. Signals may need to be sent for a brief + /// time after the connection is closed, to clean up the connection. + /// + /// If you do not need to save any additional per-connection information + /// and can handle SendSignal() using only the arguments supplied, you do + /// not need to actually create different objects per connection. In that + /// case, it is valid for all connections to use the same global object, and + /// for this function to do nothing. + public void Release() { + NativeMethods.SteamAPI_ISteamNetworkingConnectionSignaling_Release(ref this); + } + } +} + +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingConnectionSignaling.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingConnectionSignaling.cs.meta new file mode 100644 index 0000000..5d3e5af --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingConnectionSignaling.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0cfb93a120f656a43b7e5969811789e8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingSignalingRecvContext.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingSignalingRecvContext.cs new file mode 100644 index 0000000..18511a0 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingSignalingRecvContext.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// Interface used when a custom signal is received. + /// See ISteamNetworkingSockets::ReceivedP2PCustomSignal + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct ISteamNetworkingSignalingRecvContext + { + /// Called when the signal represents a request for a new connection. + /// + /// If you want to ignore the request, just return NULL. In this case, + /// the peer will NOT receive any reply. You should consider ignoring + /// requests rather than actively rejecting them, as a security measure. + /// If you actively reject requests, then this makes it possible to detect + /// if a user is online or not, just by sending them a request. + /// + /// If you wish to send back a rejection, then use + /// ISteamNetworkingSockets::CloseConnection() and then return NULL. + /// We will marshal a properly formatted rejection signal and + /// call SendRejectionSignal() so you can send it to them. + /// + /// If you return a signaling object, the connection is NOT immediately + /// accepted by default. Instead, it stays in the "connecting" state, + /// and the usual callback is posted, and your app can accept the + /// connection using ISteamNetworkingSockets::AcceptConnection. This + /// may be useful so that these sorts of connections can be more similar + /// to your application code as other types of connections accepted on + /// a listen socket. If this is not useful and you want to skip this + /// callback process and immediately accept the connection, call + /// ISteamNetworkingSockets::AcceptConnection before returning the + /// signaling object. + /// + /// After accepting a connection (through either means), the connection + /// will transition into the "finding route" state. + public IntPtr OnConnectRequest(HSteamNetConnection hConn, ref SteamNetworkingIdentity identityPeer, int nLocalVirtualPort) { + return NativeMethods.SteamAPI_ISteamNetworkingSignalingRecvContext_OnConnectRequest(ref this, hConn, ref identityPeer, nLocalVirtualPort); + } + + /// This is called to actively communicate rejection or failure + /// to the incoming message. If you intend to ignore all incoming requests + /// that you do not wish to accept, then it's not strictly necessary to + /// implement this. + public void SendRejectionSignal(ref SteamNetworkingIdentity identityPeer, IntPtr pMsg, int cbMsg) { + NativeMethods.SteamAPI_ISteamNetworkingSignalingRecvContext_SendRejectionSignal(ref this, ref identityPeer, pMsg, cbMsg); + } + } +} + +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingSignalingRecvContext.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingSignalingRecvContext.cs.meta new file mode 100644 index 0000000..5e48bf5 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingSignalingRecvContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa2e1ae613a00394e93e19a1a9ffcdd9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes.meta new file mode 100644 index 0000000..a7148ba --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1ba4e1796c90994458024f38a21ddc00 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/FSteamNetworkingSocketsDebugOutput.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/FSteamNetworkingSocketsDebugOutput.cs new file mode 100644 index 0000000..81e0604 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/FSteamNetworkingSocketsDebugOutput.cs @@ -0,0 +1,23 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + /// Setup callback for debug output, and the desired verbosity you want. + [System.Runtime.InteropServices.UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + public delegate void FSteamNetworkingSocketsDebugOutput(ESteamNetworkingSocketsDebugOutputType nType, System.Text.StringBuilder pszMsg); +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/FSteamNetworkingSocketsDebugOutput.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/FSteamNetworkingSocketsDebugOutput.cs.meta new file mode 100644 index 0000000..376bc55 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/FSteamNetworkingSocketsDebugOutput.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01e845f5c7ac1344bb4f339a4517f229 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamListenSocket.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamListenSocket.cs new file mode 100644 index 0000000..9d22029 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamListenSocket.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HSteamListenSocket : System.IEquatable, System.IComparable { + public static readonly HSteamListenSocket Invalid = new HSteamListenSocket(0); + public uint m_HSteamListenSocket; + + public HSteamListenSocket(uint value) { + m_HSteamListenSocket = value; + } + + public override string ToString() { + return m_HSteamListenSocket.ToString(); + } + + public override bool Equals(object other) { + return other is HSteamListenSocket && this == (HSteamListenSocket)other; + } + + public override int GetHashCode() { + return m_HSteamListenSocket.GetHashCode(); + } + + public static bool operator ==(HSteamListenSocket x, HSteamListenSocket y) { + return x.m_HSteamListenSocket == y.m_HSteamListenSocket; + } + + public static bool operator !=(HSteamListenSocket x, HSteamListenSocket y) { + return !(x == y); + } + + public static explicit operator HSteamListenSocket(uint value) { + return new HSteamListenSocket(value); + } + + public static explicit operator uint(HSteamListenSocket that) { + return that.m_HSteamListenSocket; + } + + public bool Equals(HSteamListenSocket other) { + return m_HSteamListenSocket == other.m_HSteamListenSocket; + } + + public int CompareTo(HSteamListenSocket other) { + return m_HSteamListenSocket.CompareTo(other.m_HSteamListenSocket); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamListenSocket.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamListenSocket.cs.meta new file mode 100644 index 0000000..3b2fea6 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamListenSocket.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 563cb1ebcd2c39742aab1d18d195c956 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetConnection.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetConnection.cs new file mode 100644 index 0000000..02e0ab5 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetConnection.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HSteamNetConnection : System.IEquatable, System.IComparable { + public static readonly HSteamNetConnection Invalid = new HSteamNetConnection(0); + public uint m_HSteamNetConnection; + + public HSteamNetConnection(uint value) { + m_HSteamNetConnection = value; + } + + public override string ToString() { + return m_HSteamNetConnection.ToString(); + } + + public override bool Equals(object other) { + return other is HSteamNetConnection && this == (HSteamNetConnection)other; + } + + public override int GetHashCode() { + return m_HSteamNetConnection.GetHashCode(); + } + + public static bool operator ==(HSteamNetConnection x, HSteamNetConnection y) { + return x.m_HSteamNetConnection == y.m_HSteamNetConnection; + } + + public static bool operator !=(HSteamNetConnection x, HSteamNetConnection y) { + return !(x == y); + } + + public static explicit operator HSteamNetConnection(uint value) { + return new HSteamNetConnection(value); + } + + public static explicit operator uint(HSteamNetConnection that) { + return that.m_HSteamNetConnection; + } + + public bool Equals(HSteamNetConnection other) { + return m_HSteamNetConnection == other.m_HSteamNetConnection; + } + + public int CompareTo(HSteamNetConnection other) { + return m_HSteamNetConnection.CompareTo(other.m_HSteamNetConnection); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetConnection.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetConnection.cs.meta new file mode 100644 index 0000000..633db88 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetConnection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d21865a9baf5e3e46bdb32c46cda3f79 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetPollGroup.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetPollGroup.cs new file mode 100644 index 0000000..662389f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetPollGroup.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HSteamNetPollGroup : System.IEquatable, System.IComparable { + public static readonly HSteamNetPollGroup Invalid = new HSteamNetPollGroup(0); + public uint m_HSteamNetPollGroup; + + public HSteamNetPollGroup(uint value) { + m_HSteamNetPollGroup = value; + } + + public override string ToString() { + return m_HSteamNetPollGroup.ToString(); + } + + public override bool Equals(object other) { + return other is HSteamNetPollGroup && this == (HSteamNetPollGroup)other; + } + + public override int GetHashCode() { + return m_HSteamNetPollGroup.GetHashCode(); + } + + public static bool operator ==(HSteamNetPollGroup x, HSteamNetPollGroup y) { + return x.m_HSteamNetPollGroup == y.m_HSteamNetPollGroup; + } + + public static bool operator !=(HSteamNetPollGroup x, HSteamNetPollGroup y) { + return !(x == y); + } + + public static explicit operator HSteamNetPollGroup(uint value) { + return new HSteamNetPollGroup(value); + } + + public static explicit operator uint(HSteamNetPollGroup that) { + return that.m_HSteamNetPollGroup; + } + + public bool Equals(HSteamNetPollGroup other) { + return m_HSteamNetPollGroup == other.m_HSteamNetPollGroup; + } + + public int CompareTo(HSteamNetPollGroup other) { + return m_HSteamNetPollGroup.CompareTo(other.m_HSteamNetPollGroup); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetPollGroup.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetPollGroup.cs.meta new file mode 100644 index 0000000..93bcbbc --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetPollGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0b21cbbe5b0d2c4789c121a63ff96d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingConfigValue_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingConfigValue_t.cs new file mode 100644 index 0000000..2222a26 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingConfigValue_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// In a few places we need to set configuration options on listen sockets and connections, and + /// have them take effect *before* the listen socket or connection really starts doing anything. + /// Creating the object and then setting the options "immediately" after creation doesn't work + /// completely, because network packets could be received between the time the object is created and + /// when the options are applied. To set options at creation time in a reliable way, they must be + /// passed to the creation function. This structure is used to pass those options. + /// + /// For the meaning of these fields, see ISteamNetworkingUtils::SetConfigValue. Basically + /// when the object is created, we just iterate over the list of options and call + /// ISteamNetworkingUtils::SetConfigValueStruct, where the scope arguments are supplied by the + /// object being created. + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct SteamNetworkingConfigValue_t + { + /// Which option is being set + public ESteamNetworkingConfigValue m_eValue; + + /// Which field below did you fill in? + public ESteamNetworkingConfigDataType m_eDataType; + + /// Option value + public OptionValue m_val; + + [StructLayout(LayoutKind.Explicit)] + public struct OptionValue + { + [FieldOffset(0)] + public int m_int32; + + [FieldOffset(0)] + public long m_int64; + + [FieldOffset(0)] + public float m_float; + + [FieldOffset(0)] + public IntPtr m_string; // Points to your '\0'-terminated buffer + + [FieldOffset(0)] + public IntPtr m_functionPtr; + } + } +} + +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingConfigValue_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingConfigValue_t.cs.meta new file mode 100644 index 0000000..650ccfe --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingConfigValue_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b673ffa9a546ca4bad40431041e7588 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingErrMsg.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingErrMsg.cs new file mode 100644 index 0000000..0d58dd1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingErrMsg.cs @@ -0,0 +1,30 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// Used to return English-language diagnostic error messages to caller. + /// (For debugging or spewing to a console, etc. Not intended for UI.) + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct SteamNetworkingErrMsg + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchMaxSteamNetworkingErrMsg)] + public byte[] m_SteamNetworkingErrMsg; + } +} + +#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingErrMsg.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingErrMsg.cs.meta new file mode 100644 index 0000000..3867d2f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingErrMsg.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd8272539368a044086b35f3cbab9243 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIPAddr.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIPAddr.cs new file mode 100644 index 0000000..fe44c8d --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIPAddr.cs @@ -0,0 +1,114 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// Store an IP and port. IPv6 is always used; IPv4 is represented using + /// "IPv4-mapped" addresses: IPv4 aa.bb.cc.dd => IPv6 ::ffff:aabb:ccdd + /// (RFC 4291 section 2.5.5.2.) + [System.Serializable] + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct SteamNetworkingIPAddr : System.IEquatable + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] m_ipv6; + public ushort m_port; // Host byte order + + // Max length of the buffer needed to hold IP formatted using ToString, including '\0' + // ([0123:4567:89ab:cdef:0123:4567:89ab:cdef]:12345) + public const int k_cchMaxString = 48; + + // Set everything to zero. E.g. [::]:0 + public void Clear() { + NativeMethods.SteamAPI_SteamNetworkingIPAddr_Clear(ref this); + } + + // Return true if the IP is ::0. (Doesn't check port.) + public bool IsIPv6AllZeros() { + return NativeMethods.SteamAPI_SteamNetworkingIPAddr_IsIPv6AllZeros(ref this); + } + + // Set IPv6 address. IP is interpreted as bytes, so there are no endian issues. (Same as inaddr_in6.) The IP can be a mapped IPv4 address + public void SetIPv6(byte[] ipv6, ushort nPort) { + NativeMethods.SteamAPI_SteamNetworkingIPAddr_SetIPv6(ref this, ipv6, nPort); + } + + // Sets to IPv4 mapped address. IP and port are in host byte order. + public void SetIPv4(uint nIP, ushort nPort) { + NativeMethods.SteamAPI_SteamNetworkingIPAddr_SetIPv4(ref this, nIP, nPort); + } + + // Return true if IP is mapped IPv4 + public bool IsIPv4() { + return NativeMethods.SteamAPI_SteamNetworkingIPAddr_IsIPv4(ref this); + } + + // Returns IP in host byte order (e.g. aa.bb.cc.dd as 0xaabbccdd). Returns 0 if IP is not mapped IPv4. + public uint GetIPv4() { + return NativeMethods.SteamAPI_SteamNetworkingIPAddr_GetIPv4(ref this); + } + + // Set to the IPv6 localhost address ::1, and the specified port. + public void SetIPv6LocalHost(ushort nPort = 0) { + NativeMethods.SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost(ref this, nPort); + } + + // Return true if this identity is localhost. (Either IPv6 ::1, or IPv4 127.0.0.1) + public bool IsLocalHost() { + return NativeMethods.SteamAPI_SteamNetworkingIPAddr_IsLocalHost(ref this); + } + + /// Print to a string, with or without the port. Mapped IPv4 addresses are printed + /// as dotted decimal (12.34.56.78), otherwise this will print the canonical + /// form according to RFC5952. If you include the port, IPv6 will be surrounded by + /// brackets, e.g. [::1:2]:80. Your buffer should be at least k_cchMaxString bytes + /// to avoid truncation + /// + /// See also SteamNetworkingIdentityRender + public void ToString(out string buf, bool bWithPort) { + IntPtr buf2 = Marshal.AllocHGlobal(k_cchMaxString); + NativeMethods.SteamAPI_SteamNetworkingIPAddr_ToString(ref this, buf2, k_cchMaxString, bWithPort); + buf = InteropHelp.PtrToStringUTF8(buf2); + Marshal.FreeHGlobal(buf2); + } + + /// Parse an IP address and optional port. If a port is not present, it is set to 0. + /// (This means that you cannot tell if a zero port was explicitly specified.) + public bool ParseString(string pszStr) { + using (var pszStr2 = new InteropHelp.UTF8StringHandle(pszStr)) { + return NativeMethods.SteamAPI_SteamNetworkingIPAddr_ParseString(ref this, pszStr2); + } + } + + /// See if two addresses are identical + public bool Equals(SteamNetworkingIPAddr x) { + return NativeMethods.SteamAPI_SteamNetworkingIPAddr_IsEqualTo(ref this, ref x); + } + + /// Classify address as FakeIP. This function never returns + /// k_ESteamNetworkingFakeIPType_Invalid. + public ESteamNetworkingFakeIPType GetFakeIPType() { + return NativeMethods.SteamAPI_SteamNetworkingIPAddr_GetFakeIPType(ref this); + } + + /// Return true if we are a FakeIP + public bool IsFakeIP() { + return GetFakeIPType() > ESteamNetworkingFakeIPType.k_ESteamNetworkingFakeIPType_NotFake; + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIPAddr.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIPAddr.cs.meta new file mode 100644 index 0000000..0bddf10 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIPAddr.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf91bd24bcddd80499a9a07ed0497513 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIdentity.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIdentity.cs new file mode 100644 index 0000000..b9577a3 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIdentity.cs @@ -0,0 +1,212 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// An abstract way to represent the identity of a network host. All identities can + /// be represented as simple string. Furthermore, this string representation is actually + /// used on the wire in several places, even though it is less efficient, in order to + /// facilitate forward compatibility. (Old client code can handle an identity type that + /// it doesn't understand.) + [System.Serializable] + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct SteamNetworkingIdentity : System.IEquatable + { + /// Type of identity. + public ESteamNetworkingIdentityType m_eType; + + // + // Internal representation. Don't access this directly, use the accessors! + // + // Number of bytes that are relevant below. This MUST ALWAYS be + // set. (Use the accessors!) This is important to enable old code to work + // with new identity types. + private int m_cbSize; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + private uint[] m_reserved; // Pad structure to leave easy room for future expansion + + // Max sizes + public const int k_cchMaxString = 128; // Max length of the buffer needed to hold any identity, formatted in string format by ToString + public const int k_cchMaxGenericString = 32; // Max length of the string for generic string identities. Including terminating '\0' + public const int k_cchMaxXboxPairwiseID = 33; // Including terminating '\0' + public const int k_cbMaxGenericBytes = 32; + + // + // Get/Set in various formats. + // + + public void Clear() { + NativeMethods.SteamAPI_SteamNetworkingIdentity_Clear(ref this); + } + + // Return true if we are the invalid type. Does not make any other validity checks (e.g. is SteamID actually valid) + public bool IsInvalid() { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_IsInvalid(ref this); + } + + public void SetSteamID(CSteamID steamID) { + NativeMethods.SteamAPI_SteamNetworkingIdentity_SetSteamID(ref this, (ulong)steamID); + } + + // Return black CSteamID (!IsValid()) if identity is not a SteamID + public CSteamID GetSteamID() { + return (CSteamID)NativeMethods.SteamAPI_SteamNetworkingIdentity_GetSteamID(ref this); + } + + // Takes SteamID as raw 64-bit number + public void SetSteamID64(ulong steamID) { + NativeMethods.SteamAPI_SteamNetworkingIdentity_SetSteamID64(ref this, steamID); + } + + // Returns 0 if identity is not SteamID + public ulong GetSteamID64() { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_GetSteamID64(ref this); + } + + // Returns false if invalid length + public bool SetXboxPairwiseID(string pszString) + { + using (var pszString2 = new InteropHelp.UTF8StringHandle(pszString)) { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_SetXboxPairwiseID(ref this, pszString2); + } + } + + // Returns nullptr if not Xbox ID + public string GetXboxPairwiseID() + { + return InteropHelp.PtrToStringUTF8(NativeMethods.SteamAPI_SteamNetworkingIdentity_GetXboxPairwiseID(ref this)); + } + + public void SetPSNID(ulong id) + { + NativeMethods.SteamAPI_SteamNetworkingIdentity_SetPSNID(ref this, id); + } + + // Returns 0 if not PSN + public ulong GetPSNID() + { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_GetPSNID(ref this); + } + + public void SetStadiaID(ulong id) + { + NativeMethods.SteamAPI_SteamNetworkingIdentity_SetStadiaID(ref this, id); + } + + // Returns 0 if not Stadia + public ulong GetStadiaID() + { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_GetStadiaID(ref this); + } + + // Set to specified IP:port + public void SetIPAddr(SteamNetworkingIPAddr addr) { + NativeMethods.SteamAPI_SteamNetworkingIdentity_SetIPAddr(ref this, ref addr); + } + + // returns null if we are not an IP address. + public SteamNetworkingIPAddr GetIPAddr(){ + throw new System.NotImplementedException(); + // TODO: Should SteamNetworkingIPAddr be a class? + // or should this return some kind of pointer instead? + //return NativeMethods.SteamAPI_SteamNetworkingIdentity_GetIPAddr(ref this); + } + + public void SetIPv4Addr(uint nIPv4, ushort nPort) { + NativeMethods.SteamAPI_SteamNetworkingIdentity_SetIPv4Addr(ref this, nIPv4, nPort); + } + + // returns 0 if we are not an IPv4 address. + public uint GetIPv4() { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_GetIPv4(ref this); + } + + public ESteamNetworkingFakeIPType GetFakeIPType() { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_GetFakeIPType(ref this); + } + + public bool IsFakeIP() { + return GetFakeIPType() > ESteamNetworkingFakeIPType.k_ESteamNetworkingFakeIPType_NotFake; + } + + // "localhost" is equivalent for many purposes to "anonymous." Our remote + // will identify us by the network address we use. + // Set to localhost. (We always use IPv6 ::1 for this, not 127.0.0.1) + public void SetLocalHost() { + NativeMethods.SteamAPI_SteamNetworkingIdentity_SetLocalHost(ref this); + } + + // Return true if this identity is localhost. + public bool IsLocalHost() { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_IsLocalHost(ref this); + } + + // Returns false if invalid length + public bool SetGenericString(string pszString) { + using (var pszString2 = new InteropHelp.UTF8StringHandle(pszString)) { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_SetGenericString(ref this, pszString2); + } + } + + // Returns nullptr if not generic string type + public string GetGenericString() { + return InteropHelp.PtrToStringUTF8(NativeMethods.SteamAPI_SteamNetworkingIdentity_GetGenericString(ref this)); + } + + // Returns false if invalid size. + public bool SetGenericBytes(byte[] data, uint cbLen) { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_SetGenericBytes(ref this, data, cbLen); + } + + // Returns null if not generic bytes type + public byte[] GetGenericBytes(out int cbLen) { + throw new System.NotImplementedException(); + //return NativeMethods.SteamAPI_SteamNetworkingIdentity_GetGenericBytes(ref this, out cbLen); + } + + /// See if two identities are identical + public bool Equals(SteamNetworkingIdentity x) { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_IsEqualTo(ref this, ref x); + } + + /// Print to a human-readable string. This is suitable for debug messages + /// or any other time you need to encode the identity as a string. It has a + /// URL-like format (type:). Your buffer should be at least + /// k_cchMaxString bytes big to avoid truncation. + /// + /// See also SteamNetworkingIPAddrRender + public void ToString(out string buf) { + IntPtr buf2 = Marshal.AllocHGlobal(k_cchMaxString); + NativeMethods.SteamAPI_SteamNetworkingIdentity_ToString(ref this, buf2, k_cchMaxString); + buf = InteropHelp.PtrToStringUTF8(buf2); + Marshal.FreeHGlobal(buf2); + } + + /// Parse back a string that was generated using ToString. If we don't understand the + /// string, but it looks "reasonable" (it matches the pattern type: and doesn't + /// have any funky characters, etc), then we will return true, and the type is set to + /// k_ESteamNetworkingIdentityType_UnknownType. false will only be returned if the string + /// looks invalid. + public bool ParseString(string pszStr) { + using (var pszStr2 = new InteropHelp.UTF8StringHandle(pszStr)) { + return NativeMethods.SteamAPI_SteamNetworkingIdentity_ParseString(ref this, pszStr2); + } + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIdentity.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIdentity.cs.meta new file mode 100644 index 0000000..6227d31 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIdentity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 88cd24c900131bb40959f94848afdebe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMessage_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMessage_t.cs new file mode 100644 index 0000000..ca2dc3b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMessage_t.cs @@ -0,0 +1,124 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + /// A message that has been received. + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct SteamNetworkingMessage_t + { + /// Message payload + public IntPtr m_pData; + + /// Size of the payload. + public int m_cbSize; + + /// For messages received on connections: what connection did this come from? + /// For outgoing messages: what connection to send it to? + /// Not used when using the ISteamNetworkingMessages interface + public HSteamNetConnection m_conn; + + /// For inbound messages: Who sent this to us? + /// For outbound messages on connections: not used. + /// For outbound messages on the ad-hoc ISteamNetworkingMessages interface: who should we send this to? + public SteamNetworkingIdentity m_identityPeer; + + /// For messages received on connections, this is the user data + /// associated with the connection. + /// + /// This is *usually* the same as calling GetConnection() and then + /// fetching the user data associated with that connection, but for + /// the following subtle differences: + /// + /// - This user data will match the connection's user data at the time + /// is captured at the time the message is returned by the API. + /// If you subsequently change the userdata on the connection, + /// this won't be updated. + /// - This is an inline call, so it's *much* faster. + /// - You might have closed the connection, so fetching the user data + /// would not be possible. + /// + /// Not used when sending messages. + public long m_nConnUserData; + + /// Local timestamp when the message was received + /// Not used for outbound messages. + public SteamNetworkingMicroseconds m_usecTimeReceived; + + /// Message number assigned by the sender. This is not used for outbound + /// messages. Note that if multiple lanes are used, each lane has its own + /// message numbers, which are assigned sequentially, so messages from + /// different lanes will share the same numbers. + public long m_nMessageNumber; + + /// Function used to free up m_pData. This mechanism exists so that + /// apps can create messages with buffers allocated from their own + /// heap, and pass them into the library. This function will + /// usually be something like: + /// + /// free( pMsg->m_pData ); + public IntPtr m_pfnFreeData; + + /// Function to used to decrement the internal reference count and, if + /// it's zero, release the message. You should not set this function pointer, + /// or need to access this directly! Use the Release() function instead! + internal IntPtr m_pfnRelease; + + /// When using ISteamNetworkingMessages, the channel number the message was received on + /// (Not used for messages sent or received on "connections") + public int m_nChannel; + + /// Bitmask of k_nSteamNetworkingSend_xxx flags. + /// For received messages, only the k_nSteamNetworkingSend_Reliable bit is valid. + /// For outbound messages, all bits are relevant + public int m_nFlags; + + /// Arbitrary user data that you can use when sending messages using + /// ISteamNetworkingUtils::AllocateMessage and ISteamNetworkingSockets::SendMessage. + /// (The callback you set in m_pfnFreeData might use this field.) + /// + /// Not used for received messages. + public long m_nUserData; + + /// For outbound messages, which lane to use? See ISteamNetworkingSockets::ConfigureConnectionLanes. + /// For inbound messages, what lane was the message received on? + public ushort m_idxLane; + + public ushort _pad1__; + + /// You MUST call this when you're done with the object, + /// to free up memory, etc. + public void Release() { + throw new System.NotImplementedException("Please use the static Release function instead which takes an IntPtr."); + } + + /// You MUST call this when you're done with the object, + /// to free up memory, etc. + /// This is a Steamworks.NET extension. + public static void Release(IntPtr pointer) { + NativeMethods.SteamAPI_SteamNetworkingMessage_t_Release(pointer); + } + + /// Convert an IntPtr received from ISteamNetworkingSockets.ReceiveMessagesOnPollGroup into our structure. + /// This is a Steamworks.NET extension. + public static SteamNetworkingMessage_t FromIntPtr(IntPtr pointer) { + return (SteamNetworkingMessage_t)Marshal.PtrToStructure(pointer, typeof(SteamNetworkingMessage_t)); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMessage_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMessage_t.cs.meta new file mode 100644 index 0000000..cc41760 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMessage_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be690315b0194d940a0efd3bb3184b90 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMicroseconds.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMicroseconds.cs new file mode 100644 index 0000000..f329784 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMicroseconds.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamNetworkingMicroseconds : System.IEquatable, System.IComparable { + public long m_SteamNetworkingMicroseconds; + + public SteamNetworkingMicroseconds(long value) { + m_SteamNetworkingMicroseconds = value; + } + + public override string ToString() { + return m_SteamNetworkingMicroseconds.ToString(); + } + + public override bool Equals(object other) { + return other is SteamNetworkingMicroseconds && this == (SteamNetworkingMicroseconds)other; + } + + public override int GetHashCode() { + return m_SteamNetworkingMicroseconds.GetHashCode(); + } + + public static bool operator ==(SteamNetworkingMicroseconds x, SteamNetworkingMicroseconds y) { + return x.m_SteamNetworkingMicroseconds == y.m_SteamNetworkingMicroseconds; + } + + public static bool operator !=(SteamNetworkingMicroseconds x, SteamNetworkingMicroseconds y) { + return !(x == y); + } + + public static explicit operator SteamNetworkingMicroseconds(long value) { + return new SteamNetworkingMicroseconds(value); + } + + public static explicit operator long(SteamNetworkingMicroseconds that) { + return that.m_SteamNetworkingMicroseconds; + } + + public bool Equals(SteamNetworkingMicroseconds other) { + return m_SteamNetworkingMicroseconds == other.m_SteamNetworkingMicroseconds; + } + + public int CompareTo(SteamNetworkingMicroseconds other) { + return m_SteamNetworkingMicroseconds.CompareTo(other.m_SteamNetworkingMicroseconds); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMicroseconds.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMicroseconds.cs.meta new file mode 100644 index 0000000..af5dbad --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMicroseconds.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e1e21ac0fb80e0646b09d95b609c47ae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingPOPID.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingPOPID.cs new file mode 100644 index 0000000..29eb4d2 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingPOPID.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamNetworkingPOPID : System.IEquatable, System.IComparable { + public uint m_SteamNetworkingPOPID; + + public SteamNetworkingPOPID(uint value) { + m_SteamNetworkingPOPID = value; + } + + public override string ToString() { + return m_SteamNetworkingPOPID.ToString(); + } + + public override bool Equals(object other) { + return other is SteamNetworkingPOPID && this == (SteamNetworkingPOPID)other; + } + + public override int GetHashCode() { + return m_SteamNetworkingPOPID.GetHashCode(); + } + + public static bool operator ==(SteamNetworkingPOPID x, SteamNetworkingPOPID y) { + return x.m_SteamNetworkingPOPID == y.m_SteamNetworkingPOPID; + } + + public static bool operator !=(SteamNetworkingPOPID x, SteamNetworkingPOPID y) { + return !(x == y); + } + + public static explicit operator SteamNetworkingPOPID(uint value) { + return new SteamNetworkingPOPID(value); + } + + public static explicit operator uint(SteamNetworkingPOPID that) { + return that.m_SteamNetworkingPOPID; + } + + public bool Equals(SteamNetworkingPOPID other) { + return m_SteamNetworkingPOPID == other.m_SteamNetworkingPOPID; + } + + public int CompareTo(SteamNetworkingPOPID other) { + return m_SteamNetworkingPOPID.CompareTo(other.m_SteamNetworkingPOPID); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingPOPID.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingPOPID.cs.meta new file mode 100644 index 0000000..aaae57f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingPOPID.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7173e2ce2d968348a916a5a34f69802 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay.meta new file mode 100644 index 0000000..15eb365 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 785e5463da50dc044a1885d9ec1ad5b3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay/RemotePlaySessionID_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay/RemotePlaySessionID_t.cs new file mode 100644 index 0000000..1718da6 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay/RemotePlaySessionID_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct RemotePlaySessionID_t : System.IEquatable, System.IComparable { + public uint m_RemotePlaySessionID; + + public RemotePlaySessionID_t(uint value) { + m_RemotePlaySessionID = value; + } + + public override string ToString() { + return m_RemotePlaySessionID.ToString(); + } + + public override bool Equals(object other) { + return other is RemotePlaySessionID_t && this == (RemotePlaySessionID_t)other; + } + + public override int GetHashCode() { + return m_RemotePlaySessionID.GetHashCode(); + } + + public static bool operator ==(RemotePlaySessionID_t x, RemotePlaySessionID_t y) { + return x.m_RemotePlaySessionID == y.m_RemotePlaySessionID; + } + + public static bool operator !=(RemotePlaySessionID_t x, RemotePlaySessionID_t y) { + return !(x == y); + } + + public static explicit operator RemotePlaySessionID_t(uint value) { + return new RemotePlaySessionID_t(value); + } + + public static explicit operator uint(RemotePlaySessionID_t that) { + return that.m_RemotePlaySessionID; + } + + public bool Equals(RemotePlaySessionID_t other) { + return m_RemotePlaySessionID == other.m_RemotePlaySessionID; + } + + public int CompareTo(RemotePlaySessionID_t other) { + return m_RemotePlaySessionID.CompareTo(other.m_RemotePlaySessionID); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay/RemotePlaySessionID_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay/RemotePlaySessionID_t.cs.meta new file mode 100644 index 0000000..d1db4cf --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay/RemotePlaySessionID_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e82598941b6d1a4f8e37e437d646bc7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage.meta new file mode 100644 index 0000000..954472e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 32162149a7c3138479f074b56fd5fcbf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileId_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileId_t.cs new file mode 100644 index 0000000..940c043 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileId_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct PublishedFileId_t : System.IEquatable, System.IComparable { + public static readonly PublishedFileId_t Invalid = new PublishedFileId_t(0); + public ulong m_PublishedFileId; + + public PublishedFileId_t(ulong value) { + m_PublishedFileId = value; + } + + public override string ToString() { + return m_PublishedFileId.ToString(); + } + + public override bool Equals(object other) { + return other is PublishedFileId_t && this == (PublishedFileId_t)other; + } + + public override int GetHashCode() { + return m_PublishedFileId.GetHashCode(); + } + + public static bool operator ==(PublishedFileId_t x, PublishedFileId_t y) { + return x.m_PublishedFileId == y.m_PublishedFileId; + } + + public static bool operator !=(PublishedFileId_t x, PublishedFileId_t y) { + return !(x == y); + } + + public static explicit operator PublishedFileId_t(ulong value) { + return new PublishedFileId_t(value); + } + + public static explicit operator ulong(PublishedFileId_t that) { + return that.m_PublishedFileId; + } + + public bool Equals(PublishedFileId_t other) { + return m_PublishedFileId == other.m_PublishedFileId; + } + + public int CompareTo(PublishedFileId_t other) { + return m_PublishedFileId.CompareTo(other.m_PublishedFileId); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileId_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileId_t.cs.meta new file mode 100644 index 0000000..6739831 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileId_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd7277dd62d0eb749bf2cb299b2a5c2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs new file mode 100644 index 0000000..1c35446 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct PublishedFileUpdateHandle_t : System.IEquatable, System.IComparable { + public static readonly PublishedFileUpdateHandle_t Invalid = new PublishedFileUpdateHandle_t(0xffffffffffffffff); + public ulong m_PublishedFileUpdateHandle; + + public PublishedFileUpdateHandle_t(ulong value) { + m_PublishedFileUpdateHandle = value; + } + + public override string ToString() { + return m_PublishedFileUpdateHandle.ToString(); + } + + public override bool Equals(object other) { + return other is PublishedFileUpdateHandle_t && this == (PublishedFileUpdateHandle_t)other; + } + + public override int GetHashCode() { + return m_PublishedFileUpdateHandle.GetHashCode(); + } + + public static bool operator ==(PublishedFileUpdateHandle_t x, PublishedFileUpdateHandle_t y) { + return x.m_PublishedFileUpdateHandle == y.m_PublishedFileUpdateHandle; + } + + public static bool operator !=(PublishedFileUpdateHandle_t x, PublishedFileUpdateHandle_t y) { + return !(x == y); + } + + public static explicit operator PublishedFileUpdateHandle_t(ulong value) { + return new PublishedFileUpdateHandle_t(value); + } + + public static explicit operator ulong(PublishedFileUpdateHandle_t that) { + return that.m_PublishedFileUpdateHandle; + } + + public bool Equals(PublishedFileUpdateHandle_t other) { + return m_PublishedFileUpdateHandle == other.m_PublishedFileUpdateHandle; + } + + public int CompareTo(PublishedFileUpdateHandle_t other) { + return m_PublishedFileUpdateHandle.CompareTo(other.m_PublishedFileUpdateHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs.meta new file mode 100644 index 0000000..73ddb32 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 430206ab4ee381d4d87a4afa70f5080f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs new file mode 100644 index 0000000..9318169 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct UGCFileWriteStreamHandle_t : System.IEquatable, System.IComparable { + public static readonly UGCFileWriteStreamHandle_t Invalid = new UGCFileWriteStreamHandle_t(0xffffffffffffffff); + public ulong m_UGCFileWriteStreamHandle; + + public UGCFileWriteStreamHandle_t(ulong value) { + m_UGCFileWriteStreamHandle = value; + } + + public override string ToString() { + return m_UGCFileWriteStreamHandle.ToString(); + } + + public override bool Equals(object other) { + return other is UGCFileWriteStreamHandle_t && this == (UGCFileWriteStreamHandle_t)other; + } + + public override int GetHashCode() { + return m_UGCFileWriteStreamHandle.GetHashCode(); + } + + public static bool operator ==(UGCFileWriteStreamHandle_t x, UGCFileWriteStreamHandle_t y) { + return x.m_UGCFileWriteStreamHandle == y.m_UGCFileWriteStreamHandle; + } + + public static bool operator !=(UGCFileWriteStreamHandle_t x, UGCFileWriteStreamHandle_t y) { + return !(x == y); + } + + public static explicit operator UGCFileWriteStreamHandle_t(ulong value) { + return new UGCFileWriteStreamHandle_t(value); + } + + public static explicit operator ulong(UGCFileWriteStreamHandle_t that) { + return that.m_UGCFileWriteStreamHandle; + } + + public bool Equals(UGCFileWriteStreamHandle_t other) { + return m_UGCFileWriteStreamHandle == other.m_UGCFileWriteStreamHandle; + } + + public int CompareTo(UGCFileWriteStreamHandle_t other) { + return m_UGCFileWriteStreamHandle.CompareTo(other.m_UGCFileWriteStreamHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs.meta new file mode 100644 index 0000000..43a3359 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2ff9e154c69ad847a864b78b6d88ed7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCHandle_t.cs new file mode 100644 index 0000000..7690ee3 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCHandle_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct UGCHandle_t : System.IEquatable, System.IComparable { + public static readonly UGCHandle_t Invalid = new UGCHandle_t(0xffffffffffffffff); + public ulong m_UGCHandle; + + public UGCHandle_t(ulong value) { + m_UGCHandle = value; + } + + public override string ToString() { + return m_UGCHandle.ToString(); + } + + public override bool Equals(object other) { + return other is UGCHandle_t && this == (UGCHandle_t)other; + } + + public override int GetHashCode() { + return m_UGCHandle.GetHashCode(); + } + + public static bool operator ==(UGCHandle_t x, UGCHandle_t y) { + return x.m_UGCHandle == y.m_UGCHandle; + } + + public static bool operator !=(UGCHandle_t x, UGCHandle_t y) { + return !(x == y); + } + + public static explicit operator UGCHandle_t(ulong value) { + return new UGCHandle_t(value); + } + + public static explicit operator ulong(UGCHandle_t that) { + return that.m_UGCHandle; + } + + public bool Equals(UGCHandle_t other) { + return m_UGCHandle == other.m_UGCHandle; + } + + public int CompareTo(UGCHandle_t other) { + return m_UGCHandle.CompareTo(other.m_UGCHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCHandle_t.cs.meta new file mode 100644 index 0000000..79f344e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0fe3f8688517afd449fb9033615c59f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots.meta new file mode 100644 index 0000000..dd65d20 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f2907eea4844294788c7760f70ca3de +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots/ScreenshotHandle.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots/ScreenshotHandle.cs new file mode 100644 index 0000000..4ec154c --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots/ScreenshotHandle.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct ScreenshotHandle : System.IEquatable, System.IComparable { + public static readonly ScreenshotHandle Invalid = new ScreenshotHandle(0); + public uint m_ScreenshotHandle; + + public ScreenshotHandle(uint value) { + m_ScreenshotHandle = value; + } + + public override string ToString() { + return m_ScreenshotHandle.ToString(); + } + + public override bool Equals(object other) { + return other is ScreenshotHandle && this == (ScreenshotHandle)other; + } + + public override int GetHashCode() { + return m_ScreenshotHandle.GetHashCode(); + } + + public static bool operator ==(ScreenshotHandle x, ScreenshotHandle y) { + return x.m_ScreenshotHandle == y.m_ScreenshotHandle; + } + + public static bool operator !=(ScreenshotHandle x, ScreenshotHandle y) { + return !(x == y); + } + + public static explicit operator ScreenshotHandle(uint value) { + return new ScreenshotHandle(value); + } + + public static explicit operator uint(ScreenshotHandle that) { + return that.m_ScreenshotHandle; + } + + public bool Equals(ScreenshotHandle other) { + return m_ScreenshotHandle == other.m_ScreenshotHandle; + } + + public int CompareTo(ScreenshotHandle other) { + return m_ScreenshotHandle.CompareTo(other.m_ScreenshotHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots/ScreenshotHandle.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots/ScreenshotHandle.cs.meta new file mode 100644 index 0000000..2a7c18b --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots/ScreenshotHandle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1436725e4a2ba6a4499efc2c11c31ece +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes.meta new file mode 100644 index 0000000..78ae71a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 974997dd55b47904bb658083a2bb24cf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AccountID_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AccountID_t.cs new file mode 100644 index 0000000..0392ac0 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AccountID_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct AccountID_t : System.IEquatable, System.IComparable { + public uint m_AccountID; + + public AccountID_t(uint value) { + m_AccountID = value; + } + + public override string ToString() { + return m_AccountID.ToString(); + } + + public override bool Equals(object other) { + return other is AccountID_t && this == (AccountID_t)other; + } + + public override int GetHashCode() { + return m_AccountID.GetHashCode(); + } + + public static bool operator ==(AccountID_t x, AccountID_t y) { + return x.m_AccountID == y.m_AccountID; + } + + public static bool operator !=(AccountID_t x, AccountID_t y) { + return !(x == y); + } + + public static explicit operator AccountID_t(uint value) { + return new AccountID_t(value); + } + + public static explicit operator uint(AccountID_t that) { + return that.m_AccountID; + } + + public bool Equals(AccountID_t other) { + return m_AccountID == other.m_AccountID; + } + + public int CompareTo(AccountID_t other) { + return m_AccountID.CompareTo(other.m_AccountID); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AccountID_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AccountID_t.cs.meta new file mode 100644 index 0000000..abbd2c0 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AccountID_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 14ca323dce9e1d241920cf66187ff942 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AppId_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AppId_t.cs new file mode 100644 index 0000000..8356307 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AppId_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct AppId_t : System.IEquatable, System.IComparable { + public static readonly AppId_t Invalid = new AppId_t(0x0); + public uint m_AppId; + + public AppId_t(uint value) { + m_AppId = value; + } + + public override string ToString() { + return m_AppId.ToString(); + } + + public override bool Equals(object other) { + return other is AppId_t && this == (AppId_t)other; + } + + public override int GetHashCode() { + return m_AppId.GetHashCode(); + } + + public static bool operator ==(AppId_t x, AppId_t y) { + return x.m_AppId == y.m_AppId; + } + + public static bool operator !=(AppId_t x, AppId_t y) { + return !(x == y); + } + + public static explicit operator AppId_t(uint value) { + return new AppId_t(value); + } + + public static explicit operator uint(AppId_t that) { + return that.m_AppId; + } + + public bool Equals(AppId_t other) { + return m_AppId == other.m_AppId; + } + + public int CompareTo(AppId_t other) { + return m_AppId.CompareTo(other.m_AppId); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AppId_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AppId_t.cs.meta new file mode 100644 index 0000000..7befb10 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AppId_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 257b639b116e86d48b55f02ffb69fe8f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/DepotId_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/DepotId_t.cs new file mode 100644 index 0000000..9bab73f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/DepotId_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct DepotId_t : System.IEquatable, System.IComparable { + public static readonly DepotId_t Invalid = new DepotId_t(0x0); + public uint m_DepotId; + + public DepotId_t(uint value) { + m_DepotId = value; + } + + public override string ToString() { + return m_DepotId.ToString(); + } + + public override bool Equals(object other) { + return other is DepotId_t && this == (DepotId_t)other; + } + + public override int GetHashCode() { + return m_DepotId.GetHashCode(); + } + + public static bool operator ==(DepotId_t x, DepotId_t y) { + return x.m_DepotId == y.m_DepotId; + } + + public static bool operator !=(DepotId_t x, DepotId_t y) { + return !(x == y); + } + + public static explicit operator DepotId_t(uint value) { + return new DepotId_t(value); + } + + public static explicit operator uint(DepotId_t that) { + return that.m_DepotId; + } + + public bool Equals(DepotId_t other) { + return m_DepotId == other.m_DepotId; + } + + public int CompareTo(DepotId_t other) { + return m_DepotId.CompareTo(other.m_DepotId); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/DepotId_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/DepotId_t.cs.meta new file mode 100644 index 0000000..0ee2f1c --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/DepotId_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d6f3da1acbe8e0245af0a17e34591226 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/PartyBeaconID_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/PartyBeaconID_t.cs new file mode 100644 index 0000000..b32e45f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/PartyBeaconID_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct PartyBeaconID_t : System.IEquatable, System.IComparable { + public static readonly PartyBeaconID_t Invalid = new PartyBeaconID_t(0); + public ulong m_PartyBeaconID; + + public PartyBeaconID_t(ulong value) { + m_PartyBeaconID = value; + } + + public override string ToString() { + return m_PartyBeaconID.ToString(); + } + + public override bool Equals(object other) { + return other is PartyBeaconID_t && this == (PartyBeaconID_t)other; + } + + public override int GetHashCode() { + return m_PartyBeaconID.GetHashCode(); + } + + public static bool operator ==(PartyBeaconID_t x, PartyBeaconID_t y) { + return x.m_PartyBeaconID == y.m_PartyBeaconID; + } + + public static bool operator !=(PartyBeaconID_t x, PartyBeaconID_t y) { + return !(x == y); + } + + public static explicit operator PartyBeaconID_t(ulong value) { + return new PartyBeaconID_t(value); + } + + public static explicit operator ulong(PartyBeaconID_t that) { + return that.m_PartyBeaconID; + } + + public bool Equals(PartyBeaconID_t other) { + return m_PartyBeaconID == other.m_PartyBeaconID; + } + + public int CompareTo(PartyBeaconID_t other) { + return m_PartyBeaconID.CompareTo(other.m_PartyBeaconID); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/PartyBeaconID_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/PartyBeaconID_t.cs.meta new file mode 100644 index 0000000..72eca38 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/PartyBeaconID_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0df4c6d3bca0df246a4cbca1bb730270 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/RTime32.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/RTime32.cs new file mode 100644 index 0000000..249dda2 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/RTime32.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct RTime32 : System.IEquatable, System.IComparable { + public uint m_RTime32; + + public RTime32(uint value) { + m_RTime32 = value; + } + + public override string ToString() { + return m_RTime32.ToString(); + } + + public override bool Equals(object other) { + return other is RTime32 && this == (RTime32)other; + } + + public override int GetHashCode() { + return m_RTime32.GetHashCode(); + } + + public static bool operator ==(RTime32 x, RTime32 y) { + return x.m_RTime32 == y.m_RTime32; + } + + public static bool operator !=(RTime32 x, RTime32 y) { + return !(x == y); + } + + public static explicit operator RTime32(uint value) { + return new RTime32(value); + } + + public static explicit operator uint(RTime32 that) { + return that.m_RTime32; + } + + public bool Equals(RTime32 other) { + return m_RTime32 == other.m_RTime32; + } + + public int CompareTo(RTime32 other) { + return m_RTime32.CompareTo(other.m_RTime32); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/RTime32.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/RTime32.cs.meta new file mode 100644 index 0000000..1fa316a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/RTime32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3da8b25ad32a0794286fc4770816b72b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamAPICall_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamAPICall_t.cs new file mode 100644 index 0000000..c104f14 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamAPICall_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamAPICall_t : System.IEquatable, System.IComparable { + public static readonly SteamAPICall_t Invalid = new SteamAPICall_t(0x0); + public ulong m_SteamAPICall; + + public SteamAPICall_t(ulong value) { + m_SteamAPICall = value; + } + + public override string ToString() { + return m_SteamAPICall.ToString(); + } + + public override bool Equals(object other) { + return other is SteamAPICall_t && this == (SteamAPICall_t)other; + } + + public override int GetHashCode() { + return m_SteamAPICall.GetHashCode(); + } + + public static bool operator ==(SteamAPICall_t x, SteamAPICall_t y) { + return x.m_SteamAPICall == y.m_SteamAPICall; + } + + public static bool operator !=(SteamAPICall_t x, SteamAPICall_t y) { + return !(x == y); + } + + public static explicit operator SteamAPICall_t(ulong value) { + return new SteamAPICall_t(value); + } + + public static explicit operator ulong(SteamAPICall_t that) { + return that.m_SteamAPICall; + } + + public bool Equals(SteamAPICall_t other) { + return m_SteamAPICall == other.m_SteamAPICall; + } + + public int CompareTo(SteamAPICall_t other) { + return m_SteamAPICall.CompareTo(other.m_SteamAPICall); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamAPICall_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamAPICall_t.cs.meta new file mode 100644 index 0000000..b9cd2c1 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamAPICall_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7bf82421c480484aa48595885f6f133 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamIPAddress_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamIPAddress_t.cs new file mode 100644 index 0000000..a815682 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamIPAddress_t.cs @@ -0,0 +1,97 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks +{ + [System.Serializable] + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct SteamIPAddress_t + { + private long m_ip0; + private long m_ip1; + + private ESteamIPType m_eType; + + public SteamIPAddress_t(System.Net.IPAddress iPAddress) + { + byte[] bytes = iPAddress.GetAddressBytes(); + switch (iPAddress.AddressFamily) + { + case System.Net.Sockets.AddressFamily.InterNetwork: + { + if (bytes.Length != 4) + { + throw new System.TypeInitializationException("SteamIPAddress_t: Unexpected byte length for Ipv4." + bytes.Length, null); + } + + m_ip0 = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; + m_ip1 = 0; + m_eType = ESteamIPType.k_ESteamIPTypeIPv4; + break; + } + case System.Net.Sockets.AddressFamily.InterNetworkV6: + { + if (bytes.Length != 16) + { + throw new System.TypeInitializationException("SteamIPAddress_t: Unexpected byte length for Ipv6: " + bytes.Length, null); + } + + m_ip0 = (bytes[1] << 56) | (bytes[0] << 48) | (bytes[3] << 40) | (bytes[2] << 32) | (bytes[5] << 24) | (bytes[4] << 16) | (bytes[7] << 8) | bytes[6]; + m_ip1 = (bytes[9] << 56) | (bytes[8] << 48) | (bytes[11] << 40) | (bytes[10] << 32) | (bytes[13] << 24) | (bytes[12] << 16) | (bytes[15] << 8) | bytes[14]; + m_eType = ESteamIPType.k_ESteamIPTypeIPv6; + break; + } + default: + { + throw new System.TypeInitializationException("SteamIPAddress_t: Unexpected address family " + iPAddress.AddressFamily, null); + } + } + } + + public System.Net.IPAddress ToIPAddress() + { + if (m_eType == ESteamIPType.k_ESteamIPTypeIPv4) + { + byte[] bytes = System.BitConverter.GetBytes(m_ip0); + return new System.Net.IPAddress(new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }); + } + else + { + byte[] bytes = new byte[16]; + System.BitConverter.GetBytes(m_ip0).CopyTo(bytes, 0); + System.BitConverter.GetBytes(m_ip1).CopyTo(bytes, 8); + return new System.Net.IPAddress(bytes); + } + } + + public override string ToString() + { + return ToIPAddress().ToString(); + } + + public ESteamIPType GetIPType() + { + return m_eType; + } + + public bool IsSet() + { + return m_ip0 != 0 || m_ip1 != 0; + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamIPAddress_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamIPAddress_t.cs.meta new file mode 100644 index 0000000..cf5aa98 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamIPAddress_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e4fa66c7d10afeb438394cd486f094d8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC.meta new file mode 100644 index 0000000..1f5d7d5 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 99134a34a0d89cc46a5397ffa2081668 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCQueryHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCQueryHandle_t.cs new file mode 100644 index 0000000..334d2e8 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCQueryHandle_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct UGCQueryHandle_t : System.IEquatable, System.IComparable { + public static readonly UGCQueryHandle_t Invalid = new UGCQueryHandle_t(0xffffffffffffffff); + public ulong m_UGCQueryHandle; + + public UGCQueryHandle_t(ulong value) { + m_UGCQueryHandle = value; + } + + public override string ToString() { + return m_UGCQueryHandle.ToString(); + } + + public override bool Equals(object other) { + return other is UGCQueryHandle_t && this == (UGCQueryHandle_t)other; + } + + public override int GetHashCode() { + return m_UGCQueryHandle.GetHashCode(); + } + + public static bool operator ==(UGCQueryHandle_t x, UGCQueryHandle_t y) { + return x.m_UGCQueryHandle == y.m_UGCQueryHandle; + } + + public static bool operator !=(UGCQueryHandle_t x, UGCQueryHandle_t y) { + return !(x == y); + } + + public static explicit operator UGCQueryHandle_t(ulong value) { + return new UGCQueryHandle_t(value); + } + + public static explicit operator ulong(UGCQueryHandle_t that) { + return that.m_UGCQueryHandle; + } + + public bool Equals(UGCQueryHandle_t other) { + return m_UGCQueryHandle == other.m_UGCQueryHandle; + } + + public int CompareTo(UGCQueryHandle_t other) { + return m_UGCQueryHandle.CompareTo(other.m_UGCQueryHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCQueryHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCQueryHandle_t.cs.meta new file mode 100644 index 0000000..f8e5992 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCQueryHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b5f5b5e4cd20e84fbd48cc6ec0065ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCUpdateHandle_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCUpdateHandle_t.cs new file mode 100644 index 0000000..d56be97 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCUpdateHandle_t.cs @@ -0,0 +1,65 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct UGCUpdateHandle_t : System.IEquatable, System.IComparable { + public static readonly UGCUpdateHandle_t Invalid = new UGCUpdateHandle_t(0xffffffffffffffff); + public ulong m_UGCUpdateHandle; + + public UGCUpdateHandle_t(ulong value) { + m_UGCUpdateHandle = value; + } + + public override string ToString() { + return m_UGCUpdateHandle.ToString(); + } + + public override bool Equals(object other) { + return other is UGCUpdateHandle_t && this == (UGCUpdateHandle_t)other; + } + + public override int GetHashCode() { + return m_UGCUpdateHandle.GetHashCode(); + } + + public static bool operator ==(UGCUpdateHandle_t x, UGCUpdateHandle_t y) { + return x.m_UGCUpdateHandle == y.m_UGCUpdateHandle; + } + + public static bool operator !=(UGCUpdateHandle_t x, UGCUpdateHandle_t y) { + return !(x == y); + } + + public static explicit operator UGCUpdateHandle_t(ulong value) { + return new UGCUpdateHandle_t(value); + } + + public static explicit operator ulong(UGCUpdateHandle_t that) { + return that.m_UGCUpdateHandle; + } + + public bool Equals(UGCUpdateHandle_t other) { + return m_UGCUpdateHandle == other.m_UGCUpdateHandle; + } + + public int CompareTo(UGCUpdateHandle_t other) { + return m_UGCUpdateHandle.CompareTo(other.m_UGCUpdateHandle); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCUpdateHandle_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCUpdateHandle_t.cs.meta new file mode 100644 index 0000000..18a1457 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCUpdateHandle_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90d7e94aac0e4fd48be2447dd81e86f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats.meta new file mode 100644 index 0000000..8e641a4 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a737c8870eef534dbb2bd2e1627d83a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboardEntries_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboardEntries_t.cs new file mode 100644 index 0000000..17080e4 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboardEntries_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamLeaderboardEntries_t : System.IEquatable, System.IComparable { + public ulong m_SteamLeaderboardEntries; + + public SteamLeaderboardEntries_t(ulong value) { + m_SteamLeaderboardEntries = value; + } + + public override string ToString() { + return m_SteamLeaderboardEntries.ToString(); + } + + public override bool Equals(object other) { + return other is SteamLeaderboardEntries_t && this == (SteamLeaderboardEntries_t)other; + } + + public override int GetHashCode() { + return m_SteamLeaderboardEntries.GetHashCode(); + } + + public static bool operator ==(SteamLeaderboardEntries_t x, SteamLeaderboardEntries_t y) { + return x.m_SteamLeaderboardEntries == y.m_SteamLeaderboardEntries; + } + + public static bool operator !=(SteamLeaderboardEntries_t x, SteamLeaderboardEntries_t y) { + return !(x == y); + } + + public static explicit operator SteamLeaderboardEntries_t(ulong value) { + return new SteamLeaderboardEntries_t(value); + } + + public static explicit operator ulong(SteamLeaderboardEntries_t that) { + return that.m_SteamLeaderboardEntries; + } + + public bool Equals(SteamLeaderboardEntries_t other) { + return m_SteamLeaderboardEntries == other.m_SteamLeaderboardEntries; + } + + public int CompareTo(SteamLeaderboardEntries_t other) { + return m_SteamLeaderboardEntries.CompareTo(other.m_SteamLeaderboardEntries); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboardEntries_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboardEntries_t.cs.meta new file mode 100644 index 0000000..5b8dd5a --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboardEntries_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f59bfdaf96f5324589e1302cdd36cb6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboard_t.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboard_t.cs new file mode 100644 index 0000000..a68367c --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboard_t.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct SteamLeaderboard_t : System.IEquatable, System.IComparable { + public ulong m_SteamLeaderboard; + + public SteamLeaderboard_t(ulong value) { + m_SteamLeaderboard = value; + } + + public override string ToString() { + return m_SteamLeaderboard.ToString(); + } + + public override bool Equals(object other) { + return other is SteamLeaderboard_t && this == (SteamLeaderboard_t)other; + } + + public override int GetHashCode() { + return m_SteamLeaderboard.GetHashCode(); + } + + public static bool operator ==(SteamLeaderboard_t x, SteamLeaderboard_t y) { + return x.m_SteamLeaderboard == y.m_SteamLeaderboard; + } + + public static bool operator !=(SteamLeaderboard_t x, SteamLeaderboard_t y) { + return !(x == y); + } + + public static explicit operator SteamLeaderboard_t(ulong value) { + return new SteamLeaderboard_t(value); + } + + public static explicit operator ulong(SteamLeaderboard_t that) { + return that.m_SteamLeaderboard; + } + + public bool Equals(SteamLeaderboard_t other) { + return m_SteamLeaderboard == other.m_SteamLeaderboard; + } + + public int CompareTo(SteamLeaderboard_t other) { + return m_SteamLeaderboard.CompareTo(other.m_SteamLeaderboard); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboard_t.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboard_t.cs.meta new file mode 100644 index 0000000..c809d5e --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboard_t.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 32228d2b055627c439306ea877bb2cef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common.meta new file mode 100644 index 0000000..b740c91 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cef32dd326c9ccd4386e5df0302100e3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamPipe.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamPipe.cs new file mode 100644 index 0000000..ad4b7d2 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamPipe.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HSteamPipe : System.IEquatable, System.IComparable { + public int m_HSteamPipe; + + public HSteamPipe(int value) { + m_HSteamPipe = value; + } + + public override string ToString() { + return m_HSteamPipe.ToString(); + } + + public override bool Equals(object other) { + return other is HSteamPipe && this == (HSteamPipe)other; + } + + public override int GetHashCode() { + return m_HSteamPipe.GetHashCode(); + } + + public static bool operator ==(HSteamPipe x, HSteamPipe y) { + return x.m_HSteamPipe == y.m_HSteamPipe; + } + + public static bool operator !=(HSteamPipe x, HSteamPipe y) { + return !(x == y); + } + + public static explicit operator HSteamPipe(int value) { + return new HSteamPipe(value); + } + + public static explicit operator int(HSteamPipe that) { + return that.m_HSteamPipe; + } + + public bool Equals(HSteamPipe other) { + return m_HSteamPipe == other.m_HSteamPipe; + } + + public int CompareTo(HSteamPipe other) { + return m_HSteamPipe.CompareTo(other.m_HSteamPipe); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamPipe.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamPipe.cs.meta new file mode 100644 index 0000000..1b06e2f --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamPipe.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 673a35c06ba2f3547bc0739d23c97ac7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamUser.cs b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamUser.cs new file mode 100644 index 0000000..a7fb2dd --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamUser.cs @@ -0,0 +1,64 @@ +// This file is provided under The MIT License as part of Steamworks.NET. +// Copyright (c) 2013-2022 Riley Labrecque +// Please see the included LICENSE.txt for additional information. + +// This file is automatically generated. +// Changes to this file will be reverted when you update Steamworks.NET + +#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX) + #define DISABLESTEAMWORKS +#endif + +#if !DISABLESTEAMWORKS + +using System.Runtime.InteropServices; +using IntPtr = System.IntPtr; + +namespace Steamworks { + [System.Serializable] + public struct HSteamUser : System.IEquatable, System.IComparable { + public int m_HSteamUser; + + public HSteamUser(int value) { + m_HSteamUser = value; + } + + public override string ToString() { + return m_HSteamUser.ToString(); + } + + public override bool Equals(object other) { + return other is HSteamUser && this == (HSteamUser)other; + } + + public override int GetHashCode() { + return m_HSteamUser.GetHashCode(); + } + + public static bool operator ==(HSteamUser x, HSteamUser y) { + return x.m_HSteamUser == y.m_HSteamUser; + } + + public static bool operator !=(HSteamUser x, HSteamUser y) { + return !(x == y); + } + + public static explicit operator HSteamUser(int value) { + return new HSteamUser(value); + } + + public static explicit operator int(HSteamUser that) { + return that.m_HSteamUser; + } + + public bool Equals(HSteamUser other) { + return m_HSteamUser == other.m_HSteamUser; + } + + public int CompareTo(HSteamUser other) { + return m_HSteamUser.CompareTo(other.m_HSteamUser); + } + } +} + +#endif // !DISABLESTEAMWORKS diff --git a/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamUser.cs.meta b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamUser.cs.meta new file mode 100644 index 0000000..947c713 --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamUser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2784c0d3f1bcd54493a2b76dd8972a1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/com.rlabrecque.steamworks.net/package.json b/Assets/com.rlabrecque.steamworks.net/package.json new file mode 100644 index 0000000..85c70ec --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/package.json @@ -0,0 +1,21 @@ +{ + "name": "com.rlabrecque.steamworks.net", + "displayName": "Steamworks.NET", + "version": "20.2.0", + "unity": "2019.4", + "author": { + "name": "Riley Labrecque", + "email": "support@rileylabrecque.com", + "url": "https://steamworks.github.io" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/rlabrecque/Steamworks.NET.git?path=/com.rlabrecque.steamworks.net" + }, + "keywords": [ + "steam", + "steamworks" + ], + "description": "Steamworks.NET is a C# Wrapper for Valve's Steamworks API." +} diff --git a/Assets/com.rlabrecque.steamworks.net/package.json.meta b/Assets/com.rlabrecque.steamworks.net/package.json.meta new file mode 100644 index 0000000..e9484ea --- /dev/null +++ b/Assets/com.rlabrecque.steamworks.net/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f9b6ad16257b2144c906eed15ad9f51e +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json new file mode 100644 index 0000000..cf8a149 --- /dev/null +++ b/Packages/manifest.json @@ -0,0 +1,48 @@ +{ + "dependencies": { + "com.unity.collab-proxy": "2.7.1", + "com.unity.ide.rider": "3.0.31", + "com.unity.ide.visualstudio": "2.0.22", + "com.unity.ide.vscode": "1.2.5", + "com.unity.multiplayer.center": "1.0.0", + "com.unity.nuget.newtonsoft-json": "3.2.1", + "com.unity.render-pipelines.universal": "17.0.4", + "com.unity.test-framework": "1.4.6", + "com.unity.timeline": "1.8.7", + "com.unity.toolchain.win-x86_64-linux-x86_64": "2.0.10", + "com.unity.ugui": "2.0.0", + "com.unity.visualscripting": "1.9.5", + "com.unity.modules.accessibility": "1.0.0", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json new file mode 100644 index 0000000..50e997a --- /dev/null +++ b/Packages/packages-lock.json @@ -0,0 +1,487 @@ +{ + "dependencies": { + "com.unity.burst": { + "version": "1.8.19", + "depth": 2, + "source": "registry", + "dependencies": { + "com.unity.mathematics": "1.2.1", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.collab-proxy": { + "version": "2.7.1", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.collections": { + "version": "2.5.1", + "depth": 2, + "source": "registry", + "dependencies": { + "com.unity.burst": "1.8.17", + "com.unity.test-framework": "1.4.5", + "com.unity.nuget.mono-cecil": "1.11.4", + "com.unity.test-framework.performance": "3.0.3" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ext.nunit": { + "version": "2.0.5", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ide.rider": { + "version": "3.0.31", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.visualstudio": { + "version": "2.0.22", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.9" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.vscode": { + "version": "1.2.5", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.mathematics": { + "version": "1.3.2", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.multiplayer.center": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.uielements": "1.0.0" + } + }, + "com.unity.nuget.mono-cecil": { + "version": "1.11.4", + "depth": 3, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.nuget.newtonsoft-json": { + "version": "3.2.1", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.render-pipelines.core": { + "version": "17.0.4", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.burst": "1.8.14", + "com.unity.mathematics": "1.3.2", + "com.unity.ugui": "2.0.0", + "com.unity.collections": "2.4.3", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.rendering.light-transport": "1.0.1" + } + }, + "com.unity.render-pipelines.universal": { + "version": "17.0.4", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.0.4", + "com.unity.shadergraph": "17.0.4", + "com.unity.render-pipelines.universal-config": "17.0.3" + } + }, + "com.unity.render-pipelines.universal-config": { + "version": "17.0.3", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.0.3" + } + }, + "com.unity.rendering.light-transport": { + "version": "1.0.1", + "depth": 2, + "source": "builtin", + "dependencies": { + "com.unity.collections": "2.2.0", + "com.unity.mathematics": "1.2.4", + "com.unity.modules.terrain": "1.0.0" + } + }, + "com.unity.searcher": { + "version": "4.9.3", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.shadergraph": { + "version": "17.0.4", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.0.4", + "com.unity.searcher": "4.9.3" + } + }, + "com.unity.sysroot": { + "version": "2.0.10", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.sysroot.linux-x86_64": { + "version": "2.0.9", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.sysroot": "2.0.10" + }, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework": { + "version": "1.4.6", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "2.0.3", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework.performance": { + "version": "3.0.3", + "depth": 3, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.31", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.timeline": { + "version": "1.8.7", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.toolchain.win-x86_64-linux-x86_64": { + "version": "2.0.10", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.sysroot": "2.0.10", + "com.unity.sysroot.linux-x86_64": "2.0.9" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ugui": { + "version": "2.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0" + } + }, + "com.unity.visualscripting": { + "version": "1.9.5", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ugui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.modules.accessibility": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.ai": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.androidjni": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.animation": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.assetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.audio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.cloth": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.director": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.animation": "1.0.0" + } + }, + "com.unity.modules.hierarchycore": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.imageconversion": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.imgui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.jsonserialize": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.particlesystem": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics2d": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.screencapture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.subsystems": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.terrain": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.terrainphysics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.terrain": "1.0.0" + } + }, + "com.unity.modules.tilemap": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics2d": "1.0.0" + } + }, + "com.unity.modules.ui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.uielements": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.hierarchycore": "1.0.0" + } + }, + "com.unity.modules.umbra": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unityanalytics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.unitywebrequest": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unitywebrequestassetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestaudio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.audio": "1.0.0" + } + }, + "com.unity.modules.unitywebrequesttexture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestwww": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.vehicles": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.video": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.vr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } + }, + "com.unity.modules.wind": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.xr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.subsystems": "1.0.0" + } + } + } +} diff --git a/ProjectSettings/AudioManager.asset b/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000..27287fe --- /dev/null +++ b/ProjectSettings/AudioManager.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 + m_RequestedDSPBufferSize: 0 diff --git a/ProjectSettings/BurstAotSettings_StandaloneWindows.json b/ProjectSettings/BurstAotSettings_StandaloneWindows.json new file mode 100644 index 0000000..2144f6d --- /dev/null +++ b/ProjectSettings/BurstAotSettings_StandaloneWindows.json @@ -0,0 +1,16 @@ +{ + "MonoBehaviour": { + "Version": 3, + "EnableBurstCompilation": true, + "EnableOptimisations": true, + "EnableSafetyChecks": false, + "EnableDebugInAllBuilds": false, + "UsePlatformSDKLinker": false, + "CpuMinTargetX32": 0, + "CpuMaxTargetX32": 0, + "CpuMinTargetX64": 0, + "CpuMaxTargetX64": 0, + "CpuTargetsX32": 6, + "CpuTargetsX64": 72 + } +} diff --git a/ProjectSettings/ClusterInputManager.asset b/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000..e7886b2 --- /dev/null +++ b/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/ProjectSettings/CommonBurstAotSettings.json b/ProjectSettings/CommonBurstAotSettings.json new file mode 100644 index 0000000..3dffdba --- /dev/null +++ b/ProjectSettings/CommonBurstAotSettings.json @@ -0,0 +1,6 @@ +{ + "MonoBehaviour": { + "Version": 3, + "DisabledWarnings": "" + } +} diff --git a/ProjectSettings/DynamicsManager.asset b/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..1596c42 --- /dev/null +++ b/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0.1 + m_ClothInterCollisionStiffness: 0.2 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 0 + m_ReuseCollisionCallbacks: 0 + m_ClothInterCollisionSettingsToggle: 0 + m_ClothGravity: {x: 0, y: -9.81, z: 0} + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 + m_FrictionType: 0 + m_EnableEnhancedDeterminism: 0 + m_EnableUnifiedHeightmaps: 1 + m_SolverType: 0 + m_DefaultMaxAngularSpeed: 50 diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..1c0984a --- /dev/null +++ b/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,14 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: + - enabled: 1 + path: Assets/Scenes/MainMenu.unity + guid: 12157234c67dbe34d896282161c213b6 + - enabled: 1 + path: Assets/Scenes/Stage_1.unity + guid: 35feab57cfbaea048a5dacffd1f9d5b9 + m_configObjects: {} diff --git a/ProjectSettings/EditorSettings.asset b/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..c8da44e --- /dev/null +++ b/ProjectSettings/EditorSettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 2 + m_DefaultBehaviorMode: 0 + m_PrefabRegularEnvironment: {fileID: 0} + m_PrefabUIEnvironment: {fileID: 0} + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp + m_ProjectGenerationRootNamespace: + m_CollabEditorSettings: + inProgressEnabled: 1 + m_EnableTextureStreamingInEditMode: 1 + m_EnableTextureStreamingInPlayMode: 1 + m_AsyncShaderCompilation: 1 + m_EnterPlayModeOptionsEnabled: 0 + m_EnterPlayModeOptions: 3 + m_ShowLightmapResolutionOverlay: 1 + m_UseLegacyProbeSampleCount: 0 + m_AssetPipelineMode: 1 + m_CacheServerMode: 0 + m_CacheServerEndpoint: + m_CacheServerNamespacePrefix: default + m_CacheServerEnableDownload: 1 + m_CacheServerEnableUpload: 1 diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000..49ee382 --- /dev/null +++ b/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,70 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 16 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_VideoShadersIncludeMode: 2 + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_PreloadShadersBatchTimeLimit: -1 + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 11400000, guid: 7b7fd9122c28c4d15b667c7040e3b3fd, + type: 2} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_BrgStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_RenderPipelineGlobalSettingsMap: + UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 18dc0cd2c080841dea60987a38ce93fa, + type: 2} + m_LightsUseLinearIntensity: 1 + m_LightsUseColorTemperature: 1 + m_LogWhenShaderIsCompiled: 0 + m_LightProbeOutsideHullStrategy: 0 + m_CameraRelativeLightCulling: 0 + m_CameraRelativeShadowCulling: 0 diff --git a/ProjectSettings/InputManager.asset b/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..b16147e --- /dev/null +++ b/ProjectSettings/InputManager.asset @@ -0,0 +1,487 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Enable Debug Button 1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: joystick button 8 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Enable Debug Button 2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: backspace + altNegativeButton: + altPositiveButton: joystick button 9 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Reset + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Next + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: page down + altNegativeButton: + altPositiveButton: joystick button 5 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Previous + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: page up + altNegativeButton: + altPositiveButton: joystick button 4 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Validate + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Persistent + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: right shift + altNegativeButton: + altPositiveButton: joystick button 2 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Multiplier + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: joystick button 3 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 2 + axis: 6 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 2 + axis: 5 + joyNum: 0 diff --git a/ProjectSettings/MemorySettings.asset b/ProjectSettings/MemorySettings.asset new file mode 100644 index 0000000..5b5face --- /dev/null +++ b/ProjectSettings/MemorySettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!387306366 &1 +MemorySettings: + m_ObjectHideFlags: 0 + m_EditorMemorySettings: + m_MainAllocatorBlockSize: -1 + m_ThreadAllocatorBlockSize: -1 + m_MainGfxBlockSize: -1 + m_ThreadGfxBlockSize: -1 + m_CacheBlockSize: -1 + m_TypetreeBlockSize: -1 + m_ProfilerBlockSize: -1 + m_ProfilerEditorBlockSize: -1 + m_BucketAllocatorGranularity: -1 + m_BucketAllocatorBucketsCount: -1 + m_BucketAllocatorBlockSize: -1 + m_BucketAllocatorBlockCount: -1 + m_ProfilerBucketAllocatorGranularity: -1 + m_ProfilerBucketAllocatorBucketsCount: -1 + m_ProfilerBucketAllocatorBlockSize: -1 + m_ProfilerBucketAllocatorBlockCount: -1 + m_TempAllocatorSizeMain: -1 + m_JobTempAllocatorBlockSize: -1 + m_BackgroundJobTempAllocatorBlockSize: -1 + m_JobTempAllocatorReducedBlockSize: -1 + m_TempAllocatorSizeGIBakingWorker: -1 + m_TempAllocatorSizeNavMeshWorker: -1 + m_TempAllocatorSizeAudioWorker: -1 + m_TempAllocatorSizeCloudWorker: -1 + m_TempAllocatorSizeGfx: -1 + m_TempAllocatorSizeJobWorker: -1 + m_TempAllocatorSizeBackgroundWorker: -1 + m_TempAllocatorSizePreloadManager: -1 + m_PlatformMemorySettings: {} diff --git a/ProjectSettings/MultiplayerManager.asset b/ProjectSettings/MultiplayerManager.asset new file mode 100644 index 0000000..2a93664 --- /dev/null +++ b/ProjectSettings/MultiplayerManager.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!655991488 &1 +MultiplayerManager: + m_ObjectHideFlags: 0 + m_EnableMultiplayerRoles: 0 + m_StrippingTypes: {} diff --git a/ProjectSettings/NavMeshAreas.asset b/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000..3b0b7c3 --- /dev/null +++ b/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/ProjectSettings/PackageManagerSettings.asset b/ProjectSettings/PackageManagerSettings.asset new file mode 100644 index 0000000..6c6ba77 --- /dev/null +++ b/ProjectSettings/PackageManagerSettings.asset @@ -0,0 +1,37 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + 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: 13964, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_EnablePreReleasePackages: 0 + m_AdvancedSettingsExpanded: 1 + m_ScopedRegistriesSettingsExpanded: 1 + m_SeeAllPackageVersions: 0 + m_DismissPreviewPackagesInUse: 0 + oneTimeWarningShown: 0 + oneTimeDeprecatedPopUpShown: 1 + m_Registries: + - m_Id: main + m_Name: + m_Url: https://packages.unity.com + m_Scopes: [] + m_IsDefault: 1 + m_Capabilities: 7 + m_ConfigSource: 0 + m_UserSelectedRegistryName: + m_UserAddingNewScopedRegistry: 0 + m_RegistryInfoDraft: + m_Modified: 0 + m_ErrorMessage: + m_UserModificationsInstanceId: -894 + m_OriginalInstanceId: -896 + m_LoadAssets: -1 diff --git a/ProjectSettings/Physics2DSettings.asset b/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..6c5cf8a --- /dev/null +++ b/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,56 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 4 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_JobOptions: + serializedVersion: 2 + useMultithreading: 0 + useConsistencySorting: 0 + m_InterpolationPosesPerJob: 100 + m_NewContactsPerJob: 30 + m_CollideContactsPerJob: 100 + m_ClearFlagsPerJob: 200 + m_ClearBodyForcesPerJob: 200 + m_SyncDiscreteFixturesPerJob: 50 + m_SyncContinuousFixturesPerJob: 50 + m_FindNearestContactsPerJob: 100 + m_UpdateTriggerContactsPerJob: 100 + m_IslandSolverCostThreshold: 100 + m_IslandSolverBodyCostScale: 1 + m_IslandSolverContactCostScale: 10 + m_IslandSolverJointCostScale: 10 + m_IslandSolverBodiesPerJob: 50 + m_IslandSolverContactsPerJob: 50 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_CallbacksOnDisable: 1 + m_ReuseCollisionCallbacks: 0 + m_AutoSyncTransforms: 0 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/ProjectSettings/PresetManager.asset b/ProjectSettings/PresetManager.asset new file mode 100644 index 0000000..67a94da --- /dev/null +++ b/ProjectSettings/PresetManager.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_DefaultPresets: {} diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000..3b30e38 --- /dev/null +++ b/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,923 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 26 + productGUID: 8031925009216d3488e5a38e37025e2a + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: SecretRogueLike + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1024 + defaultScreenHeight: 768 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 1 + m_SpriteBatchVertexThreshold: 300 + m_MTRendering: 1 + mipStripping: 0 + numberOfMipsStripped: 0 + numberOfMipsStrippedPerMipmapLimitGroup: {} + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosUseCustomAppBackgroundBehavior: 0 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 1 + androidUseSwappy: 0 + androidBlitType: 0 + androidResizableWindow: 0 + androidDefaultWindowWidth: 1920 + androidDefaultWindowHeight: 1080 + androidMinimumWindowWidth: 400 + androidMinimumWindowHeight: 300 + androidFullscreenMode: 1 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 0 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + dedicatedServerOptimizations: 0 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + useFlipModelSwapchain: 1 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 1 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 1048576 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + switchGpuScratchPoolGranularity: 2097152 + switchAllowGpuScratchShrinking: 0 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + switchNVNGraphicsFirmwareMemory: 32 + switchMaxWorkerMultiple: 8 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + vulkanEnablePreTransform: 1 + vulkanEnableLateAcquireNextImage: 0 + vulkanEnableCommandBufferRecycling: 1 + loadStoreDebugModeEnabled: 0 + bundleVersion: 0.1.0 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + enable360StereoCapture: 0 + isWsaHolographicRemotingEnabled: 0 + enableFrameTimingStats: 0 + enableOpenGLProfilerGPURecorders: 1 + useHDRDisplay: 0 + hdrBitDepth: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + resetResolutionOnWindowResize: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: + Android: com.UnityTechnologies.com.unity.template.urpblank + Standalone: com.Unity-Technologies.com.unity.template.urp-blank + iPhone: com.Unity-Technologies.com.unity.template.urp-blank + buildNumber: + Standalone: 0 + VisionOS: 0 + iPhone: 0 + tvOS: 0 + overrideDefaultApplicationIdentifier: 1 + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 22 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 0 + strictShaderVariantMatching: 0 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 12.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 12.0 + VisionOSSdkVersion: 0 + VisionOSTargetOSVersionString: 1.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSLaunchScreenCustomStoryboardPath: + iOSLaunchScreeniPadCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + macOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + iosCopyPluginsCodeInsteadOfSymlink: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + VisionOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + VisionOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + shaderPrecisionModel: 0 + clonedFromGUID: 3c72c65a16f0acb438eed22b8b16c24a + templatePackageId: com.unity.template.urp-blank@3.0.2 + templateDefaultScene: Assets/Scenes/SampleScene.unity + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 0 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 0 + useCustomGradleSettingsTemplate: 0 + useCustomProguardFile: 0 + AndroidTargetArchitectures: 1 + AndroidTargetDevices: 0 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidEnableArmv9SecurityFeatures: 0 + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 0 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + chromeosInputEmulation: 1 + AndroidMinifyRelease: 0 + AndroidMinifyDebug: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 150 + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: iPhone + m_Icons: + - m_Textures: [] + m_Width: 180 + m_Height: 180 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 120 + m_Height: 120 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 167 + m_Height: 167 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 152 + m_Height: 152 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 76 + m_Height: 76 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 120 + m_Height: 120 + m_Kind: 3 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 80 + m_Height: 80 + m_Kind: 3 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 80 + m_Height: 80 + m_Kind: 3 + m_SubKind: iPad + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 3 + m_SubKind: iPad + - m_Textures: [] + m_Width: 87 + m_Height: 87 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 58 + m_Height: 58 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 29 + m_Height: 29 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 58 + m_Height: 58 + m_Kind: 1 + m_SubKind: iPad + - m_Textures: [] + m_Width: 29 + m_Height: 29 + m_Kind: 1 + m_SubKind: iPad + - m_Textures: [] + m_Width: 60 + m_Height: 60 + m_Kind: 2 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 2 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 2 + m_SubKind: iPad + - m_Textures: [] + m_Width: 20 + m_Height: 20 + m_Kind: 2 + m_SubKind: iPad + - m_Textures: [] + m_Width: 1024 + m_Height: 1024 + m_Kind: 4 + m_SubKind: App Store + - m_BuildTarget: Android + m_Icons: + - m_Textures: [] + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 0 + m_SubKind: + - m_BuildTarget: tvOS + m_Icons: + - m_Textures: [] + m_Width: 1280 + m_Height: 768 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 800 + m_Height: 480 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 400 + m_Height: 240 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 4640 + m_Height: 1440 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 2320 + m_Height: 720 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 3840 + m_Height: 1440 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 1920 + m_Height: 720 + m_Kind: 1 + m_SubKind: + m_BuildTargetBatching: [] + m_BuildTargetShaderSettings: [] + m_BuildTargetGraphicsJobs: [] + m_BuildTargetGraphicsJobMode: [] + m_BuildTargetGraphicsAPIs: + - m_BuildTarget: iOSSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AndroidPlayer + m_APIs: 150000000b000000 + m_Automatic: 0 + m_BuildTargetVRSettings: [] + m_DefaultShaderChunkSizeInMB: 16 + m_DefaultShaderChunkCount: 0 + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + openGLRequireES32: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: + - m_BuildTarget: Android + m_EncodingQuality: 1 + m_BuildTargetGroupHDRCubemapEncodingQuality: + - m_BuildTarget: Android + m_EncodingQuality: 1 + m_BuildTargetGroupLightmapSettings: [] + m_BuildTargetGroupLoadStoreDebugModeSettings: [] + m_BuildTargetNormalMapEncoding: + - m_BuildTarget: Android + m_Encoding: 1 + m_BuildTargetDefaultTextureCompressionFormat: + - m_BuildTarget: Android + m_Format: 3 + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + bluetoothUsageDescription: + macOSTargetOSVersion: 10.13.0 + switchNMETAOverride: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchUseGOLDLinker: 0 + switchLTOSetting: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchCompilerFlags: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchTitleNames_15: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchPublisherNames_15: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchIcons_15: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchSmallIcons_15: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchRatingsInt_12: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 22 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchEnableTouchScreen: 1 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + switchUseNewStyleFilepaths: 0 + switchUseLegacyFmodPriorities: 0 + switchUseMicroSleepForYield: 1 + switchEnableRamDiskSupport: 0 + switchMicroSleepForYieldTime: 25 + switchRamDiskSpaceSize: 12 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 2 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 2 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4AllowPS5Detection: 0 + ps4GPU800MHz: 1 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 + spritePackerPolicy: + webGLMemorySize: 32 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLShowDiagnostics: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 0 + webGLWasmArithmeticExceptions: 0 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLDecompressionFallback: 0 + webGLInitialMemorySize: 32 + webGLMaximumMemorySize: 2048 + webGLMemoryGrowthMode: 2 + webGLMemoryLinearGrowthStep: 16 + webGLMemoryGeometricGrowthStep: 0.2 + webGLMemoryGeometricGrowthCap: 96 + webGLPowerPreference: 2 + scriptingDefineSymbols: + Standalone: MIRROR;MIRROR_79_OR_NEWER;MIRROR_81_OR_NEWER;MIRROR_82_OR_NEWER;MIRROR_83_OR_NEWER;MIRROR_84_OR_NEWER;MIRROR_85_OR_NEWER;MIRROR_86_OR_NEWER;MIRROR_89_OR_NEWER;STEAMWORKS_NET;ODIN_INSPECTOR;ODIN_INSPECTOR_3;ODIN_INSPECTOR_3_1 + additionalCompilerArguments: {} + platformArchitecture: {} + scriptingBackend: {} + il2cppCompilerConfiguration: {} + il2cppCodeGeneration: {} + managedStrippingLevel: + EmbeddedLinux: 1 + GameCoreScarlett: 1 + GameCoreXboxOne: 1 + Nintendo Switch: 1 + PS4: 1 + PS5: 1 + QNX: 1 + Stadia: 1 + VisionOS: 1 + WebGL: 1 + Windows Store Apps: 1 + XboxOne: 1 + iPhone: 1 + tvOS: 1 + incrementalIl2cppBuild: {} + suppressCommonWarnings: 1 + allowUnsafeCode: 0 + useDeterministicCompilation: 1 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 0 + gcWBarrierValidation: 0 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: SecretRogueLike + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: SecretRogueLike + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, + a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + vcxProjDefaultLanguage: + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnhancedXboxCompatibilityMode: 0 + XboxOneEnableGPUVariability: 1 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + XboxOneOverrideIdentityName: + XboxOneOverrideIdentityPublisher: + vrEditorSettings: {} + cloudServicesEnabled: {} + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + hmiPlayerDataPath: + hmiForceSRGBBlit: 1 + embeddedLinuxEnableGamepadInput: 1 + hmiLogStartupTiming: 0 + hmiCpuConfiguration: + apiCompatibilityLevel: 6 + activeInputHandler: 0 + windowsGamepadBackendHint: 0 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + qualitySettingsNames: [] + projectName: + organizationId: + cloudEnabled: 0 + legacyClampBlendShapeWeights: 0 + hmiLoadingImage: {fileID: 0} + platformRequiresReadableAssets: 0 + virtualTexturingSupportEnabled: 0 + insecureHttpOption: 0 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..92cbd95 --- /dev/null +++ b/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 6000.0.42f1 +m_EditorVersionWithRevision: 6000.0.42f1 (feb9a7235030) diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..6238eb7 --- /dev/null +++ b/ProjectSettings/QualitySettings.asset @@ -0,0 +1,136 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 2 + m_QualitySettings: + - serializedVersion: 2 + name: Performant + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + skinWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 11400000, guid: d0e2fc18fe036412f8223b3b3d9ad574, + type: 2} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Balanced + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + skinWeights: 4 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 11400000, guid: e1260c1148f6143b28bae5ace5e9c5d1, + type: 2} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High Fidelity + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + skinWeights: 255 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 4 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 2048 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 11400000, guid: 7b7fd9122c28c4d15b667c7040e3b3fd, + type: 2} + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 1 + CloudRendering: 2 + Lumin: 2 + GameCoreScarlett: 2 + GameCoreXboxOne: 2 + Nintendo Switch: 2 + PS4: 2 + PS5: 2 + Server: 0 + Stadia: 2 + Standalone: 2 + WebGL: 1 + Windows Store Apps: 2 + XboxOne: 2 + iPhone: 1 + tvOS: 1 diff --git a/ProjectSettings/SceneTemplateSettings.json b/ProjectSettings/SceneTemplateSettings.json new file mode 100644 index 0000000..6ed312a --- /dev/null +++ b/ProjectSettings/SceneTemplateSettings.json @@ -0,0 +1,126 @@ +{ + "templatePinStates": [], + "dependencyTypeInfos": [ + { + "userAdded": false, + "type": "UnityEngine.AnimationClip", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.Animations.AnimatorController", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.AnimatorOverrideController", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.Audio.AudioMixerController", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.ComputeShader", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.Cubemap", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.GameObject", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.LightingDataAsset", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.LightingSettings", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Material", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.MonoScript", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicMaterial", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicsMaterial", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicsMaterial2D", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.VolumeProfile", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.SceneAsset", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Shader", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.ShaderVariantCollection", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.Texture", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Texture2D", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Timeline.TimelineAsset", + "defaultInstantiationMode": 0 + } + ], + "defaultDependencyTypeInfo": { + "userAdded": false, + "type": "", + "defaultInstantiationMode": 1 + }, + "newSceneOverride": 0 +} \ No newline at end of file diff --git a/ProjectSettings/ShaderGraphSettings.asset b/ProjectSettings/ShaderGraphSettings.asset new file mode 100644 index 0000000..0beb39a --- /dev/null +++ b/ProjectSettings/ShaderGraphSettings.asset @@ -0,0 +1,18 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + 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: de02f9e1d18f588468e474319d09a723, type: 3} + m_Name: + m_EditorClassIdentifier: + shaderVariantLimit: 2048 + customInterpolatorErrorThreshold: 32 + customInterpolatorWarningThreshold: 16 + customHeatmapValues: {fileID: 0} diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..b00eabb --- /dev/null +++ b/ProjectSettings/TagManager.asset @@ -0,0 +1,52 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 3 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 + m_RenderingLayers: + - Default + - Light Layer 1 + - Light Layer 2 + - Light Layer 3 + - Light Layer 4 + - Light Layer 5 + - Light Layer 6 + - Light Layer 7 diff --git a/ProjectSettings/TimeManager.asset b/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000..558a017 --- /dev/null +++ b/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.33333334 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/ProjectSettings/URPProjectSettings.asset b/ProjectSettings/URPProjectSettings.asset new file mode 100644 index 0000000..08faf03 --- /dev/null +++ b/ProjectSettings/URPProjectSettings.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + 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: 247994e1f5a72c2419c26a37e9334c01, type: 3} + m_Name: + m_EditorClassIdentifier: + m_LastMaterialVersion: 9 diff --git a/ProjectSettings/UnityConnectSettings.asset b/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000..a88bee0 --- /dev/null +++ b/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 1 + m_Enabled: 0 + m_TestMode: 0 + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_DashboardUrl: https://dashboard.unity3d.com + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com + m_Enabled: 0 + m_LogBufferSize: 10 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_TestMode: 0 + m_InitializeOnStartup: 1 + m_PackageRequiringCoreStatsPresent: 0 + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/ProjectSettings/VFXManager.asset b/ProjectSettings/VFXManager.asset new file mode 100644 index 0000000..3a95c98 --- /dev/null +++ b/ProjectSettings/VFXManager.asset @@ -0,0 +1,12 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!937362698 &1 +VFXManager: + m_ObjectHideFlags: 0 + m_IndirectShader: {fileID: 0} + m_CopyBufferShader: {fileID: 0} + m_SortShader: {fileID: 0} + m_StripUpdateShader: {fileID: 0} + m_RenderPipeSettingsPath: + m_FixedTimeStep: 0.016666668 + m_MaxDeltaTime: 0.05 diff --git a/ProjectSettings/VersionControlSettings.asset b/ProjectSettings/VersionControlSettings.asset new file mode 100644 index 0000000..dca2881 --- /dev/null +++ b/ProjectSettings/VersionControlSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!890905787 &1 +VersionControlSettings: + m_ObjectHideFlags: 0 + m_Mode: Visible Meta Files + m_CollabEditorSettings: + inProgressEnabled: 1 diff --git a/ProjectSettings/XRSettings.asset b/ProjectSettings/XRSettings.asset new file mode 100644 index 0000000..482590c --- /dev/null +++ b/ProjectSettings/XRSettings.asset @@ -0,0 +1,10 @@ +{ + "m_SettingKeys": [ + "VR Device Disabled", + "VR Device User Alert" + ], + "m_SettingValues": [ + "False", + "False" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e165284 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# multiplayer-game +sigam diff --git a/steam_appid.txt b/steam_appid.txt new file mode 100644 index 0000000..7ad8022 --- /dev/null +++ b/steam_appid.txt @@ -0,0 +1 @@ +480 \ No newline at end of file